每天一剂Rails良药之具有数据的多对多关系

每天一剂Rails良药之Many to Many Relationships Where the Relationship Itself Has Data

通常我们面临多对多时的处理方法是建立一个关系表,然后has_and_belongs_to_many
如果我们的关系表有其他属性,我们通过声明join table来放置关系表的其他属性
而当关系表本身具有其他属性时,我们可以通过join model来处理
如Magazine和Reader的多对多关系表Subscription:
def self.up

  create_table :magazines do |t|
    t.column :title, :string
  end

  create_table :readers do |t|
    t.column :name, :string
  end

  create_table :subscriptions do |t|
    t.column :magazine_id, :integer
    t.column :reader_id, :integer
    t.column :last_renewal_on, :date
    t.column :length_in_issues, :integer
  end

end

我们建立了magazines、readers和关系表subscriptions的migration,其中关系表中有两个一般属性
然后我们可以这样定义它们三者的model:
class Subscription < ActiveRecord::Base
  belongs_to :magazine
  belongs_to :reader
end

class Magazine < ActiveRecord::Base
  has_many :subscriptions
  has_many :readers, :through => :subscriptions
end

class Reader < ActiveRecord::Base
  has_many :subscriptions
  has_many :magazines, :through => :subscriptions
end

这样我们通过Subscription这个join model建立了Magazine和Reader的多对多关系
magazine = Magazine.create(...)
reader = Reader.create(...)
subscription = Subscription.create(...)
magazine.subscriptions << subscription
reader.subscriptions << subscription
subscription.save

这样我们就保存了一个Subscription对象我们可以通过magazine.readers或者reader.magazines查看关联的对象
我们还可以给出一些has_many的options,例如得到半年的subscribers:
class Magazine < ActiveRecord::Base
  has_many :subscriptions
  has_many :readers, :through => :subscriptions
  has_many :semiannual_subscribers,
           :through => :subscriptions,
           :class_name => "Reader",
           :conditions => ['length_in_issues = 6']
end

这样我们可以通过magazine.semiannual_subscribers来得到半年的subscribers

你可能感兴趣的:(UP,Rails,ActiveRecord)