Inheriting data from one model to another


#1

Hello

I’ve been struggling with something for hours that I thought would be
a simple job. Hopefully somebody can shed some light on what I’m
trying to do :o)

First of all I’ll explain what I’m trying to achieve. In a store
application I want to have products and product variations. A product
variation should inherit all of its properties from product unless the
property is defined specifically for the product variation.

Here’s how I’ve tried to implement this: I have a simple Product model
that has various properties such as name and price. I also have
another model, ProductVariation that extends Product using single
table inheritance. ProductVariation adds a belongs_to relationship
that stores the “parent product” - i.e. the one the ProductVariation
overrides.

I’ve managed to get attributes working correctly - if I call
variation.price it uses method_missing() and send() to decide which
value to return.

ProductVariation looks like this:

class ProductVariation < Product
belongs_to :parent_product,
:class_name => “Product”,
:foreign_key => “parent_id”

@@generate_read_methods = false # turn off generating read_methods
otherwise method_missing won’t get called more than once

intercept calls to read attributes. If this instance has

a value return it, otherwise escalate the call to the parent_product

def method_missing(method_id, *args, &block)
method_name = method_id.to_s
if @attributes.include?(method_name)
if !read_attribute(method_name).nil?
puts “Returning #{method_name}”
return read_attribute(method_name)
elsif @parent_product
puts “Escalating #{method_name}”
return @parent_product.send(method_id, *args, &block)
end
end
puts “Passing thru #{method_name}”
super
end
end

My problem is that unless I use the association (by calling
variation.parent_product) before accessing any properties,
@parent_product is nil and the escalation process fails. Is there a
way around this that works inside the model?

I would also like to be able to escalate calls to associations, so if
Product has_many :images, calling variation.images would return its
parent’s images unless is had its own set of images.

I hope I’ve explained this well enough, I’m pretty stumped by it.

Regards,
Simon