2012年11月2日金曜日

Railsで正規化されていないIDから関連テーブルの情報を取得するサンプル


上図の例のように、正規化せずに一つのテーブル内に複数の外部キーを持った場合に、外部のテーブルの情報を参照(Food.name)するにはどうすれば良いだろうか?

なにはともあれscaffold。(実行結果は省略。)
rails g scaffold food name:string
rails g scaffold person name:string first_favfood_id:integer second_favfood_id:integer third_favfood_id:integer
rake db:migrate
FoodとPersonに適当にデータを入力しておく。



通常は、下記のように参照先のテーブルをblongs_toで指定することになるのだが、
class Person < ActiveRecord::Base
  belongs_to :food
end
こうすると外部キーのIDが、food_idに限定されてしまう。

下記のようにbelongs_toのオプションを指定すると、food_idの外部キーを個別に指定できるようだ。
class Person < ActiveRecord::Base
  belongs_to :first_favfood, :class_name => 'Food', :foreign_key => 'first_favfood_id'
  belongs_to :second_favfood, :class_name => 'Food', :foreign_key => 'second_favfood_id'
  belongs_to :third_favfood, :class_name => 'Food', :foreign_key => 'third_favfood_id'
end
その後、viewのindex.html.erbを下記のように変更すると、Food.nameが参照できるようになった。
<h1>Listing people</h1>

<table>
  <tr>
    <th>Name</th>
    <th>First favfood</th>
    <th>Second favfood</th>
    <th>Third favfood</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @people.each do |person| %>
  <tr>
    <td><%= person.name %></td>
    <td><%= person.first_favfood.name %></td>
    <td><%= person.second_favfood.name %></td>
    <td><%= person.third_favfood.name %></td>
    <td><%= link_to 'Show', person %></td>
    <td><%= link_to 'Edit', edit_person_path(person) %></td>
    <td><%= link_to 'Destroy', person, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Person', new_person_path %>

下記のブログが参考になった。

【Ruby on Rails】1つのテーブルと2フィールドでリレーションを持たせる方法(作成者と最終更新者の情報を持たせる)
http://kagayoshito.com/posts/show/102

1 件のコメント:

  1. 勉強になりました!フレンドを保持するエンティティに、主ユーザIDと、従ユーザIDを持たせる事を検討しておりました。ありがとうございます。

    返信削除