Module: Gricer::ActiveModel::Statistics::ClassMethods

Defined in:
lib/gricer/active_model/statistics.rb

Overview

Gricer’s statistics enhancements for ActiveModel

Extended attribute names

You can use relation attributes by using a dot in your attribute name.

Examples:

For getting the name of the attribute name of Agent associated to the Request:

Gricer::Request.human_attributes('agent.name')

Instance Method Summary collapse

Instance Method Details

#between(from, thru) ⇒ ActiveRecord::Relation/Mongoid::Criteria

Filter records for the time between from and thru

Parameters:

  • from (Date, Time)

    Only get records on or after this point of time

  • thru (Date, Time)

    Only get records before this point of time

Returns:

  • (ActiveRecord::Relation/Mongoid::Criteria)


58
59
60
61
62
63
64
# File 'lib/gricer/active_model/statistics.rb', line 58

def between(from, thru)
  if self.is_active_record?
    self.where("\"#{table_name}\".\"created_at\" >= ? AND \"#{table_name}\".\"created_at\" < ?", from, thru)
  else
    self.where(:created_at.gte => from, :created_at.lt => thru)
  end
end

#between_dates(from, thru) ⇒ ActiveRecord::Relation/Mongoid::Criteria

Filter records for the dates between from and thru

Parameters:

  • from (Date)

    Only get records on or after this date

  • thru (Date)

    Only get records on or before this date

Returns:

  • (ActiveRecord::Relation/Mongoid::Criteria)


70
71
72
# File 'lib/gricer/active_model/statistics.rb', line 70

def between_dates(from, thru)
  self.between(from.to_date.to_time, thru.to_date.to_time+1.day)
end

#count_by(attribute) ⇒ Array

Count records by attribute.

Parameters:

  • attribute (String, Symbol)

    Attribute name to count for. You can use gricers extended attribute names.

Returns:

  • (Array)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/gricer/active_model/statistics.rb', line 105

def count_by(attribute)
  parts = attribute.to_s.split('.')
  
  if self.is_active_record?
    self.grouped_by(attribute).count(:id).sort{ |a,b| b[1] <=> a[1] }
  else
    results = {}
    
    if parts[1].blank?
      scoped.each do |item|
        value = item.send(attribute)
        results[value] ||= 0
        results[value] += 1
      end
    else
      if association = self.reflect_on_association(parts[0].to_sym)          
        scoped.each do |item|
          if item.send(association.name).nil?
            value = nil
          else
            value = item.send(association.name).send(parts[1])
          end
          
          results[value] ||= 0
          results[value] += 1
        end
      else
        raise "Association '#{parts[0]}' not found on #{self.name}"
      end
    end
    
    results.map{ |a,b| [a,b] }.sort{ |a,b| b[1] <=> a[1] }
  end
end

#filter_by(attribute, value) ⇒ ActiveRecord::Relation/Mongoid::Criteria

Filter records by attribute’s value.

Examples:

some_relation.filter('agent.name', 'Internet Explorer').filter('agent.os', 'Windows')

Parameters:

  • attribute (String, Symbol)

    Attribute name to filter. You can use gricers extended attribute names.

  • value

    Attribute value to filter.

Returns:

  • (ActiveRecord::Relation/Mongoid::Criteria)


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/gricer/active_model/statistics.rb', line 148

def filter_by(attribute, value)
  return self if attribute.blank?
  
  #Rails.logger.debug "Attr: #{attribute}, Value: #{value}"
  
  parts = attribute.to_s.split('.')
  if parts[1].blank?
    self.where(attribute => value)
  else
    if association = self.reflect_on_association(parts[0].to_sym)   
      case model_type
        when :ActiveRecord 
          self.includes(association.name)
          .where(association.table_name => {parts[1] => value})
        when :Mongoid
          any_in association.key => association.class_name.constantize.where(parts[1] => value).only(:id).map{|x| x.id}
        else
          raise "Model type '#{model_type}' is not defined for filter_by in Gricer::ActiveModel::Statistics"
      end
    else
      raise "Association '#{parts[0]}' not found on #{self.name}"
    end
  end
end

#grouped_by(attribute) ⇒ ActiveRecord::Relation

Group records by attribute.

Parameters:

  • attribute (String, Symbol)

    Attribute to group the records for. You can use gricers extended attribute names.

Returns:

  • (ActiveRecord::Relation)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/gricer/active_model/statistics.rb', line 78

def grouped_by(attribute)
  parts = attribute.to_s.split('.')
  
  if self.is_active_record?
    if parts[1].blank?
      self.group(attribute)
      .select(attribute)
    else
      if association = self.reflect_on_association(parts[0].to_sym)          
        self.includes(association.name)
        .group("\"#{association.table_name}\".\"#{parts[1]}\"")
        .select("\"#{association.table_name}\".\"#{parts[1]}\"")
      else
        raise "Association '#{parts[0]}' not found on #{self.name}"
      end
    end
  else 
    
    raise "grouped_by not yet implemented for #{model_type}"
        
  end
end

#human_attribute_name(attribute, options = {}) ⇒ String

Extends ActiveModel::Translation#human_attribute_name to use Gricer’s extended attribute names.

Parameters:

  • attribute (String, Symbol)

    Attribute name to get human name for. You can use gricers extended attribute names.

  • options (Hash) (defaults to: {})

    See ActiveModel::Translation for possible options.

Returns:

  • (String)


192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/gricer/active_model/statistics.rb', line 192

def human_attribute_name(attribute, options = {})
  parts = attribute.to_s.split('.')
  if parts[1].blank?
    super attribute, options
  else
    if association = self.reflect_on_association(parts[0].to_sym)
      association.active_record.human_attribute_name parts[1], options
    else
      parts[1].to_s.humanize
    end
  end
  
end

#is_active_record?Boolean

Find out which model type is used in this class

Returns:

  • (Boolean)


42
43
44
# File 'lib/gricer/active_model/statistics.rb', line 42

def is_active_record?
  defined?(::ActiveRecord) and self.ancestors.include? ::ActiveRecord::Base
end

#model_typeObject



46
47
48
49
50
51
52
# File 'lib/gricer/active_model/statistics.rb', line 46

def model_type
  if is_active_record?
    :ActiveRecord
  else
    :Mongoid
  end
end

#stat(attribute, from, thru, step = 1.hour) ⇒ Hash

Return hash for values of an attribute within the given time

Examples:

Get agent.name statistics for 2011-07-05 08:00 until 2011-07-06 08:00

Gricer::Request.stat('agent.name', '2011-07-05 08:00', '2011-07-06 08:00')

Get agent.engine_version statistics for agents with engine_name = ‘Presto’ and values between 2011-07-05 08:00 and last hour with values in 15 minutes steps

Gricer::Request.where('gricer_agents.engine_name = ?', 'Presto').stat('agent.engine_version', '2011-07-05 08:00', Time.now - 1.hour, 15.minutes)

Parameters:

  • attribute (String, Symbol)

    Attribute name to get data for. You can use gricers extended attribute names.

  • from (Date, Time)

    Only get records on or after this point of time

  • thru (Date, Time)

    Only get records before this point of time

  • step (Integer) (defaults to: 1.hour)

    Time interval for grouping values

Returns:

  • (Hash)


219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/gricer/active_model/statistics.rb', line 219

def stat(attribute, from, thru, step = 1.hour)
  #query = self.grouped_by(attribute)
  
  from = from.to_date.to_time
  thru = thru.to_date.to_time+1.day

  now = from

  stats = {}

  while now < thru do
    self.between(now, now + step).count_by(attribute).each do |value|
      stats[value[0]] ||= []
      stats[value[0]] << [now.to_i*1000, value[1]]
    end
    now += step
  end

  return stats
end

#without_nil_in(attribute, options = {}) ⇒ ActiveRecord::Relation/Mongoid::Criteria

Filter out records with nil value in given attribute

Examples:

some_relation.without_nil_in('name')

Parameters:

  • attribute (String, Symbol)

    Attribute name to filter.

Returns:

  • (ActiveRecord::Relation/Mongoid::Criteria)


179
180
181
182
183
184
185
# File 'lib/gricer/active_model/statistics.rb', line 179

def without_nil_in(attribute, options = {})
  if model_type == :Mongoid
    excludes(attribute => nil)
  else
    where("#{attribute} IS NOT NULL")
  end
end