|
|
|
|
habtm は多対多の関係にある2つのモデルを表現するときに非常に便利です。
|
また、その関係は2つのモデルが各々結合用モデルに対して has_many を持っている構造とも同じです。
|
このように、2つのモデルが多対多の関係を持つ場合、has_many と habtm はどう違うのでしょうか?DB的には、上記の通りどちらもモデル用の2テーブルと結合を表す1テーブルのみで、違いはありません。(主キーはおいといて)。
結局のところ、両者の違いは ActiveRecord が提供してくれるDB操作メソッドだけなのです。
|
|
habtm は「2つのモデル、かつ、関係性のみ」に特化している分、汎用的な has_many に比べると
というメリットがあります。しかし、
といった複雑なケースには不向きです。こういう場合には、結合テーブルをモデルとして表に出したhas_many による構成がよいでしょう。
しかし、
>> berryz = Group.create(:name=>"Berryz工房")
>> maiha = Member.create(:name=>"石村舞波")
# 関係を作成
>> berryz.members << maiha
# 所属メンバーの一覧
>> berryz.members
=> [#<Member:0xb7a9dc9c @attributes={"name"=>"石村舞波", "id"=>"8"}>] |
一度この habtm のエレガントなアクセス方法に慣れてしまうと、
>> berryz = Group.create(:name=>"Berryz工房")
>> maiha = Member.create(:name=>"石村舞波")
# 関係を作成
>> Assign.create(:group=>berryz, :member=>maiha)
# 所属メンバーの一覧
>> berryz.assigns.collect{|assign| assign.member}
=> [#<Member:0xb7a9dc9c @attributes={"name"=>"石村舞波", "id"=>"8"}>] |
has_many で実現された多対多での操作は苦痛です。
現在の svn trunk では、has_many に :through オプションが導入され、このような中間モデル(Assign)を指定することで、habtm のように直接的に対象となる関連モデルを参照可能になりました。
class Group < ActiveRecord::Base has_many :assigns has_many :members, :through=>:assigns end class Member < ActiveRecord::Base has_many :assigns has_many :groups, :through=>:assigns end class Assign < ActiveRecord::Base belongs_to :group belongs_to :member end |
|
# 所属メンバーの一覧
>> berryz.members
=> [#<Member:0xb7a9dc9c @attributes={"name"=>"石村舞波", "id"=>"8"}>] |
現在はまだ参照のみで、追加や削除はまだ habtm の利便性に遠く及びませんが、どんどん機能追加されていくと思います。そして、中間モデル(Assign)は ActiveRecord ですので、好きなように扱うことができます。これは habtm に対する絶対的なメリットでしょう。
ここからは完全に主観と想像ですが、流れというか開発の勢いというか方向性は habtm よりも has_many の方に完全にシフトしている気がします。理由は5つ。
恐らくこれからも has_many :through がさらに機能拡張されていき、Rails 1.2 ぐらいでは、habtm は has_many :through へのマクロになってると予想します。
と、has_many を紹介しておいてなんですが、個人的には habtm のエレガントさにベタ惚れなので、has_many で同等の機能ができる日が来るまで、habtm を愛し続けるつもりです。こっそり「はびたむ」と読んでるくらいラブです。はびたむで気持ちは一杯です。もう habtm MAX Heart です。正直、歌いながら使ってます。(はびったむっ!はびったむっ!はずめにで〜、はびたむ〜、ふ〜たりは〜、はびたむ〜♪)
| JRuby | Rails | Berryz | ℃-ute | エッグ | jQuery |
| 前 | 2006年 1月 |
次 | ||||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| 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 | ||||
vgdj laiht gwkchqjp tyxjleazk tkbx smzfli tifdansj
ここを見て、has_many :throughにassignsを使うようにしたら、test/functionalsでエラーになってしまいました。<br>インスタンス変数のためのメソッドとしてassignsは定義されてるから、モデル名としては使わないほうがいいみたいでした。<br>Rails 1.xのときは気づかなかったので、Rails 2.0からでしょうか?