Como acessar o modelo de união em um has_many: através do relacionamento
-
21-09-2019 - |
Pergunta
Eu tenho um relacionamento típico de muitos para muitos usando has_many => :through
, Conforme detalhado abaixo.
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
O que estou tentando fazer aqui é permitir que os membros recebam funções. Cada função de membro tem um escopo, que por padrão está definido como "tudo", mas se desejado, pode ser definido como "esporte". Se o escopo estiver definido para o Sport, também capturamos o Sport_ID, o que nos permite restringir a avaliação desse papel a um esporte específico (ou seja, só poderá gerenciar as equipes desse esporte, em vez das equipes de todos os esportes). Parece bastante simples.
Eu configurei meu update_member_roles
ação algo assim:
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
O exposto acima funciona bem o suficiente, ele define muito bem os membros apropriados ... mas, como estou trabalhando no modelo e não no modelo MemberRole, estou meio que preso sobre como posso acessar o modelo de junção para definir: escopo e: sport_id.
Quaisquer indicadores aqui seriam muito apreciados.
Solução
Você deve usar o member_roles
associação em vez de roles
Associação.
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
Certifique -se de incluir tudo em uma transação.
Outra possibilidade é usar accepts_nested_attributes_for
sobre member_roles
Associação.
Outras dicas
Parece que você deve procurar usar atributos aninhados: