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.