Formulário nested de Rails com has_many: through, como editar atributos do modelo de junit?

Como você edita os atributos de um modelo de junit ao usar accept_nested_attributes_for?

Eu tenho 3 modelos: Tópicos e Artigos unidos por Linkers

class Topic  :linkers, :foreign_key => :article_id accepts_nested_attributes_for :articles end class Article  :linkers, :foreign_key => :topic_id end class Linker < ActiveRecord::Base #this is the join model, has extra attributes like "relevance" belongs_to :topic belongs_to :article end 

Então, quando eu construir o artigo na “nova” ação do controlador de tópicos …

 @topic.articles.build 

… e faça o formulário nested em topics / new.html.erb …

  ...fields...  ...fields... 

… Rails cria automaticamente o linker, o que é ótimo. Agora, para minha pergunta: Meu modelo de vinculador também tem atributos que desejo alterar por meio do formulário “novo tópico”. Mas o linker que o Rails cria automaticamente tem valores nulos para todos os seus atributos, exceto topic_id e article_id. Como posso colocar campos para esses outros atributos de vinculador no formulário “novo tópico” para que eles não saiam nulo?

Descobri a resposta. O truque foi:

 @topic.linkers.build.build_article 

Isso cria os vinculadores e cria o artigo para cada vinculador. Então, nos modelos:
topic.rb precisa de accepts_nested_attributes_for :linkers
linker.rb precisa de accepts_nested_attributes_for :article

Então no formulário:

 <%= form_for(@topic) do |topic_form| %> ...fields... <%= topic_form.fields_for :linkers do |linker_form| %> ...linker fields... <%= linker_form.fields_for :article do |article_form| %> ...article fields... 

Quando o formulário gerado pelo Rails é submetido à controller#action Rails, os params terão uma estrutura semelhante a esta (alguns atributos criados adicionados):

 params = { "topic" => { "name" => "Ruby on Rails' Nested Attributes", "linkers_attributes" => { "0" => { "is_active" => false, "article_attributes" => { "title" => "Deeply Nested Attributes", "description" => "How Ruby on Rails implements nested attributes." } } } } } 

Observe como linkers_attributes é, na verdade, um Hash indexado com zero com chaves String e não um Array ? Bem, isso ocorre porque as chaves do campo de formulário que são enviadas para o servidor se parecem com isso:

 topic[name] topic[linkers_attributes][0][is_active] topic[linkers_attributes][0][article_attributes][title] 

Criar o registro agora é tão simples quanto:

 TopicController < ApplicationController def create @topic = Topic.create!(params[:topic]) end end 

Um GOTCHA rápido para quando usar has_one na sua solução. Vou apenas copiar e colar a resposta dada pelo usuário KandadaBoggu neste tópico .


A assinatura do método de build é diferente para as associações has_many e has_many .

 class User < ActiveRecord::Base has_one :profile has_many :messages end 

A syntax de has_many associação has_many :

 user.messages.build 

A syntax de has_one associação has_one :

 user.build_profile # this will work user.profile.build # this will throw error 

Leia a documentação da associação has_one para mais detalhes.

    Intereting Posts