2016-02-25 50 views
0

我有订单和地址的型号,并希望订单的每个实例都具有地址表中的装运和帐单地址。我正在试图找出设置这个的最佳方法,但无法使其正常工作。具有多种不同种类地址的订单

我想:

class Address < ActiveRecord::Base 
    belongs_to :order 
end 

has_one :billing_address, -> { where type: 'billing' }, class_name: "Address" 
has_one :shipping_address, -> { where type: 'shipping' }, class_name: "Address" 

不工作,但希望应该给的什么,我试图做的感觉。任何指导将不胜感激。

+1

的方法是正确的,但不要用'type'您的列名,它被保留用于STI。您可以更改模型的默认STI列,但我更喜欢使用像'address_type'或'context'这样的列名称。另外,为了将来,请避免使用“不工作”这样的句子,而不解释它如何不起作用 - 异常和不当行为之间存在巨大差异。 – BroiSatse

回答

1

这有多种方法如下 -

方法1:使用内置STI(单表继承)机制。

class Order < ActiveRecord::Base 
    has_one :billing_address 
    has_one :shipping_address 
end 

class Address < ActiveRecord::Base 
    belongs_to :order 

    # make sure that there is an `order_id` field 
    # and `type` field on `addresses` table for STI 
end 

class BillingAddress < Address  
end 

class ShippingAddress < Address  
end 

实施例:

order = Order.new 

billing_address = BillingAddress.new(content: '123 doggy lane') 
order.billing_addresss = billing_address 

shipping_address = ShippingAddress.new(content: '123 doggy lane') 
order.shipping_address = shipping_address 

order.save! 

方法2:使用定制STI(单表继承)机制。

class Order < ActiveRecord::Base 
    has_one :billing_address 
    has_one :shipping_address 
end 

class Address < ActiveRecord::Base 
    belongs_to :order 

    # make sure that there is an `order_id` field 
    # and `address_type` field on `addresses` table for custom STI 
    # important note: make sure its `address_type`, not `type` 
    # if it is `type`, rails builtin STI kicks in 

    validates_inclusion_of :address_type, in: ['shipping', 'billing'] 
end 

实施例:

order = Order.new 

billing_address = Address.new(address_type: 'billing', content: '123 doggy lane') 
order.billing_addresss = billing_address 

shipping_address = Address.new(address_type: 'shipping', content: '123 doggy lane') 
order.shipping_address = shipping_address 

order.save! 

方法3:存储在order的地址信息,而不是周围的其他方法。

class Order < ActiveRecord::Base 
    belongs_to :billing_address, class_name: 'Address', foreign_key: 'billing_address_id' 
    belongs_to :shipping_address, class_name: 'Address', foreign_key: 'shipping_address_id' 

    # make sure that there are `billing_address_id` and `shipping_address_id` 
    # fields setup on the `orders` table 
end 

class Address < ActiveRecord::Base 
    has_many :billable_orders, class_name: 'Order', foreign_key: 'billing_address_id' 
    has_many :shippable_orders, class_name: 'Order', foreign_key: 'shipping_address_id' 
end 

例子:

order = Order.new 

billing_address = Address.new(content: '123 doggy lane') 
order.billing_addresss = billing_address 

shipping_address = Address.new(content: '123 doggy lane') 
order.shipping_address = shipping_address 

order.save! 
0

这里是你如何能做到你的要求

迁移

rails g migration CreateOrders 
rails g migration CreateAddresses shipping_id:integer billing_id:integer content:string 
rake db:migrate 

class Order < ActiveRecord::Base 
    has_one :shipping_address, class_name: 'Address', foreign_key: 'shipping_id' 
    has_one :billing_address, class_name: 'Address', foreign_key: 'billing_id' 
end 

class Address < ActiveRecord::Base 
    belongs_to :order 
end 

实施

rails c 

order = Order.create 
address = Address.create(content: '123 doggy lane') 
order.shipping_address = address 
order.billing_address = address 
order.save! 

order.shipping_address 
#=> #<Address id: 1, shipping_id: 1, billing_id: 1, content: "123 doggy lane"> 
order.billing_address 
#=> #<Address id: 1, shipping_id: 1, billing_id: 1, content: "123 doggy lane">