I’m throwing a topic here to see if anyone has been through a similar situation and see how you sorted it out.
TL;DR Would you use
@attributes_cache for memoizing a dependent object? Would you have a better suggestion?
Imagine you have an
Order model, which inherits from
ActiveRecord::Base. Sometimes you need to run some complex/slow calculation which is performed by another class, you run those calculations with this:
order = Order.find 1 order_metrics = OrderMetrics.new order
Then I can access the metrics by just calling the methods from
order_metrics, for example:
OrderMetrics always requires an order, I find it convenient to provide it as a method of the order. So, in the Order class I implemented the following method:
def metrics OrderMetrics.new self end
So I can call it like this:
But just so it’ll run faster on successive calls, I modified the method implementation to this:
def metrics @metrics ||= OrderMetrics.new self end
But because the metrics depend on the values of the order, I want the metrics object to be discarded if any changes happen in the order. For example:
order = Order.find 1 order.metrics.average_time_per_week # => whatever value order.update_attribute(:created_at, 1.day.ago) order.metrics.average_time_per_week # => this value is no longer valid order.instance_value_set :@metrics, nil order.metrics.average_time_per_week # => this is the correct new value
So this has been my final implementation:
def metrics @attributes_cache[:metrics] ||= OrderMetrics.new self end
I don’t like this solution mainly because I think it’s using Rails’ private API. However I can’t think of a better way to memoize this dependent object and discard it on any update.
Have you ever had a similar problem to this?