开发者

has_many :through -- Adding metadata to the through relationship

开发者 https://www.devze.com 2023-03-29 20:44 出处:网络
I have a need to add metadata about a HABTM relationship. I wanted to use a has_many :through relationship to accomplish this, but it is not necessary. Here is the problem simplified:

I have a need to add metadata about a HABTM relationship. I wanted to use a has_many :through relationship to accomplish this, but it is not necessary. Here is the problem simplified:

class Customer < ActiveRecord::Base
  has_many :customer_teddy_bears
  has_many :teddy_bears, :through => :customer_teddy_bears
end

class CustomerTeddyBear < ActiveRecrod::Base
  belongs_to :customer
  belongs_to :teddy_bear
  attr_accesible :most_favoritest # just to show it exists, boolean
end

class TeddyBear < ActiveRecord::Base
  has_many :cusomter_teddy_bears
end

So what I need to do is start adding teddy bears to my customers, Teddy Bears are a fixed set of data, lets say a fireman_bear, doctor_bear, dominatrix_bear. Any customer can claim to own a kind of teddy bear, but they also specify which is their most开发者_开发知识库 favoritest bear. Since I cannot modify the bears model because that is globally shared among all customers I am adding the metadata (among other metadata) to CustomerTeddyBear.

The problem is that the following does not work.

customer = Customer.new # new record, not yet saved, this must be handled.
customer.teddy_bears << fireman_bear
customer.teddy_bears << doctor_bear
# now to set some metadata
favoritest_record = customer.customer_teddy_bears.select{|ctb| ctb.teddy_bear == doctor_bear}.first
favoritest_record.most_favoritest = true

The above code does not work since customer_teddy_bears entries are only populated during save when creating records in the database. Is there another mechanism for doing this?

If there is nothing "automated" built into rails I will just have to manually manage this relationship by including teddy_bears when I select customer_teddy_bears and using techniques like

def teddy_bears
    self.customer_teddy_bears.map(&:teddy_bear)
end 

along with manually creating the associations, and not using a :through relationship.

please note, all this must happen before the #save is executed on the Customer object, so I need to set all relevant metadata while still in-memory.

Recommendations I got from #RubyOnRails

ctb = customer.customer_teddy_bears.build({:customer => customer, :teddy_bear => fireman_bear})
ctb2 = customer.customer_teddy_bears.build({:customer => customer, :teddy_bear => doctor_bear})
...
ctb.most_favoritest = true


You can simply do this:

customer = Customer.new # new record, not yet saved, this must be handled.
customer.teddy_bears << fireman_bear
customer.teddy_bears << doctor_bear
customer.save

fav = CustomerTeddyBear.where(:customer_id => customer.id, :teddybear_id => doctor_bear.id)
fav.most_favoritest = true
fav.save


The solution I was forced to resort to is manually building the CustomerTeddyBear object and setting both the customer, teddy_bear, and most_favoritest. Basically most of the time, access is by customer.customer_teddy_bears.map(&:teddy_bear) at least in logic where the possibility is that the record is not yet saved, otherwise just short-cut to customer.teddy_bears.

0

精彩评论

暂无评论...
验证码 换一张
取 消