订单有多个不同种类的地址

时间:2016-02-25 19:15:05

标签: ruby-on-rails ruby-on-rails-4

我有订单和地址的模型,并希望订单的每个实例都有一个来自地址表的送货地址和帐单地址。我试图找出设置它的最佳方法,但无法使其发挥作用。

我试过了:

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"

这不起作用,但希望能够了解我想要做的事情。任何指导都将不胜感激。

2 个答案:

答案 0 :(得分:2)

有以下几种方法 -

方法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!

答案 1 :(得分: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">