我使用has_many => :through
拥有典型的多对多关系,详情如下。
class member
has_many member_roles
has_many roles, :through => :member_roles
end
class role
has_many member_roles
has_man members, :through => :member_roles
end
class member_role
belongs_to :member
belongs_to :role
# has following fields: member_id, role_id, scope, sport_id
end
我在这里要做的是允许成员分配角色。每个成员角色都有一个范围,默认情况下设置为“全部”,但如果需要,可以设置为“运动”。如果范围设置为运动,那么我们还捕获sport_id,这允许我们限制对特定运动的角色评估(即,只能管理该运动的团队,而不是每项运动的团队)。听起来很简单。
我设置了update_member_roles
这样的动作:
def update
# Assume we passing a param like: params[:member][:roles]
# as an array of hashes consisting of :role_id and if set, :sport_id
roles = (params[:member] ||= {}).delete "roles"
@member.roles = Role.find_all_by_id(roles.map{|r| r["role_id"]})
if @member.update_attributes params[:member]
flash[:notice] = "Roles successfully updated."
redirect_to member_path(@member)
else
render :action => "edit"
end
end
上面的工作非常好,它设置了相应的member_roles非常好...但是当我正在处理Role模型而不是MemberRole模型时,我有点担心如何访问连接模型设置:scope和:sport_id。
这里的任何指示都会非常感激。
答案 0 :(得分:1)
您应该使用member_roles
关联代替roles
关联。
def update
# The role hash should contain :role_id, :scope and if set, :sport_id
roles = ((params[:member] ||= {}).delete "roles") || []
MemberRole.transaction do
# Next line will associate the :sport_id and :scope to member_roles
# EDIT: Changed the code to flush old roles.
@member.member_roles = roles.collect{|r| MemberRole.new(r)}
# Next line will save the member attributes and member_roles in one TX
if @member.update_attributes params[:member]
# some code
else
# some code
end
end
end
确保将所有内容都包含在一个事务中。
其他可能性是在accepts_nested_attributes_for
关联上使用member_roles
。
答案 1 :(得分:0)
听起来应该考虑使用嵌套属性: