def define_statistic(name, options)
      method_name = name.to_s.gsub(" ", "").underscore + "_stat"

      @statistics ||= {}
      @filter_all_on ||= ActiveRecord::Base.instance_eval { @filter_all_on }
      @statistics[name] = method_name

      options = { :column_name => :id }.merge(options)

      calculation = options.keys.find {|opt| Statistics::supported_calculations.include?(opt)}
      calculation ||= :count

      # We must use the metaclass here to metaprogrammatically define a class method
      (class<<self; self; end).instance_eval do
        define_method(method_name) do |filters|
          # check the cache before running a query for the stat
          cached_val = Rails.cache.read("#{self.name}#{method_name}#{filters}") if options[:cache_for]
          return cached_val unless cached_val.nil?

          scoped_options = Marshal.load(Marshal.dump(options))

          filters.each do |key, value|
            unless value.nil?
              sql = ((@filter_all_on || {}).merge(scoped_options[:filter_on] || {}))[key].gsub("?", "'#{value}'")
              sql = sql.gsub("%t", "#{table_name}")
              sql_frag = send(:sanitize_sql_for_conditions, sql)
              case
                when sql_frag.nil? then nil
                when scoped_options[:conditions].nil? then scoped_options[:conditions] = sql_frag
                when scoped_options[:conditions].is_a?(Array) then scoped_options[:conditions][0].concat(" AND #{sql_frag}")
                when scoped_options[:conditions].is_a?(String) then scoped_options[:conditions].concat(" AND #{sql_frag}")
              end
            end
          end if filters.is_a?(Hash)

          base = self
          # chain named scopes
          scopes = Array(scoped_options[calculation])
          scopes.each do |scope|
            base = base.send(scope)
          end if scopes != [:all]
          stat_value = base.send(calculation, scoped_options[:column_name], sql_options(scoped_options))

          # cache stat value
          Rails.cache.write("#{self.name}#{method_name}#{filters}", stat_value, :expires_in => options[:cache_for]) if options[:cache_for]

          stat_value
        end
      end
    end
def define_statistic(name, options)
      method_name = name.to_s.gsub(" ", "").underscore + "_stat"

      @statistics ||= {}
      @filter_all_on ||= ActiveRecord::Base.instance_eval { @filter_all_on }
      @statistics[name] = method_name

      options = { :column_name => :id }.merge(options)

      calculation = options.keys.find {|opt| Statistics::supported_calculations.include?(opt)}
      calculation ||= :count

      # We must use the metaclass here to metaprogrammatically define a class method
      (class<<self; self; end).instance_eval do
        define_method(method_name) do |filters|
          # check the cache before running a query for the stat
          cached_val = Rails.cache.read("#{self.name}#{method_name}#{filters}") if options[:cache_for]
          return cached_val unless cached_val.nil?

          scoped_options = Marshal.load(Marshal.dump(options))

          filters.each do |key, value|
            unless value.nil?
              sql = ((@filter_all_on || {}).merge(scoped_options[:filter_on] || {}))[key].gsub("?", "'#{value}'")
              sql = sql.gsub("%t", "#{table_name}")
              sql_frag = send(:sanitize_sql_for_conditions, sql)
              case
                when sql_frag.nil? then nil
                when scoped_options[:conditions].nil? then scoped_options[:conditions] = sql_frag
                when scoped_options[:conditions].is_a?(Array) then scoped_options[:conditions][0].concat(" AND #{sql_frag}")
                when scoped_options[:conditions].is_a?(String) then scoped_options[:conditions].concat(" AND #{sql_frag}")
              end
            end
          end if filters.is_a?(Hash)

          base = self
          # chain named scopes
          scopes = Array(scoped_options[calculation])
          scopes.each do |scope|
            base = base.send(scope)
          end if scopes != [:all]
          stat_value = base.send(calculation, scoped_options[:column_name], sql_options(scoped_options))

          # cache stat value
          Rails.cache.write("#{self.name}#{method_name}#{filters}", stat_value, :expires_in => options[:cache_for]) if options[:cache_for]

          stat_value
        end
      end
    end
OPTIONS:

* +average+, +count+, +sum+, +maximum+, +minimum+ - Only one of these keys is passed, which
   one depends on the type of operation. The value is an array of named scopes to scope the
   operation by (+:all+ should be used if no scopes are to be applied)
* +column_name+ - The SQL column to perform the operation on (default: +id+)
* +filter_on+ - A hash with keys that represent filters. The with values in the has are rules
   on how to generate the query for the correspond filter.
* +cached_for+ - A duration for how long to cache this specific statistic

   Additional options can also be passed in that would normally be passed to an ActiveRecord
   +calculate+ call, like +conditions+, +joins+, etc

 EXAMPLE:

  class MockModel < ActiveRecord::Base

    named_scope :my_scope, :conditions => 'value > 5'

    define_statistic "Basic Count", :count => :all
    define_statistic "Basic Sum", :sum => :all, :column_name => 'amount'
    define_statistic "Chained Scope Count", :count => [:all, :my_scope]
    define_statistic "Default Filter", :count => :all
    define_statistic "Custom Filter", :count => :all, :filter_on => { :channel => 'channel = ?', :start_date => 'DATE(created_at) > ?' }
    define_statistic "Cached", :count => :all, :filter_on => { :channel => 'channel = ?', :blah => 'blah = ?' }, :cache_for => 1.second
  end