我有三种模式:
class User < ActiveRecord::Base
has_many :projects, :through => :permissions
class Permission < ActiveRecord::Base
belongs_to :user
belongs_to :project
belongs_to :role
class Project < ActiveRecord::Base
has_many :users, :through => :permissions
通过以上方式获取项目的所有用户非常容易:@project.users
但我想做的是得到这样的结果:获取所有用户项目中的所有用户。
因此,如果用户有3个项目,每个项目有5个用户。我想查询以获取所有用户组中的所有15个用户。
我正在尝试。
current_user.projects.users
但是Rails并不喜欢那么多。 current_user.projects效果很好,但不是用户。
连连呢?想法?谢谢!
更新代码3基于noodl的评论
scope :suggestedContacts, lambda { |user|
users_from_projects = user.projects.reduce([]) {|all_users,prj|
all_users + prj.users
}.uniq
}
错误:
NoMethodError(#的未定义方法`includes_values'):
答案 0 :(得分:3)
我的两个解决方案是:
您可以在用户类中链接您的关系 由于rails 3.0.x尚不支持嵌套的has_many_through,因此您可以使用this插件直到rails 3.1
class User < ActiveRecord::Base
has_many :permissions
has_many :projects, :through => :permissions
has_many :users_in_projects, :through => :projects, :source => :user # chain the relation
class Permission < ActiveRecord::Base
belongs_to :user
belongs_to :project
class Project < ActiveRecord::Base
has_many :users, :through => :permissions
current_user.users_in_projects
另一种方式是急切加载和减少(就像其他答案已经描述的那样,但我会更明确地说明。) 这是更多的工作,更少的依赖。
class User < ActiveRecord::Base
has_many :permissions
has_many :projects, :through => :permissions, :include => :users # eager load users
class Permission < ActiveRecord::Base
belongs_to :user
belongs_to :project
class Project < ActiveRecord::Base
has_many :users, :through => :permissions
current_user.projects.map(&:users).reduce(&:+).uniq_by(&:id)
# returns users in current_user's projects, one query, some computations
答案 1 :(得分:2)
@noodl有正确的想法,但是它确实会导致“一些”开销。除非您谈论拥有数百万个项目和权限,否则您将不会注意到通过优化获得的改进。无论如何,这是一种替代方法,理论上,虽然不是很好,但可以“有效地”为您提供所需的内容(假设您的表格被正确编入索引)。
class User
has_many :project_users, :class_name => "User", :finder_sql => 'select u.* from users u join permissions pp on pp.user_id=u.id join projects p on pp.project_id=p.id where project_id in (select project_id from permissions pp2 where user_id=#{id}) and pp.user_id != #{id} group by u.id'
end
这不是范围,但允许你说:
user = User.find(1)
=> #<User id: 1, name: "Stephen">
user.project_users
=> [#<User id: 2, name: "Kathleen">, #<User id: 3, name: "Anne">]
答案 2 :(得分:1)
由于评论主题有点费力,我会试着说出我是如何直接解决它的。
users = current_user.projects.map(&:users).flatten.uniq
答案 3 :(得分:0)
由于项目是聚合,它将返回Enumerable对象。您可以使用(例如)每个迭代它们:
current_user.projects.each {|prj|
prj.users.each{|usr|
#do stuff
}
}
如果你想将这些收集到一个可枚举(并摆脱重复),那么
users_from_projects = current_user.projects.reduce([]) {|all_users,prj|
all_users = all_users + prj.users
}.uniq
编辑纠正,谢谢你指出它。
答案 4 :(得分:0)
向您的用户类添加:
has_many :users, :through => :permissions
所以它看起来像:
class User < ActiveRecord::Base
has_many :projects, :through => :permissions
has_many :users, :through => :permissions
答案 5 :(得分:-1)
您需要eager-load your associations
class User < ActiveRecord::Base
has_many :projects, :through => :permissions, :include => :users
has_many :permissions, :include => {:project => :users}
…
end