如何最好地将地址与rails中的多个模型相关联?

时间:2010-10-13 17:55:46

标签: ruby-on-rails activerecord

关于SO的{p> This question似乎与我的问题有关,但我不确定我的问题是否得到了解答。

一个地址可以属于多个模型(UserProfile和Event) 实现这个的正确方法是什么?

基本表:

user_profiles(id)
events(id)

实施地址表的选项:

  1. addresses(id,user_profile_id,event_id)
    这种方法似乎很麻烦,因为如果明天地址需要属于另一个模型,我必须添加该id字段。
    此外,我还不知道,但添加新的id字段可能会导致一些代码 打破呢?

  2. addresses(id,model_type,model_id)
    这是多态的,对吧。我不知道为什么,但我对此感到警惕?

  3. 其他一些方法吗?

  4. 注意

    我想我可以制作这样的表格,我想:

    user_profiles(id,address_id)
    events(id,address_id)
    

    但是,这意味着相同的address_id可以属于不同的模型。 我想它不应该那样,因为例如说事件的地址需要改变,但它不应该影响user_profile的地址。 所以这就是这样的(我认为这是错误的):

    @current_user_profile.address = some_new_address
    #this would have changed the address for both the user_profile *and* the event
    @current_user_profile.save 
    

2 个答案:

答案 0 :(得分:11)

您错过了一个选项:拥有一个包含常见行为的类,并将字段添加到所有表中。使用composition_of聚合来管理数据。

class Address
  attr_accessor :line1, :line2, :city, :state, :zip

  def initialize(line1, line2, city, state, zip)
    @line1 = line1
  end
end

class UserProfile < ActiveRecord::Base
  composed_of :address, :mapping => %w(line1 line2 city state zip)
end

class Event < ActiveRecord::Base
  composed_of :address, :mapping => %w(line1 line2 city state zip)
end

请参阅Ruby on Rails API文档中的#composed_of

答案 1 :(得分:11)

一种方法是标准的Rails多态:

class Address
  belongs_to :addressable, :polymorphic => true
end

class UserProfile
  has_one address, :as => :addressable
end

class Event
  has_one address, :as => :addressable
end

你可能会有这种唠叨的感觉,就是你无法使用Rails风格的多态关系创建数据库级约束。替代方案(Dan Chak在Enterprise Rails中建议)就像你的#1选项,你确实为每种类型的关系创建了一个单独的id字段。这确实会留下未使用的字段,但它也允许约束。我可以看到两者的论点,但是Rails社区已经使用AR多态性一段时间了,显然取得了很好的成功。我毫不犹豫地使用它。但是,如果这会让你感到烦恼,你可以使用Chak的方法。这是一项更多的工作。 :)

编辑:@ Slick86,迁移看起来像:

class CreateAddresses < ActiveRecord::Migration
  def change
    create_table :addresses do |t|
      t.integer :addressable_id
      t.string :addressable_type
    end
  end
end