问候,
我有一个应用程序,其中Companies
and Users
需要通过某种方式彼此归属CompanyMembership
模型,其中包含有关成员资格的额外信息(具体来说,用户是否是公司的管理员,通过布尔值admin
)。代码的简单版本:
class CompanyMembership < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
class Company < ActiveRecord::Base
has_many :company_memberships
has_many :users, :through => :company_memberships
end
class User < ActiveRecord::Base
has_many :company_memberships
has_many :companies, :through => :company_memberships
end
当然,这使得通过以下方式获取公司的所有成员变得很简单company.users.all
,等人。但是,我试图获取公司中作为该公司管理员的所有用户的列表(并测试用户是否是给定公司的管理员)。我的第一个解决方案如下company.rb
:
def admins
company_memberships.where(:admin => true).collect do |membership|
membership.user
end
end
def is_admin?(user)
admins.include? user
end
虽然这有效,但感觉效率低下(它遍历每个成员资格,每次都执行 SQL,对吗?或者 Relation 比这更聪明吗?),我不确定是否有更好的方法来解决这个问题(也许使用范围或奇特的新Relation
Rails 3 使用的对象?)。
任何有关最佳操作方式(最好使用 Rails 3 最佳实践)的建议将不胜感激!
我相信我以错误的方式处理这个问题,指定了条件company_memberships
代替users
,这就是我真正想要的(列表Users
,不是列表CompanyMemberships
)。我想我正在寻找的解决方案是:
users.where(:company_memberships => {:admin => true})
它生成以下 SQL(对于 ID 为 1 的公司):
SELECT "users".* FROM "users"
INNER JOIN "company_memberships"
ON "users".id = "company_memberships".user_id
WHERE (("company_memberships".company_id = 1))
AND ("company_memberships"."admin" = 't')
我还不确定我是否需要它,但是includes()
如有必要,方法将执行预先加载以减少 SQL 查询的数量:
Active Record lets you specify in
advance all the associations that are
going to be loaded. This is possible
by specifying the includes
method of
the Model.find
call. With includes,
Active Record ensures that all of the
specified associations are loaded
using the minimum possible number of
queries.queries. RoR Guides: ActiveRecord Querying http://edgeguides.rubyonrails.org/active_record_querying.html#eager-loading-associations
(我仍然愿意接受任何认为这不是最好/最有效/正确的方法的人的任何建议。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)