Question

So I have a Vendor model, and a Sale model. An entry is made in my Sale model whenever an order is placed via a vendor.

On my vendor model, I have 3 cache columns. sales_today, sales_this_week, and sales_lifetime.

For the first two, I calculated it something like this:

  def update_sales_today
    today = Date.today.beginning_of_day
    sales_today = Sale.where("created_at >= ?", today).find_all_by_vendor_id(self.id)
    self.sales_today = 0
    sales_today.each do |s|
      self.sales_today = self.sales_today + s.amount
    end 
    self.save    
  end

So that resets that value everytime it is accessed and re-calculates it based on the most current records.

The weekly one is similar but I use a range of dates instead of today.

But...I am not quite sure how to do Lifetime data.

I don't want to clear out my value and have to sum all the Sale.amount for all the sales records for my vendor, every single time I update this record. That's why I am even implementing a cache in the first place.

What's the best way to approach this, from a performance perspective?

Was it helpful?

Solution

I might use ActiveRecord's sum method in this case (docs). All in one:

today = Date.today
vendor_sales = Sale.where(:vendor_id => self.id)

self.sales_today =     vendor_sales.
                        where("created_at >= ?", today.beginning_of_day).
                        sum("amount")

self.sales_this_week = vendor_sales.
                        where("created_at >= ?", today.beginning_of_week).
                        sum("amount")

self.sales_lifetime = vendor_sales.sum("amount")

This would mean you wouldn't have to load lots of sales objects in memory to add the amounts.

OTHER TIPS

You can use callbacks on the create and destroy events for your Sales model:

class SalesController < ApplicationController

    after_save :increment_vendor_lifetime_sales
    before_destroy :decrement_vendor_lifetime_sales

    def increment_vendor_lifetime_sales
        vendor.update_attribute :sales_lifetime, vendor.sales_lifetime + amount
    end

    def decrement_vendor_lifetime_sales
        vendor.update_attribute :sales_lifetime, vendor.sales_lifetime - amount
    end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top