recursos rails formularios form anidados ruby-on-rails join nested nested-forms

ruby-on-rails - anidados - rails formularios



Rails anidado forma con has_many: a través de, cómo editar los atributos de modelo de unión? (3)

¿Cómo se editan los atributos de un modelo de unión cuando se utiliza accept_nested_attributes_for?

Tengo 3 modelos: temas y artículos unidos por Linkers

class Topic < ActiveRecord::Base has_many :linkers has_many :articles, :through => :linkers, :foreign_key => :article_id accepts_nested_attributes_for :articles end class Article < ActiveRecord::Base has_many :linkers has_many :topics, :through => :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

Entonces cuando construyo el artículo en la "nueva" acción del controlador de temas ...

@topic.articles.build

... y hacer la forma anidada en topics / new.html.erb ...

<% form_for(@topic) do |topic_form| %> ...fields... <% topic_form.fields_for :articles do |article_form| %> ...fields...

... Rails crea automáticamente el enlazador, que es genial. Ahora, para mi pregunta: el modelo My Linker también tiene atributos que deseo poder cambiar a través del formulario "nuevo tema". Pero el enlazador que Rails crea automáticamente tiene valores nulos para todos sus atributos, excepto topic_id y article_id. ¿Cómo puedo poner campos para esos otros atributos del enlazador en el formulario "nuevo tema" para que no salgan?


Cuando el formulario generado por Rails se envía a la controller#action Rails, los params tendrán una estructura similar a esta (se agregaron algunos atributos):

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 cómo linkers_attributes es en realidad un Hash índice cero con las teclas String , y no una Array ? Bueno, esto se debe a que las claves de campo de formulario que se envían al servidor se ven así:

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

Crear el registro ahora es tan simple como:

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


Encontré la respuesta. El truco fue:

@topic.linkers.build.build_article

Eso construye los enlazadores, luego construye el artículo para cada enlazador. Entonces, en los modelos:
topic.rb necesita accepts_nested_attributes_for :linkers
linker.rb necesita accepts_nested_attributes_for :article

Luego en la forma:

<%= 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...


Un GOTCHA rápido para cuando uses has_one en tu solución. KandadaBoggu y KandadaBoggu la respuesta dada por el usuario KandadaBoggu en este hilo .

La firma del método de build es diferente para has_one y has_one asociaciones.

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

La sintaxis de compilación para la asociación has_many :

user.messages.build

La sintaxis de has_one para la asociación has_one :

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

Lea la documentation asociación has_one para más detalles.