6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/periodic_counter.rb', line 6
def initialize(environment, root)
@db, @log, @mail = ActiveWrapper.setup(
:base => root,
:env => environment
)
@db.establish_connection
@tables = ActiveRecord::Base.connection.tables.inject({}) do |hash, table|
hash[table] = ActiveRecord::Base.connection.columns(table).collect(&:name)
hash
end
if File.exists?(counters_yml = "#{root}/config/counters.yml")
@counters = YAML::load(File.open(counters_yml))
else
raise "#{counters_yml} not found"
end
@counters.each do |table, counters|
columns = @tables[table]
if columns
columns.each do |column|
if counters.include?(column)
period = columns.select do |col|
col =~ /^#{column}/ &&
col != column &&
!col.include?('_data')
end
select_columns = [ 'id', column, "#{column}_data" ]
select_columns += period
records = ActiveRecord::Base.connection.select_all <<-SQL
SELECT #{select_columns.join(', ')}
FROM #{table}
SQL
records.each do |record|
id = record.delete('id')
data = YAML::load(record["#{column}_data"] || '') || {}
count = record.delete(column).to_i
period.each do |col|
computed_at = data["#{col}_at"] || Time.now.utc
duration = column_to_period_integer(col)
time_since_compute = Time.now.utc - computed_at
last_day =
if col.include?('day')
self.class.today
elsif col.include?('week')
self.class.last_monday
elsif col.include?('month')
self.class.first_of_the_month
end
if (time_since_compute - duration) >= 0
data[col] = count
data["#{col}_at"] = last_day
else
data[col] ||= count
data["#{col}_at"] ||= last_day
end
record[col] = count - data[col].to_i
end
record["#{column}_data"] = "'#{YAML::dump(data)}'"
set = record.collect { |col, value| "#{col} = #{value || 0}" }
ActiveRecord::Base.connection.update <<-SQL
UPDATE #{table}
SET #{set.join(', ')}
WHERE id = #{id}
SQL
end
end
end
end
end
end
|