我有一个典型的使用has_many => :through
的多对多关系,如下所述。如何通过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非常漂亮......但因为我工作的榜样,而不是MemberRole模型我对我如何访问连接模型以设置:scope和:sport_id感到困惑。
任何指针在这里将不胜感激。
种类。唯一的一点是,如果我更改所选角色,则不会删除旧角色。我想我可以在动作开始时放置@ member.member_roles.destroy_all,但感觉有点像我用大锤来攻击坚果。 – aaronrussell
您可以通过更改代码来删除旧值并分配新值,如下所示: '@member.member_roles = roles.collect {| r | MemberRole.new(r)}' –
我编辑了我的答案来解决您的问题。由于您在'MemberRole'模型中存储了附加信息(除了'member_id'和'role_id'),这是一个合理的方法。 –