在我的应用程序(Rails 4.2.0.rc2)中,用户可以是特定机构的学生或管理员。 :admin_institutions
上的关联User
通过检查联接表中的role
来返回用户管理的所有机构。 :students
上的关联Institution
还会根据institution_users.role
返回该机构中所有学生的用户。
这些关联按预期工作,因此我向:admin_students
添加了一个关联User
,旨在返回给定用户为管理员的所有机构的所有学生。
class InstitutionUser < ActiveRecord::Base
belongs_to :institution
belongs_to :user
end
class Institution < ActiveRecord::Base
has_many :institution_users
has_many :users, :through => :institution_users
has_many :students, -> { where "institution_users.role = 'Student'" }, :through => :institution_users, source: :user
...
end
class User < ActiveRecord::Base
has_many :institution_users
has_many :admin_institutions, -> { where "institution_users.role = 'Admin'" }, through: :institution_users, source: :institution
has_many :admin_students, through: :admin_institutions, source: :students
...
end
但是,:admin_students
无效。它生成以下SQL:
SELECT&#34;用户&#34;。* FROM&#34;用户&#34; INNER JOIN&#34; institution_users&#34; ON&#34;用户&#34;。&#34; id&#34; =&#34; institution_users&#34;。&#34; user_id&#34; INNER JOIN&#34;机构&#34; ON&#34; institution_users&#34;。&#34; institution_id&#34; =&#34;机构&#34;。&#34; id&#34; INNER JOIN&#34; institution_users&#34; &#34; institution_users_admin_students_join&#34; ON&#34;机构&#34;。&#34; id&#34; =&#34; institution_users_admin_students_join&#34;。&#34; institution_id&#34; WHERE&#34; institution_users_admin_students_join&#34;。&#34; user_id&#34; = $ 1 AND(institution_users.role =&#39;学生&#39;)AND(institution_users.role =&#39;管理员&#39;)[[&#34; user_id&#34;,190]]
不是寻找用户是管理员并选择所有学生的所有机构,而是寻找用户同时是学生和管理员的机构,因此它返回一个空集合。
有没有办法写一个关联(而不仅仅是一个方法),它会给我我想要的结果,而不会像我这样的条件冲突?
(旁注:这是这种关联的预期行为吗?如果是这样,我真的很感激进一步了解ActiveRecord为何如此解释它。)
答案 0 :(得分:1)
这可能不是答案,但可能会导致一个。
我不喜欢硬编码SQL的关联:
-> { where "institution_users.role = 'Student'" }
它们肯定至少是问题的一部分,因为ActiveRecord无法解释它们确定将INSTIT_users应用于哪个表别名。
您可以通过引用InsitutionUser模型的类方法来允许ActiveRecord具有灵活性:
def self.students
where(role: "Student")
end
这也将InstitutionUser逻辑保存在一个地方。
然后关联成为:
has_many :students, -> {merge(InstitutionUser.students)}, :through => :institution_users, source: :user
或许可以尝试一下,看看是否可以为你排序,如果没有,它可能会让事情朝着正确的方向发展。