periodic_calculations 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +120 -0
- data/MIT-LICENSE +20 -0
- data/README.md +8 -0
- data/Rakefile +24 -0
- data/lib/periodic_calculations/base.rb +36 -0
- data/lib/periodic_calculations/engine.rb +5 -0
- data/lib/periodic_calculations/lazy_query.rb +36 -0
- data/lib/periodic_calculations/query.rb +136 -0
- data/lib/periodic_calculations/query_options.rb +61 -0
- data/lib/periodic_calculations/version.rb +3 -0
- data/lib/periodic_calculations.rb +11 -0
- data/periodic_calculations.gemspec +28 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/activity.rb +2 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +23 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +20 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20131203172849_create_activities.rb +9 -0
- data/spec/dummy/db/schema.rb +26 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/model_spec.rb +82 -0
- data/spec/periodic_calculations/lazy_query_spec.rb +38 -0
- data/spec/periodic_calculations/query_options_spec.rb +82 -0
- data/spec/periodic_calculations/query_spec.rb +211 -0
- data/spec/spec_helper.rb +6 -0
- metadata +227 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
periodic_calculations (0.0.1)
|
5
|
+
rails (>= 3.2)
|
6
|
+
railties
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (4.0.1)
|
12
|
+
actionpack (= 4.0.1)
|
13
|
+
mail (~> 2.5.4)
|
14
|
+
actionpack (4.0.1)
|
15
|
+
activesupport (= 4.0.1)
|
16
|
+
builder (~> 3.1.0)
|
17
|
+
erubis (~> 2.7.0)
|
18
|
+
rack (~> 1.5.2)
|
19
|
+
rack-test (~> 0.6.2)
|
20
|
+
activemodel (4.0.1)
|
21
|
+
activesupport (= 4.0.1)
|
22
|
+
builder (~> 3.1.0)
|
23
|
+
activerecord (4.0.1)
|
24
|
+
activemodel (= 4.0.1)
|
25
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
26
|
+
activesupport (= 4.0.1)
|
27
|
+
arel (~> 4.0.0)
|
28
|
+
activerecord-deprecated_finders (1.0.3)
|
29
|
+
activesupport (4.0.1)
|
30
|
+
i18n (~> 0.6, >= 0.6.4)
|
31
|
+
minitest (~> 4.2)
|
32
|
+
multi_json (~> 1.3)
|
33
|
+
thread_safe (~> 0.1)
|
34
|
+
tzinfo (~> 0.3.37)
|
35
|
+
arel (4.0.1)
|
36
|
+
atomic (1.1.14)
|
37
|
+
builder (3.1.4)
|
38
|
+
coveralls (0.7.0)
|
39
|
+
multi_json (~> 1.3)
|
40
|
+
rest-client
|
41
|
+
simplecov (>= 0.7)
|
42
|
+
term-ansicolor
|
43
|
+
thor
|
44
|
+
diff-lcs (1.2.5)
|
45
|
+
docile (1.1.1)
|
46
|
+
erubis (2.7.0)
|
47
|
+
hike (1.2.3)
|
48
|
+
i18n (0.6.5)
|
49
|
+
mail (2.5.4)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.25.1)
|
53
|
+
minitest (4.7.5)
|
54
|
+
multi_json (1.8.2)
|
55
|
+
pg (0.15.1)
|
56
|
+
polyglot (0.3.3)
|
57
|
+
rack (1.5.2)
|
58
|
+
rack-test (0.6.2)
|
59
|
+
rack (>= 1.0)
|
60
|
+
rails (4.0.1)
|
61
|
+
actionmailer (= 4.0.1)
|
62
|
+
actionpack (= 4.0.1)
|
63
|
+
activerecord (= 4.0.1)
|
64
|
+
activesupport (= 4.0.1)
|
65
|
+
bundler (>= 1.3.0, < 2.0)
|
66
|
+
railties (= 4.0.1)
|
67
|
+
sprockets-rails (~> 2.0.0)
|
68
|
+
railties (4.0.1)
|
69
|
+
actionpack (= 4.0.1)
|
70
|
+
activesupport (= 4.0.1)
|
71
|
+
rake (>= 0.8.7)
|
72
|
+
thor (>= 0.18.1, < 2.0)
|
73
|
+
rake (10.1.0)
|
74
|
+
rest-client (1.6.7)
|
75
|
+
mime-types (>= 1.16)
|
76
|
+
rspec-core (2.14.7)
|
77
|
+
rspec-expectations (2.14.4)
|
78
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
79
|
+
rspec-mocks (2.14.4)
|
80
|
+
rspec-rails (2.14.0)
|
81
|
+
actionpack (>= 3.0)
|
82
|
+
activesupport (>= 3.0)
|
83
|
+
railties (>= 3.0)
|
84
|
+
rspec-core (~> 2.14.0)
|
85
|
+
rspec-expectations (~> 2.14.0)
|
86
|
+
rspec-mocks (~> 2.14.0)
|
87
|
+
simplecov (0.8.2)
|
88
|
+
docile (~> 1.1.0)
|
89
|
+
multi_json
|
90
|
+
simplecov-html (~> 0.8.0)
|
91
|
+
simplecov-html (0.8.0)
|
92
|
+
sprockets (2.10.1)
|
93
|
+
hike (~> 1.2)
|
94
|
+
multi_json (~> 1.0)
|
95
|
+
rack (~> 1.0)
|
96
|
+
tilt (~> 1.1, != 1.3.0)
|
97
|
+
sprockets-rails (2.0.1)
|
98
|
+
actionpack (>= 3.0)
|
99
|
+
activesupport (>= 3.0)
|
100
|
+
sprockets (~> 2.8)
|
101
|
+
term-ansicolor (1.2.2)
|
102
|
+
tins (~> 0.8)
|
103
|
+
thor (0.18.1)
|
104
|
+
thread_safe (0.1.3)
|
105
|
+
atomic
|
106
|
+
tilt (1.4.1)
|
107
|
+
tins (0.13.1)
|
108
|
+
treetop (1.4.15)
|
109
|
+
polyglot
|
110
|
+
polyglot (>= 0.3.1)
|
111
|
+
tzinfo (0.3.38)
|
112
|
+
|
113
|
+
PLATFORMS
|
114
|
+
ruby
|
115
|
+
|
116
|
+
DEPENDENCIES
|
117
|
+
coveralls
|
118
|
+
periodic_calculations!
|
119
|
+
pg
|
120
|
+
rspec-rails
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Pol Miro
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# PeriodicCalculations
|
2
|
+
|
3
|
+
[](https://travis-ci.org/polmiro/periodic_calculations)
|
4
|
+
[](https://codeclimate.com/github/polmiro/periodic_calculations)
|
5
|
+
[](https://coveralls.io/r/polmiro/periodic_calculations)
|
6
|
+
[](http://badge.fury.io/rb/periodic_calculations)
|
7
|
+
|
8
|
+
Periodic Calculations gem allows you to retrieve periodic results of aggregates that can be accumulated over time with PostgreSQL.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/setup'
|
3
|
+
begin
|
4
|
+
require 'rdoc/task'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rdoc/rdoc'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
RDoc::Task = Rake::RDocTask
|
9
|
+
end
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'PeriodicCalculations'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.rdoc')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
Bundler::GemHelper.install_tasks
|
20
|
+
|
21
|
+
require 'rspec/core/rake_task'
|
22
|
+
task :default => :spec
|
23
|
+
RSpec::Core::RakeTask.new
|
24
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PeriodicCalculations
|
2
|
+
module Base
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# TODO:
|
6
|
+
# * Rails 4 compatible only right now (scoped vs all)
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def periodic_count(*args)
|
10
|
+
periodic_calculation(:count, *args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def periodic_maximum(*args)
|
14
|
+
periodic_calculation(:max, *args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def periodic_minimum(*args)
|
18
|
+
periodic_calculation(:min, *args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def periodic_sum(*args)
|
22
|
+
periodic_calculation(:sum, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def periodic_average(*args)
|
26
|
+
periodic_calculation(:avg, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def periodic_calculation(operation, column_name, window_start, window_end, options = {})
|
30
|
+
query_options = QueryOptions.new(operation, column_name, window_start, window_end, options)
|
31
|
+
query = Query.new(all, query_options)
|
32
|
+
LazyQuery.new(query)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PeriodicCalculations
|
2
|
+
class LazyQuery
|
3
|
+
def initialize(query)
|
4
|
+
@query = query
|
5
|
+
@executed = false
|
6
|
+
@result = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method_name, *args, &block)
|
10
|
+
if method_name == :to_sql
|
11
|
+
@query.to_sql
|
12
|
+
else
|
13
|
+
lazy_result.send(method_name, *args, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to?(method_name, include_private = false)
|
18
|
+
method_name == :to_sql || super || lazy_result.respond_to?(method_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def result
|
22
|
+
lazy_result
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def lazy_result
|
28
|
+
if @executed
|
29
|
+
@result
|
30
|
+
else
|
31
|
+
@executed = true
|
32
|
+
@result = @query.execute
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module PeriodicCalculations
|
2
|
+
class Query
|
3
|
+
INTERVAL_UNIT = [:day, :week, :month, :year]
|
4
|
+
|
5
|
+
# TODO:
|
6
|
+
# * prepared statement?
|
7
|
+
|
8
|
+
# Builds a periodic operation query with PostgresSQL window functions
|
9
|
+
#
|
10
|
+
# @param relation [ActiveRecord::Relation] Object to build query from
|
11
|
+
# @param query_options [QueryOptions]
|
12
|
+
# @return [Array<Array>] for each period the time of the interval and the count of it
|
13
|
+
def initialize(relation, query_options)
|
14
|
+
@relation = relation
|
15
|
+
@target_column = query_options.target_column
|
16
|
+
@timestamp_column = query_options.timestamp_column
|
17
|
+
@operation = query_options.operation.upcase
|
18
|
+
@window_function = query_options.cumulative ? "ORDER" : "PARTITION"
|
19
|
+
@binds = {
|
20
|
+
:unit => query_options.interval_unit,
|
21
|
+
:interval => "1 #{query_options.interval_unit.upcase}",
|
22
|
+
:start => query_options.window_start,
|
23
|
+
:end => query_options.window_end,
|
24
|
+
:offset => "#{query_options.timezone_offset} seconds"
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def execute
|
29
|
+
ActiveRecord::Base.connection_pool.with_connection do |connection|
|
30
|
+
connection.execute(sanitized_sql).map do |elem|
|
31
|
+
[Date.parse(elem["frame"]).to_time, elem["result"].to_i]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_sql
|
37
|
+
sanitized_sql
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def sanitized_sql
|
43
|
+
ActiveRecord::Base.send(:sanitize_sql_array, [Arel.sql(sql), @binds])
|
44
|
+
end
|
45
|
+
|
46
|
+
def sql
|
47
|
+
# How are timezones managed?
|
48
|
+
# * Take into account the timezone offset throughout the search,
|
49
|
+
# so that the periods are correctly grouped.
|
50
|
+
# * Restore the timezone at the very end to return the date in UTC
|
51
|
+
# being consistent with the Rails convention
|
52
|
+
|
53
|
+
# What does it do?
|
54
|
+
# 1. group currently selected rows by the interval
|
55
|
+
# 2. trim out unneeded rows if query is not cumulative
|
56
|
+
# 3. make a union to add possible missing time points
|
57
|
+
# 4. iterate over a window function that can cumulate the previous counters if needed
|
58
|
+
# 5. trim out rows outside the time window
|
59
|
+
# Cannot be done before in the same query because window function iterates after the
|
60
|
+
# where/group by/having clauses (could be improved for non cumulative queries)
|
61
|
+
|
62
|
+
<<-SQL
|
63
|
+
WITH
|
64
|
+
-- generate series within window
|
65
|
+
-- (with shifted timezones utc_date -> zone_date)
|
66
|
+
grid AS (
|
67
|
+
SELECT date_trunc(:unit, serie) AS frame,
|
68
|
+
NULL::integer AS result
|
69
|
+
FROM generate_series(
|
70
|
+
:start::timestamp + INTERVAL :offset,
|
71
|
+
:end::timestamp + INTERVAL :offset,
|
72
|
+
:interval
|
73
|
+
) AS serie
|
74
|
+
)
|
75
|
+
|
76
|
+
-- preprocess results grouping by interval
|
77
|
+
-- (with shifted timezones utc_date -> zone_date)
|
78
|
+
, preprocessed_results AS (
|
79
|
+
#{relation_sql}
|
80
|
+
)
|
81
|
+
|
82
|
+
-- running window function calculate results and fill up gaps
|
83
|
+
, results AS (
|
84
|
+
SELECT DISTINCT frame,
|
85
|
+
#{@operation}(result) OVER (#{@window_function} BY frame) AS result
|
86
|
+
FROM (
|
87
|
+
SELECT frame, result FROM preprocessed_results
|
88
|
+
UNION ALL
|
89
|
+
SELECT frame, result FROM grid
|
90
|
+
) AS fulfilled_gaps
|
91
|
+
)
|
92
|
+
|
93
|
+
-- cut out values outside window
|
94
|
+
-- (with shifted timezones utc_date -> zone_date)
|
95
|
+
SELECT frame,
|
96
|
+
result
|
97
|
+
FROM results
|
98
|
+
WHERE frame BETWEEN
|
99
|
+
date_trunc(:unit, :start::timestamp + INTERVAL :offset)
|
100
|
+
AND
|
101
|
+
date_trunc(:unit, :end::timestamp + INTERVAL :offset)
|
102
|
+
ORDER BY frame ASC
|
103
|
+
SQL
|
104
|
+
end
|
105
|
+
|
106
|
+
def relation_sql
|
107
|
+
# select frames an results
|
108
|
+
relation_query = @relation
|
109
|
+
.select(<<-SQL)
|
110
|
+
date_trunc(:unit, #{@relation.table_name}.#{@timestamp_column} + INTERVAL :offset) AS frame,
|
111
|
+
#{@operation}(#{@target_column}) AS result
|
112
|
+
SQL
|
113
|
+
|
114
|
+
# optimize selection if not cumulative query
|
115
|
+
if @window_function == "PARTITION"
|
116
|
+
relation_query = relation_query.where(<<-SQL)
|
117
|
+
date_trunc(:unit, #{@relation.table_name}.#{@timestamp_column} + INTERVAL :offset) BETWEEN
|
118
|
+
date_trunc(:unit, :start::timestamp + INTERVAL :offset)
|
119
|
+
AND
|
120
|
+
date_trunc(:unit, :end::timestamp + INTERVAL :offset)
|
121
|
+
SQL
|
122
|
+
end
|
123
|
+
|
124
|
+
# group results by frames
|
125
|
+
relation_query = relation_query.group(<<-SQL)
|
126
|
+
date_trunc(:unit, #{@relation.table_name}.#{@timestamp_column} + INTERVAL :offset)
|
127
|
+
SQL
|
128
|
+
|
129
|
+
relation_query.to_sql
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
ActiveRecord::Base.extend PeriodicCalculations
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module PeriodicCalculations
|
2
|
+
class QueryOptions
|
3
|
+
OPERATION = [:count, :max, :min, :sum, :avg]
|
4
|
+
INTERVAL_UNIT = [:day, :week, :month, :year]
|
5
|
+
|
6
|
+
attr_reader :operation,
|
7
|
+
:target_column,
|
8
|
+
:timestamp_column,
|
9
|
+
:window_start,
|
10
|
+
:window_end,
|
11
|
+
:interval_unit,
|
12
|
+
:cumulative,
|
13
|
+
:timezone_offset
|
14
|
+
|
15
|
+
def initialize(operation, column_name, window_start, window_end, options = {})
|
16
|
+
@operation = operation
|
17
|
+
@target_column = column_name
|
18
|
+
@timestamp_column = options[:timestamp_column] || :created_at
|
19
|
+
@window_start = window_start
|
20
|
+
@window_end = window_end
|
21
|
+
@interval_unit = options[:interval_unit] || :day
|
22
|
+
@cumulative = !!options[:cumulative]
|
23
|
+
@timezone_offset = Time.now.in_time_zone.utc_offset
|
24
|
+
|
25
|
+
validate!
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def validate!
|
31
|
+
validate_operation!
|
32
|
+
validate_target_column!
|
33
|
+
validate_window!
|
34
|
+
validate_interval_unit!
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_operation!
|
38
|
+
unless OPERATION.include?(@operation)
|
39
|
+
raise ArgumentError.new("Invalid operation")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_target_column!
|
44
|
+
unless @target_column.present?
|
45
|
+
raise ArgumentError.new("Target column name must be present")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_window!
|
50
|
+
unless window_start.is_a?(Time) && window_end.is_a?(Time)
|
51
|
+
raise ArgumentError.new("Invalid Time window")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_interval_unit!
|
56
|
+
unless INTERVAL_UNIT.include?(@interval_unit)
|
57
|
+
raise ArgumentError.new("Invalid interval unit")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
module PeriodicCalculations
|
5
|
+
require "periodic_calculations/version"
|
6
|
+
require "periodic_calculations/base"
|
7
|
+
require "periodic_calculations/query"
|
8
|
+
require "periodic_calculations/query_options"
|
9
|
+
require "periodic_calculations/lazy_query"
|
10
|
+
require "periodic_calculations/engine"
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "periodic_calculations/version"
|
5
|
+
|
6
|
+
# Describe your gem and declare its dependencies:
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "periodic_calculations"
|
9
|
+
s.version = PeriodicCalculations::VERSION
|
10
|
+
s.authors = ["Pol"]
|
11
|
+
s.email = ["polmiro@gmail.com"]
|
12
|
+
s.homepage = "https://github.com/polmiro/periodic_calculations"
|
13
|
+
s.summary = "Retrieve periodic stats in periods of time"
|
14
|
+
s.description = "Periodic Calculations gem allows you to retrieve periodic results of aggregates that can be accumulated over time with PostgreSQL."
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency "rails", ">= 3.2"
|
23
|
+
s.add_dependency "railties"
|
24
|
+
|
25
|
+
s.add_development_dependency "rspec-rails"
|
26
|
+
s.add_development_dependency "pg"
|
27
|
+
s.add_development_dependency "coveralls"
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/spec/dummy/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Dummy</title>
|
5
|
+
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
|
6
|
+
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require 'rails/all'
|
4
|
+
|
5
|
+
Bundler.require(*Rails.groups)
|
6
|
+
require "periodic_calculations"
|
7
|
+
|
8
|
+
module Dummy
|
9
|
+
class Application < Rails::Application
|
10
|
+
# Settings in config/environments/* take precedence over those specified here.
|
11
|
+
# Application configuration should go into files in config/initializers
|
12
|
+
# -- all .rb files in that directory are automatically loaded.
|
13
|
+
|
14
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
15
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
16
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
17
|
+
|
18
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
19
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
20
|
+
# config.i18n.default_locale = :de
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
development:
|
2
|
+
adapter: postgresql
|
3
|
+
encoding: utf8
|
4
|
+
database: periodic_calculations_development
|
5
|
+
pool: 5
|
6
|
+
host: 127.0.0.1
|
7
|
+
username: rewardli_su
|
8
|
+
password:
|
9
|
+
timeout: 5000
|
10
|
+
|
11
|
+
test:
|
12
|
+
adapter: postgresql
|
13
|
+
encoding: utf8
|
14
|
+
database: periodic_calculations_test
|
15
|
+
pool: 5
|
16
|
+
host: 127.0.0.1
|
17
|
+
username: rewardli_su
|
18
|
+
password:
|
19
|
+
timeout: 5000
|
20
|
+
|