Report abuse

domain.rb


			
class Domain < ActiveRecord::Base
  belongs_to :user
  has_many :pages
  has_many :stats do
    def count(*args)
      @owner.rrd_aggregate_page_views.sum :value, *args
    end
  end

  has_many :referers
  has_many :uniques do
    def count(*args)
      @owner.rrd_aggregate_uniques.sum :value, *args
    end
  end

  has_many :rrd_aggregate_page_views, :class_name => 'Rrd::AggregatePageView'
  has_many :rrd_aggregate_uniques,    :class_name => 'Rrd::AggregateUnique', :conditions => ["timespan = ?", 1.day]

rrd/aggregate.rb


			
class Rrd::Aggregate < ActiveRecord::Base
  belongs_to :domain
  @@precision = 1.day

  def self.last_update(domain_id)
    if last = find(:first, :conditions => ['domain_id=?', domain_id], :order => 'time_from desc')
      last.time_from
    end
  end

  # Update the aggregate table with any new data.
  def self.update(domain_id)
    old_count = count(:conditions => ['domain_id=?', domain_id])

    name, day_group_string = case @@precision
    when 1.day
      ["concat( year(created_at), '-', dayofyear(created_at) )", "dayofyear(created_at), year(created_at)"]
    when 1.week
      ["concat( year(created_at), '-', week(created_at), 'w')", "year(created_at), week(created_at)"]
    else
      raise "Precision value not supported"
    end

    connection.execute("
      insert into #{table_name} (timespan, name, value, domain_id, time_from, type)
      select '#{@@precision}', #{name}, count(#{aggregate_table}.id), #{domain_id}, DATE_FORMAT(created_at, '%Y%m%d000000'), '#{self.name.split(":")[-1]}'
      from #{aggregate_table}
      where #{aggregate_table}.domain_id = #{domain_id} and #{aggregate_table}.created_at >= '#{last_update(domain_id)}'
      group by dayofyear(created_at), year(created_at)
    ")    

    count(:conditions => ['domain_id=?', domain_id]) - old_count
  end


  def self.find_with_interpolation(what, args = {})

    # automagically add to an options hash for find
    # todo: extract this to a plugin
    args[:conditions] ||= {}
    case args[:conditions]
    when Hash
      args[:conditions].update( :timespan => @@precision )
    when Array # assumes there ARE conditions
      if args[:conditions][1].is_a?Hash
        args[:conditions][0] << " AND timespan = :rrd_timespan"
        args[:conditions][1].update :rrd_timespan => @@precision
      else
        args[:conditions][0] << " AND timespan = ? "
        args[:conditions] << @@precision
      end
    when String
      args[:conditions] = [args[:conditions] + " AND timespan = ? ", @@precision]
    else
      raise "Cannot determine conditions since conditions is #{args[:conditions].inspect}"
    end

    results = find(what, args)
    return if results.empty?

    first_result = results.shift
    date = first_result.time_from
    ret = [ first_result ]

    # fill in any empty days with a zero.
    results.each do |result|
      missing_days = (result.time_from - date - @@precision) / @@precision
      missing_days.to_i.times do |i|
        new_date = date + (i + 1) * @@precision
        logger.warn "Interpolating #{new_date}"
        ret << self.new(:time_from => new_date, :name => "#{new_date.year}-#{new_date.yday}", :value => '0', :timespan => @@precision)
      end # times 
      ret << result
      date = result.time_from
    end # results
    ret
  end # def

end