update dynamic fields automatically in database

I'm working on a shopping cart application and I've run into a design
question:

I have a field in the cart_lines table called total_price. That field
is really just a calculated field based on qty and unit_price. If
either of those values change, total_price should also be updated.

The way that makes the most sense to me is to write a method called
total_price that defines how it should be calculated rather than
modify the value directly from both the qty= and unit_price= methods.
The problem is, I want that value stamped in the database so I can use
it as a condition or sort field in queries.

I've written the following code (which works fine) that loops through
the object's attributes, checks to see if a method exists with the
same name, and updates the value if it's different:

class CartLine < ActiveRecord::Base
  before_save :recalculate

  def total_price
    qty * unit_price
  end

  def recalculate
    attributes.each do |attribute_name, attribute_value|
      if respond_to_without_attributes? attribute_name
        method_value = send(attribute_name)
        send(attribute_name + "=", method_value) if method_value !=
attribute_value
      end
    end
  end
end

That's fine and it works well but I'm wondering if I'm missing
something or there's a simpler way to handle this since I'm going to
have to reuse that code all over the place. If not, I could just
refactor it to a plugin but I'd be surprised since it sounds like it
would be a common situation.

How would you handle this? Any ideas or insight would be appreciated.
Thanks!

jaystotz wrote:

I've written the following code (which works fine) that loops through
the object's attributes, checks to see if a method exists with the
same name, and updates the value if it's different:

I'm wondering if you need all of that. When you save a record in Rails all the attributes are put in the update statement (not just the ones changed). So can't you just define total_price how you have and since total_price is a real field in the database it should get qty * unit_price without any callback. I think.... I haven't tried it myself. :slight_smile:

Eric

You know, I assumed the same thing which led me to this question. But
it turns out the values used in the update statement are based on the
values in the internal @attributes hash, not the results of method
calls. Defining a method named total_price does not affect the value
used in the update statement.