0

在has_many:through關聯中,未覆蓋默認範圍(以一種有用的方式)。如何覆蓋has_many:through關聯中的默認範圍?

下面是從模型中的相關的東西:

class User 
    has_one :invitation 
    default_scope where(registered: true) 
end 

class Invitation 
    belongs_to :user, conditions: { registered: [true, false] } 
    belongs_to :program 
end 

class Program 
    has_many :invitations 
    has_many :users, through: :invitations 
end 

通過邀請查找用戶按預期工作。

Invitation.joins(:user) 

產生這樣的:

SELECT `invitations`.* FROM `invitations` INNER JOIN `users` ON `users`.`id` = `invitations`.`user_id` AND `users`.`registered` IN (1, 0) 

鑑於此,我認爲應該Program.last.users找到所有相關用戶,註冊是真還是假。相反,我得到這個:

SELECT `users`.* FROM `users` INNER JOIN `invitations` ON `users`.`id` = `invitations`.`user_id` WHERE `users`.`registered` = 1 AND `invitations`.`program_id` = 52 AND (`users`.`registered` IN (1, 0)) 

這是我期望的SQL。我如何創建一個關聯給我這個?

SELECT `users`.* FROM `users` INNER JOIN `invitations` ON `users`.`id` = `invitations`.`user_id` WHERE `users`.`registered` IN (1, 0) AND `invitations`.`program_id` = 52 

更多內容:我正在使用rails 3.1.3,在此功能需要熄滅之前,升級rails並不是一個可行的選項。擺脫default_scope不是我可以做的事情。

+3

請試試這個 - >'Program.last.users.unscoped'。 –

+0

我知道我可以在關聯的末尾添加其他範圍。我的問題是要讓Program.last.users返回正確的範圍,所以我們不必每次都要把事情弄糟。 – yerdua

+0

此外,'Program.last.users.unscoped'選擇所有用戶,包括那些沒有將它們鏈接到程序的邀請。 – yerdua

回答

0

我能解決這個使用has_and_belongs_to_many關聯。在此關聯上設置的條件將覆蓋用戶的默認範圍。

class Program 
    has_and_belongs_to_many :users, 
          join_table: :invitations, 
          conditions: {registered: [true, false]} 
end 

program.users產生這個SQL:

SELECT `users`.* 
FROM `users` 
INNER JOIN `invitations` 
ON `users`.`id` = `invitations`.`user_id` 
WHERE `invitations`.`program_id` = 111 
AND `users`.`registered` IN (1, 0) 
0
class Program 
    # override association with a method 
    def users 
    Program.joins(:invitation).joins(:users).where('users.registered = true')....ETC 
    end 
end 
+0

我正在嘗試這一個,但因爲它不是一個關聯,所以預加載將不起作用。 'Program.includes(:users).last'會引發錯誤 – yerdua

+0

您將不得不自己編寫SQL。讓用戶函數返回一個範圍,然後添加必要的添加。 (1) – penner

0
@program = Program.last  
@user = @program.users.unscoped.all 
+0

所以,當你想我說的是正確的,你可以投我的答案。而不是像你自己的回答一樣。 –