DataMapper でカスタムリレーション

DataMapper - Associations の「Customizing Associations」に書いてある。


User と Message というモデルがあり,Message には宛先が(複数)指定できる,とする。できるだけ規約ベースで書くと以下のようになる。

class User
  include DataMapper::Resource

  property :id, Serial

  has n, :message_receipients
  has n, :messages,
    :through => :message_receipients
end

class Message
  include DataMapper::Resource

  property :id, Serial

  has n, :message_receipients
  has n, :users,
    :through => :message_receipients
end

class MessageReceipient
  include DataMapper::Resource

  property :id, Serial

  belongs_to :user
  belongs_to :message
end

u = User.create
m = Message.new
m.users << u
m.save

p m.users
p u.messages

でもこれだと,「宛先」ぽさとか User の「受信したメッセージ」ぽさの意図がなくなってわかりにくい。

class User
  has n, :message_receipients,
    :child_key => [ :receipient_id ]
  has n, :received_messages, :model => 'Message',
    :through => :message_receipients,
    :via => :message
end

class Message
  has n, :message_receipients
  has n, :receipients, :model => 'User',
    :through => :message_receipients
end

class MessageReceipient
  belongs_to :receipient, :model => 'User'
  belongs_to :message
end

u = User.create
m = Message.new
m.receipients << u
m.save

p m.receipients
p u.received_messages

要するに :child_key とか (今回は使ってないけど) :parent_key とか :via などのオプションを使えば,リレーション時にどのような外部キーを使うかなどをカスタマイズできる。

新規開発だけでなくレガシースキーマを相手にする場合にも。

まぁ ORM でリレーションまでやってしまうかどうかという問題もあるけど。