【问题标题】:How to access the joining model on a has_many :through relationship如何访问 has_many 上的加入模型:通过关系
【发布时间】:2010-02-17 18:01:06
【问题描述】:

我有一个使用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。

这里的任何指针将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord many-to-many has-many-through


    【解决方案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
    

    确保将所有内容都包含在一个事务中。

    其他可能性是在member_roles 关联上使用accepts_nested_attributes_for

    【讨论】:

    • 那种。唯一的事情是,如果我更改所选角色,这不会删除旧角色。我想我可以把@member.member_roles.destroy_all 放在行动的开始,但这感觉有点像我在挥舞着大锤敲碎坚果。
    • 您可以删除旧值并通过更改代码分配新值,如下所示:@member.member_roles = roles.collect{|r| MemberRole.new(r)}
    • 我已编辑我的答案以解决您的问题。由于您将附加信息存储在MemberRole 模型中(除了member_idrole_id),这是一种合理的方法。
    • 谢谢。我昨晚拼凑了类似的东西,虽然你的解决方案更简洁。非常感谢。
    • 如果你不介意再问一个问题,用MemberRole.transaction do 包裹这个实际上能实现什么?
    【解决方案2】:

    听起来你应该考虑使用嵌套属性:

    【讨论】:

    • 您好,感谢您的回答,但说​​实话,我不确定这是否真的有帮助。我看过那些截屏视频,但这里的情况略有不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多