Sql 在分配给父模型期间向联接模型添加属性
我有以下设置: Schema.rbSql 在分配给父模型期间向联接模型添加属性,sql,ruby-on-rails,ruby,ruby-on-rails-3,activerecord,Sql,Ruby On Rails,Ruby,Ruby On Rails 3,Activerecord,我有以下设置: Schema.rb ActiveRecord::Schema.define(version: 20130923235150) do create_table "addresses", force: true do |t| t.datetime "created_at" t.datetime "updated_at" end create_table "user_addresses", force: true do |t| t.integer
ActiveRecord::Schema.define(version: 20130923235150) do
create_table "addresses", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "user_addresses", force: true do |t|
t.integer "user_id"
t.integer "address_id"
t.string "purpose"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
end
User.rb:
class User < ActiveRecord::Base
has_one :user_address
has_one :primary_shipping_address, through: :user_address, class_name: :UserAddress, source: :address
has_one :primary_billing_address, through: :user_address, class_name: :UserAddress, source: :address
end
如何才能使其适用于新的和持久化记录?。我已经提出了90%的解决方案,但由于我的方法没有抓住一个边缘案例,在一些随机规范上出现了突破
要解决的最棘手的部分是关联=
的行为:在新记录上,它通过联接模型将关联排队等待分配
注:我省略了
has_one
关系上的条件,我将使用这些关系来获取我想要的地址。我认为这个问题与此无关。首先,关联有点不一致,primary\u shipping\u address
和primary\u billing\u address
将返回相同的地址。你可以把它改成
class User < ActiveRecord::Base
has_many :user_addresses # user can have multiple addresses one for shipping and one for billing
has_one :primary_shipping_address,
through: :user_address, class_name: :UserAddress,
source: :address, :conditions => ['user_addresses.purpose = ?','shipping']
has_one :primary_billing_address,
through: :user_address, class_name: :UserAddress,
source: :address, :conditions => ['user_addresses.purpose = ?','billing']
end
选项2:创建自定义方法(我更喜欢这种方法,因为它更干净干燥)
我想您需要定义一个before_save方法来检查账单地址的设置,并适当地设置目的?我如何知道要分配哪个目的?
class UserAddress < ActiveRecord::Base
belongs_to :user
belongs_to :address
end
irb(main):013:0> u = User.new
=> #<User id: nil, created_at: nil, updated_at: nil>
irb(main):014:0> a = Address.create
=> #<Address id: 3, created_at: "2013-09-24 00:13:07", updated_at: "2013-09-24 00:13:07">
irb(main):015:0> u.primary_billing_address = a
=> #<Address id: 3, created_at: "2013-09-24 00:13:07", updated_at: "2013-09-24 00:13:07">
irb(main):016:0> u.save!
=> true
irb(main):017:0> u.user_address
=> #<UserAddress id: 2, user_id: 3, address_id: 3, purpose: nil, created_at: "2013-09-24 00:13:18", updated_at: "2013-09-24 00:13:18">
(not what I want... purpose should be "billing")
class User < ActiveRecord::Base
has_many :user_addresses # user can have multiple addresses one for shipping and one for billing
has_one :primary_shipping_address,
through: :user_address, class_name: :UserAddress,
source: :address, :conditions => ['user_addresses.purpose = ?','shipping']
has_one :primary_billing_address,
through: :user_address, class_name: :UserAddress,
source: :address, :conditions => ['user_addresses.purpose = ?','billing']
end
# alias is needed to refer to original method
alias_method :orig_primary_billing_address=, :primary_billing_address=
def primary_billing_address=(obj)
self.orig_primary_billing_address = obj
self.user_addresses.where("address_id = ?", obj.id).update_attribute(:purpose, 'billing')
end
# repeat for shipping
def save_address_with_purpose(obj,purpose)
self.send("primary_#{purpose}_address=", obj)
self.user_addresses.where("address_id = ?", obj.id).update_attribute(:purpose, purpose)
end