HABTM(はびたむ)

2013-04-21T00:00:00+00:00 Ruby

っていうテーブル構造があったとした場合に、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を使っても出来るっていうのを知った等

RubyOnRails演習 (1) XMLHttpRequestで取得した画像バイナリをJavaScriptでロードする