2017.07 «  - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - - » 2017.09
TOP > DBテーブル間の結びつき その3【has_one とか has_and_belongs_to_many とか】

 ← ERB でのコメントアウト | TOP | DBテーブル間の結びつき その2【belongs_to の方のモデルで出来ること】

スポンサーサイト 

--年--月--日 (--)
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


【広告】

[--.--.--(--) --:--] スポンサー広告 | Trackback(-) | Comment(-)
↑TOPへ

DBテーブル間の結びつき その3【has_one とか has_and_belongs_to_many とか】 

2007年10月30日 ()
DBテーブル間の関係としては、3種類ほどありまして、


ケース1 テーブルAの1レコードに対してテーブルBの1レコードが対応
ケース2 テーブルAの1レコードに対してテーブルBのたくさんのレコードが対応
ケース3 テーブルAのたくさんのレコードに対してテーブルBのたくさんのレコードが対応



とあります。Rails はそれぞれをモデルファイルで指定できます。

前回のエントリの都道府県テーブルと市区町村テーブルは、上記のケース2にあたりますね。

普段のエントリに漏れず、やはり例が分かりやすいと思うので、上記の3ケースの例を書いてみます。

ケース1 都道府県 (1) -> (1) 知事
ケース2 都道府県 (1) -> (たくさん) 市区町村
ケース3 都道府県 (たくさん) <-> (たくさん) 路線




今回は、上記のケース1と、ケース3をナイスカバー(©中山律子 in ザ・スターボウリング)してみたいと思います。

まず、ケース1

前々回作った都道府県テーブルを使用します。それから、新しく知事テーブルを作ります。

知事テーブル governors

+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| prefecture_id | int(11)      | YES  |     | NULL    |                |
| name          | varchar(255) | YES  |     | NULL    |                |
| age           | int(11)      | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+



そしてそして、知事モデルを追加します。

app/models/governor.rb

class Governor < ActiveRecord::Base
 belongs_to :prefecture
end



さらに、都道府県モデルに知事モデルのことを書きます。

app/models/prefecture.rb

class Prefecture < ActiveRecord::Base
  has_many :cities
  has_one :governor
end



じゃあ、これを書いたことで何できるの?というところですが、前回のように、belongs_to 側(知事側)から都道府県の操作をするのはつまんなーいので、都道府県側から知事側を操作します。ほいっ。

pref = Prefecture.find_by_name('東京都')
pref.create_governor(:name => '石原慎太郎', :age => 75)
pref = Prefecture.find_by_name('千葉県')
pref.create_governor(:name => '堂本暁子', :age => 75)
pref = Prefecture.find_by_name('埼玉県')
pref.create_governor(:name => '上田清司', :age => 59)
pref = Prefecture.find_by_name('神奈川県')
pref.create_governor(:name => '松沢成文', :age => 49)



石原さんが結構ご高齢なのですね。テレビでは若く見えます。


次に、ケース3

路線テーブルを作ります。

路線テーブル raillines

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| name        | varchar(255) | YES  |     | NULL    |                |
| train_color | varchar(255) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+




でも、この路線テーブルは、都道府県テーブルに結びつく外部キー prefecture_id を持っとらんですね、そう、このケースは中間テーブルが別に必要なのです。

都道府県-路線テーブル prefectures_raillines
(※1 アルファベット順に2つのテーブル名をつなげること!!)
(※2 auto_incrementのidカラムを作らないこと!!作ってしまうと、Mysql::Error: #23000Duplicate entry エラーがでて主キーが重なるときがある)
↑ちなみに、rake db:migrate では、:id => false を指定します

+---------------+---------+------+-----+---------+----------------+
| Field         | Type    | Null | Key | Default | Extra          |
+---------------+---------+------+-----+---------+----------------+
| prefecture_id | int(11) | YES  |     | NULL    |                |
| railline_id   | int(11) | YES  |     | NULL    |                |
+---------------+---------+------+-----+---------+----------------+



でも、この中間テーブル prefectures_raillines に対しては、モデルはいりません。

路線モデルを新規に追加、そして既存の都道府県モデルに1行書き足すだけでよろしかろう。

路線モデル
app/models/railline.rb

class Railline < ActiveRecord::Base
  has_and_belongs_to_many :prefectures
end



都道府県モデル
app/models/prefecture.rb

class Prefecture < ActiveRecord::Base
  has_many :cities
  has_one :governor
  has_and_belongs_to_many :raillines
end




以上をやりますと、都道府県に対する路線を簡単にDBに挿入できたりします。(その逆も簡単です。)

pref = Prefecture.find_by_name('東京都')
pref.raillines.create(:name => '山手線', :train_color => '緑')
pref.raillines.create(:name => '総武線', :train_color => '黄')
pref = Prefecture.find_by_name('千葉県')
rail = Railline.find_by_name('総武線')
pref.raillines.push(rail) # 千葉県と総武線を結びつける



という訳で、まだまだカバーし足りない部分(:through オプションとか・・・)もあるのですが、そちらは続編を書く気になれば書きますし、リクエストがあれば即書くと思います。(乗せられやすいから)

では、さらばー。

【広告】

[2007.10.30(Tue) 20:58] RubyOnRails(Model)Trackback(0) | Comments(0)
↑TOPへ

 ← ERB でのコメントアウト | TOP | DBテーブル間の結びつき その2【belongs_to の方のモデルで出来ること】

COMMENT

COMMENT POST















管理者にだけ表示

 ← ERB でのコメントアウト | TOP | DBテーブル間の結びつき その2【belongs_to の方のモデルで出来ること】
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。