Как получить доступ к модели объединения в has_many:через отношение

StackOverflow https://stackoverflow.com/questions/2283151

Вопрос

У меня типичные отношения "многие ко многим", использующие 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, то мы также фиксируем 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_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 ассоциация.

Другие советы

Похоже, вам следует подумать об использовании вложенных атрибутов:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top