Pregunta

Tengo un típico has_many => :through muchos-a-muchos relación utilizando, como se detalla a continuación.

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

Lo que estoy tratando de hacer aquí es permitir que los miembros sean roles asignados. Cada función miembro tiene un ámbito de aplicación, que por defecto está ajustado a "todos" pero si se desea se puede ajustar a "Sport". Si el alcance se establece en el deporte entonces también capturar el sport_id, lo que nos limitamos a evaluar en ese rol a un deporte en particular (es decir, sólo puede administrar los equipos de ese deporte, en lugar de los equipos de todos los deportes). Suena bastante simple.

He fijado mi acción update_member_roles algo como esto:

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

Lo anterior funciona bastante agradable, que establece los member_roles apropiadas muy bien ... pero como yo estoy trabajando en el modelo de clases, y no el modelo MemberRole estoy un poco atascado en cuanto a cómo puedo tener acceso al modelo de unirse a establecer el: alcance y:. sport_id

Cualquier punteros aquí sería muy apreciada.

¿Fue útil?

Solución

Se debe utilizar la asociación member_roles vez de asociación 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

Asegúrese de que se encierra todo en una sola transacción.

Otra posibilidad es utilizar accepts_nested_attributes_for en asociación member_roles.

Otros consejos

Parece que usted debe buscar en el uso de atributos anidados:

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top