HABTM(はびたむ)
っていうテーブル構造があったとした場合に、RailsというかActiveRecordに中間モデルを用いて多対多を用いる方法として、:throughを用いてやるケースっていうのがあると思うのですが
とりあえずRailsまでは必要なくActiveRecord単体を使って検証してみる
require "active_record"
require "pp"
class Category < ActiveRecord::Base
has_one :entry_category
def self.table_name
"category"
end
end
class Entry < ActiveRecord::Base
has_many :category, :through => :entry_category
has_many :entry_category
def self.table_name
"entry"
end
end
class EntryCategory < ActiveRecord::Base
belongs_to :entry
belongs_to :category
def self.table_name
"entry_category"
end
end
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "knowdb"
);
pp Entry.find(555).category
entry = Entry.new
entry.title = "hoge";
entry.content = "hoge";
entry.category.push Category.find(15)
entry.category.push Category.find(36)
entry.save()
:throughを使って中間モデルを使って参照を紐付ける方法がある。インスタンスを作って参照にぶち込むだけで勝手にINSERTとかやってくれるっていうのをRailsとかでは良くあるケースだと思うのですが、has_and_belongs_to_many(通称 HABTM)を使う事でも出来る模様
require "active_record"
require "pp"
class Category < ActiveRecord::Base
has_and_belongs_to_many :entry, :join_table => "entry_category"
def self.table_name
"category"
end
end
class Entry < ActiveRecord::Base
has_and_belongs_to_many :category, :join_table => "entry_category"
def self.table_name
"entry"
end
end
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "knowdb"
);
pp Entry.find(555).category
entry = Entry.new
entry.title = "hoge";
entry.content = "hoge";
entry.category.push Category.find(15)
entry.category.push Category.find(36)
entry.save()
今回は
- Entryクラスが参照するテーブルがentriesではない
- Categoryクラスが参照するテーブルがcategoriesではない
- 上記により、参照を中間するテーブル名はActiveRecordが意図するのとは異なる為に:join_tableによるJOINするテーブル名の指定が必要
っていう事なんかなと。とりまぁこういうケースの場合はhas_and_belongs_to_manyを使っても出来るっていうのを知った等