Rails2.3 の Nested Attributes の機能を試してみました。
rails 2.3 のインストール
rails 2.3 は以下のようにしてインストールしました。
sudo gem install rails --source http://gems.rubyonrails.org
アプリケーションの作成
アプリケーションを作り、モデルをいくつか作成します。
% rails nested_attributes_sample % cd nested_attributes_sample % script/generate model book title:string % script/generate model author name:string book_id:integer % script/generate model page text:text book_id:integer % rake db:migrate
モデルファイルに関連の情報を書きます。
app/models/book.rb
class Book < ActiveRecord::Base has_one :author has_many :pages accepts_nested_attributes_for :author accepts_nested_attributes_for :pages, :allow_destroy => true end
accepts_nested_attributes_for メソッドを呼び出しているところがポイントです。
これにより author と pages に対して Nested Attributes の機能が使えるようになります。
さらに pages に関しては :allow_destroy => true とすることで親(Book)から削除できるようにしています。
app/models/author.rb
class Author < ActiveRecord::Base belongs_to :book end
app/models/page.rb
class Page < ActiveRecord::Base belongs_to :book end
確認
script/console でちゃんと動作するか確認してみます。
% script/console
One-to-one
まずはデータの作成。
>> book = Book.create({:title => 'ruby book', :author_attributes => {:name => 'foo'}})
>> book.author.name
=> "foo"
ちゃんと book.author が作成されてますね!
次にデータの更新。
>> book.update_attributes({:author_attributes => {:name => 'jugyo'}})
>> book.author.name
=> "jugyo"
ちゃんと更新されてますね!
One-to-many
次は「一対多」の場合のデータ作成のやり方です。
こんなふうにします。
>> book = Book.create({
:title => 'rails book',
:pages_attributes => {
'new_1' => {:text => 'aaaaaaaaa'},
'new_2' => {:text => 'bbbbbbbbb'},
'new_3' => {:text => 'ccccccccc'},
}
})
>> book.pages.size
=> 3
>> book.pages[0].text
=> "aaaaaaaaa"
おお、ちゃんとできてるっぽい!
page に対応する 各 Hash のキーは 'new' という文字列から始まっている必要があるようです。
データを更新してみます。
>> book.attributes = {:pages_attributes => {1 => {:text => 'AAAAAAA'}}}
>> book.pages[0].text
=> "AAAAAAA"
データを削除してみます。
>> book.attributes = {:pages_attributes => {1 => {'_delete' => '1'}}}
>> book.save
>> book.pages.size
=> 3
ん?、book.pages.size が 3 のままですね。
でも DB を見てみるとちゃんと削除されてたのでとりあえずはよしとします。
参考URL:
http://weblog.rubyonrails.org/2009/1/26/nested-model-forms
http://api.rubyonrails.com/classes/ActiveRecord/NestedAttributes/ClassMethods.html
