我正在开发一个包含模型User
和Project
的应用,User
可以通过Project
分配给多个ProjectUser
,有角色(例如开发人员,设计师)。
Project
has_many :project_users
has_many :users, :through => :project_users
User
has_many :project_users
has_many :projects, :through => :project_users
ProjectUser (user_id, project_id, role)
belongs_to :user
belongs_to :project
我可以致电@project.users
和@user.projects
,但由于角色各不相同,我希望对这些关系更加具体。理想情况下,我希望能够做到以下几点:
@project.developers
# returns @project.users, but only where ProjectUser.role = 'Developer'
@project.designers << @user
# creates a ProjectUser for @project, @user with role 'Designer'
@user.development_projects
# returns projects where @user is assigned as a 'Developer'
@user.design_projects << @project
# creates a ProjectUser for @project, @user with role 'Designer'
我目前有以下代码:
has_many :developers, :through => :project_users, :source => :user,
:class_name => "User",
:conditions => ['project_users.role = ?','Developer']
但这只是单向提取,并没有给我太多其他的东西 - 我无法建立或分配任何东西。
我正在尝试一些我认为可能有用的更复杂的逻辑,但我会欣赏一些指示:
has_many :developer_assignments, :source => :project_user,
:conditions => { :role => 'Developer' }
has_many :developers, :through => :developer_assignments # class_name?
有什么建议吗?谢谢!
答案 0 :(得分:12)
has_many
接受一个可以定义/覆盖关联方法的块。这将允许您为<<
创建自定义方法。我为你创建了一个小例子,你可以用类似的方式创建构建。
# Project.rb
has_many :developers, :through => :project_users, :source => :user,
:conditions => "project_users.role = 'developer'" do
def <<(developer)
proxy_owner.project_users.create(:role => 'developer', :user => developer)
end
end
现在,您可以根据要求使用@project.developers << @user
向项目中添加新的开发人员。 @project.developers
为您提供所有开发人员。
如果您有很多角色,那么动态创建这些has_many语句可能会很有用。
# Project.rb
ROLES = ['developer','contractor']
ROLES.each do |role|
self.class_eval <<-eos
has_many :#{role.downcase}s, :through => :project_users, :source => :user,
:conditions => "project_users.role = '#{role}'" do
def <<(user)
proxy_owner.project_users.create(:role => '#{role}', :user => user)
end
end
eos
end
回顾上面的所有内容似乎不是做事的方式。确定范围可以使构建和创建命令成为可能,而无需重新定义所有内容。
希望这有帮助!
答案 1 :(得分:1)
听起来你正在寻找的是RoR single table inheritance和named scopes的组合。
请查看以下article以获取有关多态关联的一个很好的示例。这可以帮助您实现以下目标:
@project.developers
# returns @project.users, but only where ProjectUser.role = 'Developer'
@project.designers << @user
# creates a ProjectUser for @project, @user with role 'Designer'
范围将为您提供实施@user.development_projects
的简洁方法,但获取<<
运算符可能需要更多技巧。
答案 2 :(得分:0)
您尝试使用scopes了吗?它不会让你做&lt;&lt;但它简化了查询。
<强>尝试:强>
Project
scope :developers, lambda {
includes(:project_users).where("project_users.role = ?", "developer")
}
您将能够让所有开发人员使用:@project.developers