views:

467

answers:

3

I have a model which is generated by parsing a data file. There are several interesting values which are not present in the original data file but can be derived from the ones that are.

However, many of these derived values are expensive to compute, so I would like to store them in the database once they have been computed.

I have tried to this:

def profit
  if not self[:profit]
    update_attribute :profit, expensive_computation
  end
  self[:profit]
end

Unfortunately, that only gets half the job done. The computed value gets stored, but every time I call profit, it computes the value again.

UPDATE:

Turns out the problem was not in the method, but in a find_by_sql statement earlier on that had Rails confused about the id's of the models. The code I ended up with was this:

def profit
  unless read_attribute(:profit)
    update_attribute(:profit, expensive_computation ) 
    self.save!
  end
  read_attribute(:profit)
end
+1  A: 

You create a new method and remove the reading logic from it. Maybe something like this

 def update_profit
    update_attribute :profit, expensive_computation
 end

That way you can separate the reading logic and just use the method to get profit that rails gives you.

 @model.profit

Where @model is an instance of whatever class the attribute profit is in.

vrish88
A: 

Where the code should go is going to depend on when it's possible to calculate the profit (e.g. as soon as the record is first being saved, or will it sometimes be later?), and whether the profit can ever change.

In general it probably be best to put the calculation in some sort of before_create/before_save call that saves it only when it's possible to be calculated and/or has changed

vrish88 is right that you should probably leave the profit method alone unless you really need to calculate this on-the-fly as the data is needed. If that's really what you need, try:

def profit
  update_attribute(:profit, expensive_computation) unless read_attribute(:profit)

  read_attribute(:profit)
end
AdminMyServer
A: 

This works fine for me. My first thought is: do you have a typo in the if not self[:profit] line?

joshuaxls