Come accedere al modello che unisce su un has_many: attraverso la relazione
-
21-09-2019 - |
Domanda
Ho un tipico molti-a-molti con has_many => :through
, come dettagliato di seguito.
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
Quello che sto cercando di fare qui è consentire ai membri di essere ruoli assegnati. Ogni ruolo membro ha una portata, che di default è impostata su "All", ma se lo si desidera può essere impostato su "Sport". Se il campo di applicazione è impostato allo sport, allora abbiamo anche catturare l'sport_id, che ci permette di valutare limitiamo a quel ruolo per uno sport particolare (cioè, in grado di gestire solo le squadre di che lo sport, piuttosto che le squadre di tutti gli sport). Suona abbastanza semplice.
Ho installato la mia azione update_member_roles
qualcosa di simile:
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
È possibile che questo funziona abbastanza bello, imposta le member_roles appropriate molto bene ... ma come sto lavorando sul modello di ruolo e non il modello MemberRole Sono un po 'bloccato da come posso accedere al modello a unirsi a impostare il: portata e:. sport_id
Tutti gli indicatori qui sarebbe molto apprezzato.
Soluzione
Si consiglia di utilizzare l'associazione member_roles
invece di associazione 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
Assicurati di racchiudere tutto in un'unica transazione.
Altra possibilità è quella di utilizzare accepts_nested_attributes_for
riguardante l'associazione member_roles
.
Altri suggerimenti
Sembra che si dovrebbe guardare in utilizzando attributi nidificati: