Railsで多対多のモデル
去年からずーっとこの課題でひっ掛かっている。
Mail -> MailUser <- Userのモデルを考えてみる。
スキーマは以下
create_table "mail_users", :force => true do |t| t.boolean "active" t.integer "user_id" t.integer "mail_id" t.datetime "created_at" t.datetime "updated_at" end create_table "mails", :force => true do |t| t.string "title" t.text "comment" t.date "write_date" t.datetime "created_at" t.datetime "updated_at" end create_table "users", :force => true do |t| t.string "name" t.string "email" t.datetime "created_at" t.datetime "updated_at" end
modelは以下
class Mail < ActiveRecord::Base # has_many for user through mail_user has_many :mail_user has_many :user, :through=>:mail_user # nested attribute accepts_nested_attributes_for :mail_user end class User < ActiveRecord::Base # has_many for user through mail_user has_many :mail_user has_many :mail, :through=>:mail_user # nested attribute accepts_nested_attributes_for :mail_user end class MailUser < ActiveRecord::Base belongs_to :mail belongs_to :user end
それぞれをscaffoldで作成してmigrateでDBを作成して、テスト用のデータを登録して。
さて、MailのShow画面で、関連するユーザ名を表示する画面に挑戦。
まずは、Show画面でMailUserのindex画面を表示する事から。
partialを使うので、view/mail/show.html.erbを
<p> <b>Title:</b> <%=h @mail.title %> </p> <p> <b>Comment:</b> <%=h @mail.comment %> </p> <p> <b>Write date:</b> <%=h @mail.write_date %> </p> ここから <div id="mail_users"> <%= render :partial=>"mail_user_index", :locals=>{:mail_users=>@mail.mail_user} %> </div> ここまでを追加 <%= link_to 'Edit', edit_mail_path(@mail) %> | <%= link_to 'Back', mails_path %>
と修正して
view/mail_user/index.html.erbをview/mail/_mail_user_index.html.erbにコピーして
<h1>Listing mail_users</h1> <table> <tr> <th>Active</th> <th>User</th> <th>Mail</th> </tr> <% mail_users.each do |mail_user| %> @mail_usersをmail_usersに変更 <tr> <td><%=h mail_user.active %></td> <td><%=h mail_user.user_id %></td> <td><%=h mail_user.mail_id %></td> <td><%= link_to 'Show', mail_user %></td> <td><%= link_to 'Edit', edit_mail_user_path(mail_user) %></td> <td><%= link_to 'Destroy', mail_user, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New mail_user', new_mail_user_path %>
このままでは、User_IDとMail_IDを表示する事は出来ても、ユーザ名が表示できないので、以下のように修正
<table> <tr> <th>Active</th> <th>User Name</th> <th> Address</th> </tr> <% mail_users.each do |mail_user| %> @mail_usersをmail_usersに変更 <tr> <td><%=h mail_user.active %></td> <td><%=h mail_user.user.name %></td> <- belongs_to でuserと連携できる <td><%=h mail_user.user.email %></td> <- のでuser.nameとuser.emailを参照 <td><%= link_to 'Show', mail_user %></td> <td><%= link_to 'Edit', edit_mail_user_path(mail_user) %></td> <td><%= link_to 'Destroy', mail_user, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table>