groupdate 3.2.0 → 6.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +146 -27
- data/CONTRIBUTING.md +75 -0
- data/LICENSE.txt +1 -1
- data/README.md +67 -44
- data/lib/groupdate/active_record.rb +4 -51
- data/lib/groupdate/adapters/base_adapter.rb +51 -0
- data/lib/groupdate/adapters/mysql_adapter.rb +63 -0
- data/lib/groupdate/adapters/postgresql_adapter.rb +46 -0
- data/lib/groupdate/adapters/sqlite_adapter.rb +51 -0
- data/lib/groupdate/enumerable.rb +9 -14
- data/lib/groupdate/magic.rb +202 -333
- data/lib/groupdate/query_methods.rb +18 -0
- data/lib/groupdate/relation.rb +19 -0
- data/lib/groupdate/series_builder.rb +304 -0
- data/lib/groupdate/version.rb +1 -1
- data/lib/groupdate.rb +37 -7
- metadata +20 -145
- data/.gitignore +0 -19
- data/.travis.yml +0 -25
- data/Gemfile +0 -6
- data/Rakefile +0 -24
- data/groupdate.gemspec +0 -37
- data/lib/groupdate/calculations.rb +0 -26
- data/lib/groupdate/order_hack.rb +0 -11
- data/lib/groupdate/scopes.rb +0 -24
- data/lib/groupdate/series.rb +0 -30
- data/test/enumerable_test.rb +0 -60
- data/test/gemfiles/activerecord31.gemfile +0 -6
- data/test/gemfiles/activerecord32.gemfile +0 -6
- data/test/gemfiles/activerecord40.gemfile +0 -6
- data/test/gemfiles/activerecord41.gemfile +0 -6
- data/test/gemfiles/activerecord42.gemfile +0 -6
- data/test/gemfiles/redshift.gemfile +0 -7
- data/test/mysql_test.rb +0 -15
- data/test/postgresql_test.rb +0 -15
- data/test/redshift_test.rb +0 -18
- data/test/sqlite_test.rb +0 -29
- data/test/test_helper.rb +0 -1207
@@ -1,26 +0,0 @@
|
|
1
|
-
module Groupdate
|
2
|
-
class Calculations
|
3
|
-
attr_reader :relation
|
4
|
-
|
5
|
-
def initialize(relation)
|
6
|
-
@relation = relation
|
7
|
-
end
|
8
|
-
|
9
|
-
def include?(method)
|
10
|
-
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb
|
11
|
-
ActiveRecord::Calculations.method_defined?(method) || custom_calculations.include?(method)
|
12
|
-
end
|
13
|
-
|
14
|
-
def custom_calculations
|
15
|
-
return [] if !model.respond_to?(:groupdate_calculation_methods)
|
16
|
-
model.groupdate_calculation_methods
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def model
|
22
|
-
return if !relation.respond_to?(:klass)
|
23
|
-
relation.klass
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/groupdate/order_hack.rb
DELETED
data/lib/groupdate/scopes.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module Groupdate
|
2
|
-
module Scopes
|
3
|
-
Groupdate::PERIODS.each do |period|
|
4
|
-
define_method :"group_by_#{period}" do |field, *args|
|
5
|
-
args = args.dup
|
6
|
-
options = args[-1].is_a?(Hash) ? args.pop : {}
|
7
|
-
options[:time_zone] ||= args[0] unless args[0].nil?
|
8
|
-
options[:range] ||= args[1] unless args[1].nil?
|
9
|
-
|
10
|
-
Groupdate::Magic.new(period, options).relation(field, self)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def group_by_period(period, field, options = {})
|
15
|
-
# to_sym is unsafe on user input, so convert to strings
|
16
|
-
permitted_periods = ((options[:permit] || Groupdate::PERIODS).map(&:to_sym) & Groupdate::PERIODS).map(&:to_s)
|
17
|
-
if permitted_periods.include?(period.to_s)
|
18
|
-
send("group_by_#{period}", field, options)
|
19
|
-
else
|
20
|
-
raise ArgumentError, "Unpermitted period"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/groupdate/series.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Groupdate
|
2
|
-
class Series
|
3
|
-
attr_accessor :magic, :relation
|
4
|
-
|
5
|
-
def initialize(magic, relation)
|
6
|
-
@magic = magic
|
7
|
-
@relation = relation
|
8
|
-
@calculations = Groupdate::Calculations.new(relation)
|
9
|
-
end
|
10
|
-
|
11
|
-
# clone to prevent modifying original variables
|
12
|
-
def method_missing(method, *args, &block)
|
13
|
-
if @calculations.include?(method)
|
14
|
-
magic.perform(relation, method, *args, &block)
|
15
|
-
elsif relation.respond_to?(method, true)
|
16
|
-
Groupdate::Series.new(magic, relation.send(method, *args, &block))
|
17
|
-
else
|
18
|
-
super
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def respond_to?(method, include_all = false)
|
23
|
-
@calculations.include?(method) || relation.respond_to?(method) || super
|
24
|
-
end
|
25
|
-
|
26
|
-
def reverse_order_value
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/test/enumerable_test.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
require "ostruct"
|
3
|
-
|
4
|
-
class EnumerableTest < Minitest::Test
|
5
|
-
include TestGroupdate
|
6
|
-
|
7
|
-
def test_enumerable
|
8
|
-
user_a = create_user("2014-01-21")
|
9
|
-
user_b = create_user("2014-03-14")
|
10
|
-
expected = {
|
11
|
-
Date.parse("2014-01-01") => [user_a],
|
12
|
-
Date.parse("2014-03-01") => [user_b]
|
13
|
-
}
|
14
|
-
assert_equal expected, [user_a, user_b].group_by_month(&:created_at)
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_enumerable_series
|
18
|
-
user_a = create_user("2014-01-21")
|
19
|
-
user_b = create_user("2014-03-14")
|
20
|
-
expected = {
|
21
|
-
Date.parse("2014-01-01") => [user_a],
|
22
|
-
Date.parse("2014-02-01") => [],
|
23
|
-
Date.parse("2014-03-01") => [user_b]
|
24
|
-
}
|
25
|
-
assert_equal expected, [user_a, user_b].group_by_month(series: true, &:created_at)
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_no_block
|
29
|
-
assert_raises(ArgumentError) { [].group_by_day(:created_at) }
|
30
|
-
end
|
31
|
-
|
32
|
-
def call_method(method, field, options)
|
33
|
-
Hash[@users.group_by_period(method, options) { |u| u.send(field) }.map { |k, v| [k, v.size] }]
|
34
|
-
end
|
35
|
-
|
36
|
-
def create_user(created_at, score = 1)
|
37
|
-
user =
|
38
|
-
OpenStruct.new(
|
39
|
-
name: "Andrew",
|
40
|
-
score: score,
|
41
|
-
created_at: created_at ? utc.parse(created_at) : nil,
|
42
|
-
created_on: created_at ? Date.parse(created_at) : nil
|
43
|
-
)
|
44
|
-
@users << user
|
45
|
-
user
|
46
|
-
end
|
47
|
-
|
48
|
-
def setup
|
49
|
-
super
|
50
|
-
@users = []
|
51
|
-
end
|
52
|
-
|
53
|
-
def teardown
|
54
|
-
# do nothing
|
55
|
-
end
|
56
|
-
|
57
|
-
def enumerable_test?
|
58
|
-
true
|
59
|
-
end
|
60
|
-
end
|
data/test/mysql_test.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class MysqlTest < Minitest::Test
|
4
|
-
include TestGroupdate
|
5
|
-
include TestDatabase
|
6
|
-
|
7
|
-
def setup
|
8
|
-
super
|
9
|
-
@@setup ||= begin
|
10
|
-
ActiveRecord::Base.establish_connection adapter: "mysql2", database: "groupdate_test", username: "root"
|
11
|
-
create_tables
|
12
|
-
true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/test/postgresql_test.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class PostgresqlTest < Minitest::Test
|
4
|
-
include TestGroupdate
|
5
|
-
include TestDatabase
|
6
|
-
|
7
|
-
def setup
|
8
|
-
super
|
9
|
-
@@setup ||= begin
|
10
|
-
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "groupdate_test"
|
11
|
-
create_tables
|
12
|
-
true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/test/redshift_test.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class RedshiftTest < Minitest::Test
|
4
|
-
include TestGroupdate
|
5
|
-
include TestDatabase
|
6
|
-
|
7
|
-
def setup
|
8
|
-
super
|
9
|
-
@@setup ||= begin
|
10
|
-
abort("REDSHIFT_URL environment variable must be set in order to run tests") unless ENV["REDSHIFT_URL"].present?
|
11
|
-
|
12
|
-
ActiveRecord::Base.establish_connection(ENV["REDSHIFT_URL"])
|
13
|
-
|
14
|
-
create_redshift_tables
|
15
|
-
true
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/test/sqlite_test.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class TestSqlite < Minitest::Test
|
4
|
-
include TestGroupdate
|
5
|
-
include TestDatabase
|
6
|
-
|
7
|
-
def setup
|
8
|
-
super
|
9
|
-
@@setup ||= begin
|
10
|
-
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
11
|
-
create_tables
|
12
|
-
true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_where_after
|
17
|
-
skip
|
18
|
-
end
|
19
|
-
|
20
|
-
def call_method(method, field, options)
|
21
|
-
if method == :quarter || options[:time_zone] || options[:day_start] || options[:week_start] || Groupdate.week_start != :sun || (Time.zone && options[:time_zone] != false)
|
22
|
-
error = assert_raises(Groupdate::Error) { super }
|
23
|
-
assert_includes error.message, "not supported for SQLite"
|
24
|
-
skip # after assertions
|
25
|
-
else
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|