[Rails] Inheriting data from one model to another

Simon King
Mon, 10 Apr 2006 21:08:49 -0000

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