【问题标题】:How best to associate an Address to multiple models in rails?如何最好地将地址与 Rails 中的多个模型相关联?
【发布时间】:2011-04-25 00:00:39
【问题描述】:

This question 上的 SO 似乎与我的问题有关,但我不确定我的问题是否得到回答。

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

基本表:

user_profiles(id)
events(id)

实现addresses表的选项:

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

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

  3. 其他方法可以做到这一点?

注意

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

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 

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    您错过了一个选项:拥有一个包含常见行为的类并将字段添加到所有表中。使用 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

    【讨论】:

    • 学到了新东西,谢谢!但我认为它不适合我目前的需要,但它可以在将来帮助我做其他事情。
    【解决方案2】:

    一种方法是标准 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
    

    【讨论】:

    • 我无法确定关于此的迁移。它会是什么样子?
    • 如何为每个模型设置多个地址类型。例如,一个事件可以有一个行人地址和一个停车地址?
    猜你喜欢
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 2018-01-05
    相关资源
    最近更新 更多