気づいたらRails2.3RC1が出てました。 こないだ2.2がでたばかりなのに、忙しいですね。。
http://guides.rubyonrails.org/2_3_release_notes.html
Nested Object Formsという機能が追加されていまして、 その名前の通り、入れ子状態のモデルのフォームを作るための機能らしいです。
親モデルのフォーム内で、子モデルの編集を展開できるようにするのは、いままでだとちょっと面倒だったので願ったり叶ったりですね。
gem を最新の状態に
rackが0.9以上じゃないとダメだと怒られたので、アップデートしておきましょう
# rackを最新版にしておきます
sudo gem install rack
# 僕は念のために全部updateしました
sudo gem update
sudo gem install rack
# 僕は念のために全部updateしました
sudo gem update
プロジェクト作成
railsのプロジェクトを作って、最新版でフリーズする
$ rails nested_sample
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
$ cd nested_sample
$ rake rails:freeze:edge
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
$ cd nested_sample
$ rake rails:freeze:edge
scaffold
ToDoリストの簡単なアプリをScaffoldします
% script/generate scaffold user name:string
exists app/models/
exists app/controllers/
exists app/helpers/
....
% script/generate scaffold todo user_id:integer title:string due:date is_finish:boolean
exists app/models/
exists app/controllers/
exists app/helpers/
...
% rake db:migrate
(in /Users/haga/Desktop/nested_sample)
exists app/models/
exists app/controllers/
exists app/helpers/
....
% script/generate scaffold todo user_id:integer title:string due:date is_finish:boolean
exists app/models/
exists app/controllers/
exists app/helpers/
...
% rake db:migrate
(in /Users/haga/Desktop/nested_sample)
モデルで関連を設定する
- Userにhas_many :todos
- Todoにbelongs_to :user
を設定する。 その際にaccepts_nested_attributes_forというメソッドを使ってNested Object Formsを利用できるようにしておくこと。
% emacs app/models/user.rb
class User < ActiveRecord::Base
has_many :todos
accepts_nested_attributes_for :todos, :allow_destroy => true
end
class User < ActiveRecord::Base
has_many :todos
accepts_nested_attributes_for :todos, :allow_destroy => true
end
% emacs app/models/todo.rb
class Todo < ActiveRecord::Base
belongs_to :user
end
class Todo < ActiveRecord::Base
belongs_to :user
end
Userモデルのフォームを変更
app/views/user/edit.html.erbを変更します。 fields_forを使って、子todoをeachしていますね。
<h1>Editing user</h1>
<% form_for(@user) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<ol>
<% f.fields_for :todos do |todo_form| %>
<li>
<p>
<%= todo_form.label :title %><br />
<%= todo_form.text_field :title %>
</p>
<p>
<%= todo_form.label :due %><br />
<%= todo_form.date_select :due %>
</p>
<p>
<%= todo_form.label :is_finish %><br />
<%= todo_form.check_box :is_finish %>
</p>
</li>
<% end %>
</ol>
<p>
<%= f.submit "Update" %>
</p>
<% end %>
<%= link_to 'Show', @user %> |
<%= link_to 'Back', users_path %>
<% form_for(@user) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<ol>
<% f.fields_for :todos do |todo_form| %>
<li>
<p>
<%= todo_form.label :title %><br />
<%= todo_form.text_field :title %>
</p>
<p>
<%= todo_form.label :due %><br />
<%= todo_form.date_select :due %>
</p>
<p>
<%= todo_form.label :is_finish %><br />
<%= todo_form.check_box :is_finish %>
</p>
</li>
<% end %>
</ol>
<p>
<%= f.submit "Update" %>
</p>
<% end %>
<%= link_to 'Show', @user %> |
<%= link_to 'Back', users_path %>
script/consoleでユーザーとToDoを追加
ちょっとずるして、script/consoleでユーザーとToDoの準備をば
$ script/console
>> u = User.create :name => 'func09'
=> #<user id: 2, name: "func09", created_at: "2009-02-02 04:11:11", updated_at: "2009-02-02 04:11:11">
>> u.todos.create :title => "test 1", :due => 2.day.since, :is_finish => false
=> #<todo id: 3, user_id: 2, title: "test 1", due: "2009-02-04 04:13:01", is_finish: false, created_at: "2009-02-02 04:13:01", updated_at: "2009-02-02 04:13:01">
>> u.todos.create :title => "test 2", :due => 1.day.ago, :is_finish => true
=> #<todo id: 4, user_id: 2, title: "test 2", due: "2009-02-01 04:13:13", is_finish: true, created_at: "2009-02-02 04:13:13", updated_at: "2009-02-02 04:13:13">
>> u = User.create :name => 'func09'
=> #<user id: 2, name: "func09", created_at: "2009-02-02 04:11:11", updated_at: "2009-02-02 04:11:11">
>> u.todos.create :title => "test 1", :due => 2.day.since, :is_finish => false
=> #<todo id: 3, user_id: 2, title: "test 1", due: "2009-02-04 04:13:01", is_finish: false, created_at: "2009-02-02 04:13:01", updated_at: "2009-02-02 04:13:01">
>> u.todos.create :title => "test 2", :due => 1.day.ago, :is_finish => true
=> #<todo id: 4, user_id: 2, title: "test 2", due: "2009-02-01 04:13:13", is_finish: true, created_at: "2009-02-02 04:13:13", updated_at: "2009-02-02 04:13:13">
確認
できた!!
関連記事
