2010-02-02 23 views
102

¿Cómo editas los atributos de un modelo de unión cuando usas accept_nested_attributes_for?Rails anidados con has_many: a través de, ¿cómo editar los atributos del modelo join?

tengo 3 modelos: Temas y artículos unidos por enlazadores

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 

Así que cuando construyo el artículo en el "nuevo" acción del controlador de temas ...

@topic.articles.build 

.. .y hacer la forma anidada en los temas/new.html.erb ...

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

... rieles crea automáticamente el enlazador, que i es grandioso. Ahora para mi pregunta: Mi modelo de enlazador también tiene atributos que quiero 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?

+3

que estoy tratando de hacer lo mismo usted está, solo en una acción nueva/crear ... Me pregunto si podría compartir las acciones de su controlador. Quiero crear un "Usuario" a través de una "Cuenta" usando una "Relación" como un "enlazador" ... pero no puedo entender cómo se verán las acciones nuevas y creadas ... ¿te importaría? ? – Mohamad

+0

https://robots.thoughtbot.com/accepts-nested-attributes-for-has- many-through – zx1986

Respuesta

89

Encontré la respuesta. El truco era:

@topic.linkers.build.build_article 

que construye los enlazadores, entonces construye el artículo para cada enlazador. Así, en los modelos:
topic.rb necesita accepts_nested_attributes_for :linkers
linker.rb necesita accepts_nested_attributes_for :article

A continuación, 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... 
+13

Avíseme si esto fue útil – Arcolye

+13

Actualización de Rails 3: form_for y field_for need <%= %> en lugar de <% %> si Estoy usando Rails 3. – Arcolye

+0

Agregaría códigos backticks alrededor de los dos accept_nested_attributes_for líneas que ha agregado. Me perdí esa información varias veces mientras escaneaba el código, una vez que lo leí a fondo, capté ese detalle perdido y resolvió mi problema. ¡Gracias! –

3

Una rápida GOTCHA al utilizar has_one en su solución. Copiaré y pegaré la respuesta dada por el usuario KandadaBoggu en this thread.


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

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

La sintaxis para la construcción has_many asociación:

user.messages.build 

La sintaxis para la construcción has_one asociación:

user.build_profile # this will work 

user.profile.build # this will throw error 

Leer la asociación has_onedocumentation para más detalles.

6

Cuando el formulario generado por los rieles se somete a los rieles controller#action, el params tendrá una estructura similar a esto (algunos formados por atributos añadidos):

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 indexados a cero Hash con String claves, y no un Array?Bueno, esto se debe a que las claves de campos de formulario que se envían al servidor aspecto:

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

Crear el registro es ahora tan simple como:

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

No estoy seguro, pero creo que se ha asumido todo el tiempo con 'accept_nested_attributes_for' – Arcolye

+2

@Arcolye - Encontrar esta información en Internet para una asociación como esta fue tan dolorosa en ese momento - tal vez mi google-fu fue ese día. Quería al menos documentarlo aquí ya que, como mi compañero de trabajo, asumí que los rieles convertían linked_attributes a una matriz, en lugar de un hash indexado cero. Con suerte, este bocado ayuda a alguien en el futuro :) –

Cuestiones relacionadas