Los rieles se forman con tres modelos y espacios de nombres
-
07-07-2019 - |
Pregunta
Golpeando mi cabeza contra esta por mucho tiempo. En Rails 2.3.2, Ruby 1.9.1.
Intentando usar un formulario para crear tres objetos que tengan estas relaciones:
class Person
has_one :goat
end
class Goat
belongs_to :person
has_many :kids
end
class Goat::Kid
belongs_to :goat
end
Aquí hay un resumen del esquema:
Person
first_name
last_name
Goat
name
color
Goat::Kid
nickname
age
Me gustaría que mi acción #create
instaure nuevas instancias de los tres modelos con las asociaciones especificadas. Sin embargo, aunque parece que mi hash de params se está pasando al controlador como debería (según los registros de seguimiento en el navegador cuando explota), el objeto Goat :: Kid
no está recopilando el params.
irb (irb session es solo una representación psuedo de lo que estoy tratando de lograr, por lo que si no llama a #save!
o cualquier otra necesidad, en realidad no está destinado a ser correcto. Estoy tratando de hacer esto a través del navegador / formulario web).
a = Person.new :first_name => 'Leopold', :last_name => 'Bloom'
b = Goat.new :name => 'Billy', :color => 'white'
c = Goat::Kid.new :nickname => 'Jr.', :age => 2
a.goat.kids
>> []
Ahora, no puedo entender cómo hacer que la vista pase los parámetros a cada objeto y que el controlador guarde estos parámetros en la base de datos.
Mis preguntas: A) ¿es este un buen lugar para usar nested_attributes_for
y, de ser así, ¿cómo declaro eso con un espacio de nombres? B) ¿hay una manera mucho más simple y fácil de entender para hacer esto?
Pasar parámetros a tres modelos ha sido muy desafiante para mí y no importa cuánta documentación lea, no puedo entenderlo ( #form_for
y #fields_for ). El espacio de nombres lo complica aún más. ¡Gracias por cualquier ayuda!
Anexo: si termino declarando
accepts_nested_attributes_for
¿Cuál es la forma correcta de usar el argumento de símbolo para un modelo de espacio de nombres?
accepts_nested_attributes_for :kids, :through => :goats
o
accepts_nested_attributes_for :goats_kids, :through => :goats
o
accepts_nested_attributes_for :goats::kids, :through => :goats
No estoy seguro de cómo se traducen los modelos con espacios de nombres a sus identificadores de símbolos. Gracias!
Solución
Bueno, esta es la primera vez que juego con accept_nested_attributes_for
, pero con un poco de juego pude conseguir que algo funcionara.
Primero la configuración del modelo:
class Person < ActiveRecord::Base
has_one :goat
accepts_nested_attributes_for :goat
end
class Goat < ActiveRecord::Base
belongs_to :person
has_many :kids
accepts_nested_attributes_for :kids
end
class Goat::Kid < ActiveRecord::Base
belongs_to :goat
end
Con un controlador simple y reparador:
ActionController::Routing::Routes.draw do |map|
map.resources :farm
end
class FarmController < ApplicationController
def new
end
def create
person = Person.new params[:person]
person.save
render :text => person.inspect
end
end
Luego viene la forma semi-compleja:
A continuación, la configuración del formulario:
<% form_for :person, :url => farm_index_path do |p| %>
<%= p.label :first_name %>: <%= p.text_field :first_name %><br />
<%= p.label :last_name %>: <%= p.text_field :last_name %><br />
<% p.fields_for :goat_attributes do |g| %>
<%= g.label :name %>: <%= g.text_field :name %><br />
<%= g.label :color %>: <%= g.text_field :color %><br />
<% g.fields_for 'kids_attributes[]', Goat::Kid.new do |k| %>
<%= k.label :nickname %>: <%= k.text_field :nickname %><br />
<%= k.label :age %>: <%= k.text_field :age %><br />
<% end %>
<% end %>
<%= p.submit %>
<% end %>
Al mirar la fuente de accept_nested_attributes_for
, parece que creará un método para usted llamado # {attr_name} _attributes =
, por lo que necesitaba configurar mi < code> fields_for para reflejar eso (Rails 2.3.3). A continuación, haga que has_many: kids
trabaje con accept_nested_attributes_for
. El método kids_attributes =
estaba buscando una matriz de objetos, por lo que necesitaba especificar la asociación de la matriz en el formulario manualmente y decirle a fields_for
qué tipo de modelo usar.
Espero que esto ayude.