Rails の場合はSQLを直接使わないので、下図のような1対多の関係を設定するにはどうすれば良いのだろうか?
まずはRails付属のSQLiteのSQLでやってみる。
E:\Sites\mytest\db>sqlite3 development.sqlite3
SQLite version 3.7.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table team(id, name);
sqlite> create table member(id, team_id, name);
sqlite> insert into team values(1, 'team1');
sqlite> insert into member values(1, 1, 'member1');
sqlite> insert into member values(2, 1, 'member2');
▽データの取得
sqlite> select team.id, team.name, member.id, member.name from team, member wher
e team.id = member.team_id;
1|team1|1|member1
1|team1|2|member2
こんな感じで、簡単にできる。(外部キーは未設定。)
Rails の ActiveRecord では、references という型を指定することで、他のクラスへの外部参照を設定できるようである。
まずは sacffold を作成してみる。
先程作成したテーブルと同じ名前のテーブルは作成できないので、rteam と rmember で作成する。(長いので実行結果は省略。)
rails g scaffold rteam name:string
rails g scaffold rmember name:string rteam:references
Rmember のクラスには、"belongs_to :rteam" という属性が追加されている。
class Rmember < ActiveRecord::Base
belongs_to :rteam
end
Rmember のクラスは何も変更されていない。
"has_many :rmember" を手動で追加する必要があるようだ。
▽修正前
class Rteam < ActiveRecord::Base
end
▽修正後
class Rteam < ActiveRecord::Base
has_many :rmembers
end
修正後にデータベースの Migration を実行。
E:\Sites\mytest>rake db:migrate
== AddThirdnameOnecolumnmodel: migrating =====================================
-- add_column(:onecolumnmodels, :thirdname, :string)
-> 0.0020s
== AddThirdnameOnecolumnmodel: migrated (0.0020s) ============================
== CreateRteams: migrating ===================================================
-- create_table(:rteams)
-> 0.1510s
== CreateRteams: migrated (0.1520s) ==========================================
== CreateRmembers: migrating =================================================
-- create_table(:rmembers)
-> 0.0020s
-- add_index(:rmembers, :rteam_id)
-> 0.0350s
== CreateRmembers: migrated (0.0390s) ========================================
db/schema.rb を見ると、rteam_id が rmembers テーブルに追加されている。
index も追加されているようだ。
create_table "rmembers", :force => true do |t|
t.string "name"
t.integer "rteam_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "rmembers", ["rteam_id"], :name => "index_rmembers_on_rteam_id"
create_table "rteams", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
自動生成されたテストデータを読み込でおく。
E:\Sites\mytest>rake db:fixtures:load
rails consoleから、Rteamクラスのデータを確認してみる。
現時点では、Rteam に関連付けられた Rmember は空の状態。
E:\Sites\mytest>rails console
Loading development environment (Rails 3.2.1)
irb(main):001:0> rteam1=Rteam.find(980190962)
=> #<Rteam id: 980190962, name: "MyString", created_at: "2012-10-02 04:13:28", u
pdated_at: "2012-10-02 04:13:28">
irb(main):002:0> rteam1.rmembers
=> []
rmembers の配列に Rmember から値を抽出して追加。
irb(main):003:0> rteam1.rmembers << Rmember.find(980190962)
=> [#<Rmember id: 980190962, name: "MyString", rteam_id: 980190962, created_at:
"2012-10-02 04:13:28", updated_at: "2012-10-02 05:52:04">]
Rmember 側の rteam_id も自動で追加された。
irb(main):005:0> rteam1.rmembers
=> [#<Rmember id: 980190962, name: "MyString", rteam_id: 980190962, created_at:
"2012-10-02 04:13:28", updated_at: "2012-10-02 05:52:04">]