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

所以,当你想我说的是正确的,你可以投我的答案。而不是像你自己的回答一样。 –