3つのモデルと名前空間を持つRailsフォーム
-
07-07-2019 - |
質問
長い間、これに頭をぶつける。 Rails 2.3.2、Ruby 1.9.1で。
1つのフォームを使用して、これらの関係を持つ3つのオブジェクトを作成しようとしています:
class Person
has_one :goat
end
class Goat
belongs_to :person
has_many :kids
end
class Goat::Kid
belongs_to :goat
end
スキーマの概要は次のとおりです。
Person
first_name
last_name
Goat
name
color
Goat::Kid
nickname
age
#create
アクションで、指定された関連付けを持つ3つのモデルすべての新しいインスタンスをインスタンス化したい。ただし、パラメータハッシュが必要に応じてコントローラに渡されているように見えますが(ブラウザが爆発したときのバックトレースログに基づいて)、 Goat :: Kid
オブジェクトは収集していませんparams。
irb(irbセッションは、私が達成しようとしていることの単なる擬似表現であるため、 #save!
またはその他の必需品を呼び出していない場合、それは本当に正しいことを意味しません。私はこれをすべてブラウザ/ウェブフォームで実行しようとしています。)
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
>> []
今、私はビューを取得して各オブジェクトにパラメータを渡す方法と、これらのパラメータをデータベースに保存するコントローラを取得する方法を理解できません。
私の質問:A)これは nested_attributes_for
を使用するのに適した場所です。 B)これを行うためのもっと簡単で理解しやすい方法はありますか?
パラメータを3つのモデルに渡すことは私にとって非常に困難であり、どんなに多くのドキュメントを読んでも頭を包むことはできません( #form_for
および #fields_for コード>)。名前空間はこれをさらに複雑にします。助けてくれてありがとう!
補遺:宣言することになった場合
accepts_nested_attributes_for
名前空間付きモデルにシンボル引数を使用する適切な方法は何ですか?
accepts_nested_attributes_for :kids, :through => :goats
または
accepts_nested_attributes_for :goats_kids, :through => :goats
または
accepts_nested_attributes_for :goats::kids, :through => :goats
名前空間付きモデルがどのようにシンボル識別子に変換されるかわかりません。ありがとう!
解決
まあ、これは accepts_nested_attributes_for
で遊ぶのは初めてですが、少し遊んでみると、何かを動かすことができました。
最初のモデル設定:
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
単純な安らかなコントローラーを使用する場合:
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
次に、準複雑な形式があります:
次に、フォームのセットアップ:
<% 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 %>
accepts_nested_attributes_for
のソースを見ると、#{attr_name} _attributes =
というメソッドが作成されているように見えるため、< code> fields_for でそれを反映します(Rails 2.3.3)。次に、 accepts_nested_attributes_for
と連携する has_many:kids
を取得します。 kids_attributes =
メソッドはオブジェクトの配列を探していたので、フォームの配列の関連付けを手動で指定し、使用するモデルのタイプを fields_for
に伝える必要がありました。
これがお役に立てば幸いです。