groupdate 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b555424def0887e8b0ab933f26c84844a6e9b8b
4
- data.tar.gz: c16d375c965c0d289ffc8476435b47b61e09ebf2
3
+ metadata.gz: e50a64260e2d0aa3ce8675cce56a1b074c4e1bff
4
+ data.tar.gz: 08366d6b98a953349a1dff0e1585de45d3f4ff05
5
5
  SHA512:
6
- metadata.gz: 835b67dacd82ce1fde549847fcf2647cad712ef75a14841c13b42d06ce95f606c4f5db124f0795dedace821d9c0113211b6d4c011a9c29cfc717fe2cbbc4e643
7
- data.tar.gz: 3cb677877505d1f09ad3067fbc0777f4db8d0330429710d43f38544b0782dec7ce1c98f7f9d488c947f9c8de4bb638fced6475e98514c06c6a4ad72891852a01
6
+ metadata.gz: cc9ae556196bbb405d1524d55b770a67b4b68647fc54332636e01b65e325221158cbb90bfd4868d47e7a6c8d86f267e507da0bb9213aff7c0322d8943214096f
7
+ data.tar.gz: 63b2478668b5f76a29b4c72beffa227402eedd5671a9b4da7ad88a748373847e6ae5c181b64c0ec692c637c3914313e2731919e8356f0b03e33e3733313a13a1
@@ -1,16 +1,18 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.2
3
+ - 2.2.4
5
4
  - jruby
6
5
  gemfile:
7
6
  - Gemfile
8
- - gemfiles/activerecord31.gemfile
9
- - gemfiles/activerecord32.gemfile
10
- - gemfiles/activerecord40.gemfile
11
- - gemfiles/activerecord41.gemfile
7
+ - test/gemfiles/activerecord31.gemfile
8
+ - test/gemfiles/activerecord32.gemfile
9
+ - test/gemfiles/activerecord40.gemfile
10
+ - test/gemfiles/activerecord41.gemfile
11
+ - test/gemfiles/activerecord50.gemfile
12
+ sudo: false
12
13
  script: bundle exec rake test
13
- before_script:
14
+ before_install:
15
+ - gem install bundler
14
16
  - mysql -e 'create database groupdate_test;'
15
17
  - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
16
18
  - psql -c 'create database groupdate_test;' -U postgres
@@ -22,3 +24,4 @@ matrix:
22
24
  allow_failures:
23
25
  - rvm: jruby
24
26
  gemfile: Gemfile
27
+ - gemfile: test/gemfiles/activerecord50.gemfile
@@ -1,3 +1,11 @@
1
+ ## 2.5.1
2
+
3
+ - Added `group_by_quarter`
4
+ - Added `default_value` option
5
+ - Accept symbol for `format` option
6
+ - Raise `ArgumentError` if no field specified
7
+ - Added support for ActiveRecord 5 beta
8
+
1
9
  ## 2.5.0
2
10
 
3
11
  - Added `group_by_period` method
data/README.md CHANGED
@@ -41,6 +41,7 @@ You can also group by:
41
41
  - hour
42
42
  - week
43
43
  - month
44
+ - quarter
44
45
  - year
45
46
 
46
47
  and
@@ -140,10 +141,10 @@ User.group_by_day(:created_at).order("day desc").count
140
141
  To get keys in a different format, use:
141
142
 
142
143
  ```ruby
143
- User.group_by_day(:created_at, format: "%b %-e, %Y").count
144
+ User.group_by_month(:created_at, format: "%b %Y").count
144
145
  # {
145
- # "Jan 1, 2015" => 10
146
- # "Jan 2, 2015" => 12
146
+ # "Jan 2015" => 10
147
+ # "Feb 2015" => 12
147
148
  # }
148
149
  ```
149
150
 
@@ -158,7 +159,7 @@ User.group_by_hour_of_day(:created_at, format: "%-l %P").count
158
159
  # }
159
160
  ```
160
161
 
161
- Takes a `String`, which is passed to [strftime](http://strfti.me/), or a `Proc`. You can pass a locale with the `locale` option.
162
+ Takes a `String`, which is passed to [strftime](http://strfti.me/), or a `Symbol`, which is looked up by `I18n.localize` in `i18n` scope 'time.formats', or a `Proc`. You can pass a locale with the `locale` option.
162
163
 
163
164
  ### Dynamic Grouping
164
165
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
- task :default => :test
4
+ task default: :test
5
5
  Rake::TestTask.new do |t|
6
6
  t.libs << "test"
7
7
  t.pattern = "test/**/*_test.rb"
@@ -4,8 +4,10 @@ require "groupdate/version"
4
4
  require "groupdate/magic"
5
5
 
6
6
  module Groupdate
7
- FIELDS = [:second, :minute, :hour, :day, :week, :month, :year, :day_of_week, :hour_of_day, :day_of_month, :month_of_year]
8
- METHODS = FIELDS.map { |v| :"group_by_#{v}" }
7
+ PERIODS = [:second, :minute, :hour, :day, :week, :month, :quarter, :year, :day_of_week, :hour_of_day, :day_of_month, :month_of_year]
8
+ # backwards compatibility for anyone who happened to use it
9
+ FIELDS = PERIODS
10
+ METHODS = PERIODS.map { |v| :"group_by_#{v}" }
9
11
 
10
12
  mattr_accessor :week_start, :day_start, :time_zone
11
13
  self.week_start = :sun
@@ -26,25 +26,27 @@ module ActiveRecord
26
26
  module Associations
27
27
  class CollectionProxy
28
28
  if ActiveRecord::VERSION::MAJOR == 3
29
- delegate *Groupdate::METHODS, :to => :scoped
29
+ delegate *Groupdate::METHODS, to: :scoped
30
30
  end
31
31
  end
32
32
  end
33
33
  end
34
34
 
35
- # hack for **unfixed** rails issue
35
+ # hack for issue before Rails 5
36
36
  # https://github.com/rails/rails/issues/7121
37
37
  module ActiveRecord
38
38
  module Calculations
39
39
  private
40
40
 
41
- def column_alias_for_with_hack(*keys)
42
- if keys.first.is_a?(Groupdate::OrderHack)
43
- keys.first.field
44
- else
45
- column_alias_for_without_hack(*keys)
41
+ if ActiveRecord::VERSION::MAJOR < 5
42
+ def column_alias_for_with_hack(*keys)
43
+ if keys.first.is_a?(Groupdate::OrderHack)
44
+ keys.first.field
45
+ else
46
+ column_alias_for_without_hack(*keys)
47
+ end
46
48
  end
49
+ alias_method_chain :column_alias_for, :hack
47
50
  end
48
- alias_method_chain :column_alias_for, :hack
49
51
  end
50
52
  end
@@ -1,8 +1,10 @@
1
1
  module Enumerable
2
- Groupdate::FIELDS.each do |field|
3
- define_method :"group_by_#{field}" do |options = {}, &block|
2
+ Groupdate::PERIODS.each do |period|
3
+ define_method :"group_by_#{period}" do |*args, &block|
4
4
  if block
5
- Groupdate::Magic.new(field, options).group_by(self, &block)
5
+ Groupdate::Magic.new(period, args[0] || {}).group_by(self, &block)
6
+ elsif respond_to?(:scoping)
7
+ scoping { @klass.send(:"group_by_#{period}", *args, &block) }
6
8
  else
7
9
  raise ArgumentError, "no block given"
8
10
  end
@@ -11,7 +13,7 @@ module Enumerable
11
13
 
12
14
  def group_by_period(period, options = {}, &block)
13
15
  # to_sym is unsafe on user input, so convert to strings
14
- permitted_periods = ((options[:permit] || Groupdate::FIELDS).map(&:to_sym) & Groupdate::FIELDS).map(&:to_s)
16
+ permitted_periods = ((options[:permit] || Groupdate::PERIODS).map(&:to_sym) & Groupdate::PERIODS).map(&:to_s)
15
17
  if permitted_periods.include?(period.to_s)
16
18
  send("group_by_#{period}", options, &block)
17
19
  else
@@ -8,13 +8,9 @@ module Groupdate
8
8
  @field = field
9
9
  @options = options
10
10
 
11
- unless time_zone
12
- raise "Unrecognized time zone"
13
- end
11
+ raise "Unrecognized time zone" unless time_zone
14
12
 
15
- if field == :week && !week_start
16
- raise "Unrecognized :week_start option"
17
- end
13
+ raise "Unrecognized :week_start option" if field == :week && !week_start
18
14
  end
19
15
 
20
16
  def group_by(enum, &_block)
@@ -36,7 +32,7 @@ module Groupdate
36
32
  adapter_name = relation.connection.adapter_name
37
33
  query =
38
34
  case adapter_name
39
- when "MySQL", "Mysql2"
35
+ when "MySQL", "Mysql2", "Mysql2Spatial"
40
36
  case field
41
37
  when :day_of_week # Sunday = 0, Monday = 1, etc
42
38
  # use CONCAT for consistent return type (String)
@@ -49,6 +45,8 @@ module Groupdate
49
45
  ["MONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?))", time_zone]
50
46
  when :week
51
47
  ["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL ((#{7 - week_start} + WEEKDAY(CONVERT_TZ(#{column}, '+00:00', ?) - INTERVAL #{day_start} HOUR)) % 7) DAY) - INTERVAL #{day_start} HOUR, '+00:00', ?), '%Y-%m-%d 00:00:00') + INTERVAL #{day_start} HOUR, ?, '+00:00')", time_zone, time_zone, time_zone]
48
+ when :quarter
49
+ ["DATE_ADD(CONVERT_TZ(DATE_FORMAT(DATE(CONCAT(EXTRACT(YEAR FROM CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)), '-', LPAD(1 + 3 * (QUARTER(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)) - 1), 2, '00'), '-01')), '%Y-%m-%d %H:%i:%S'), ?, '+00:00'), INTERVAL #{day_start} HOUR)", time_zone, time_zone, time_zone]
52
50
  else
53
51
  format =
54
52
  case field
@@ -109,9 +107,7 @@ module Groupdate
109
107
  def perform(relation, method, *args, &block)
110
108
  # undo reverse since we do not want this to appear in the query
111
109
  reverse = relation.send(:reverse_order_value)
112
- if reverse
113
- relation = relation.except(:reverse_order)
114
- end
110
+ relation = relation.except(:reverse_order) if reverse
115
111
  order = relation.order_values.first
116
112
  if order.is_a?(String)
117
113
  parts = order.split(" ")
@@ -140,7 +136,7 @@ module Groupdate
140
136
  raise "Be sure to install time zone support - https://github.com/ankane/groupdate#for-mysql"
141
137
  end
142
138
 
143
- series(count, 0, multiple_groups, reverse)
139
+ series(count, (options.key?(:default_value) ? options[:default_value] : 0), multiple_groups, reverse)
144
140
  end
145
141
 
146
142
  protected
@@ -207,7 +203,11 @@ module Groupdate
207
203
  if time_range.first
208
204
  series = [round_time(time_range.first)]
209
205
 
210
- step = 1.send(field)
206
+ if field == :quarter
207
+ step = 3.months
208
+ else
209
+ step = 1.send(field)
210
+ end
211
211
 
212
212
  while (next_step = round_time(series.last + step)) && time_range.cover?(next_step)
213
213
  series << next_step
@@ -231,9 +231,7 @@ module Groupdate
231
231
  end
232
232
 
233
233
  # reversed above if multiple groups
234
- if !multiple_groups && reverse
235
- series = series.to_a.reverse
236
- end
234
+ series = series.to_a.reverse if !multiple_groups && reverse
237
235
 
238
236
  locale = options[:locale] || I18n.locale
239
237
  key_format =
@@ -253,7 +251,7 @@ module Groupdate
253
251
  when :month_of_year
254
252
  key = Date.new(2014, key, 1).to_time
255
253
  end
256
- I18n.localize(key, format: options[:format].to_s, locale: locale)
254
+ I18n.localize(key, format: options[:format], locale: locale)
257
255
  end
258
256
  end
259
257
  else
@@ -273,11 +271,11 @@ module Groupdate
273
271
  time =
274
272
  case field
275
273
  when :second
276
- time.change(:usec => 0)
274
+ time.change(usec: 0)
277
275
  when :minute
278
- time.change(:sec => 0)
276
+ time.change(sec: 0)
279
277
  when :hour
280
- time.change(:min => 0)
278
+ time.change(min: 0)
281
279
  when :day
282
280
  time.beginning_of_day
283
281
  when :week
@@ -286,6 +284,8 @@ module Groupdate
286
284
  (time - ((7 - week_start + weekday) % 7).days).midnight
287
285
  when :month
288
286
  time.beginning_of_month
287
+ when :quarter
288
+ time.beginning_of_quarter
289
289
  when :year
290
290
  time.beginning_of_year
291
291
  when :hour_of_day
@@ -1,19 +1,19 @@
1
1
  module Groupdate
2
2
  module Scopes
3
- Groupdate::FIELDS.each do |field|
4
- define_method :"group_by_#{field}" do |*args|
3
+ Groupdate::PERIODS.each do |period|
4
+ define_method :"group_by_#{period}" do |field, *args|
5
5
  args = args.dup
6
6
  options = args[-1].is_a?(Hash) ? args.pop : {}
7
- options[:time_zone] ||= args[1] unless args[1].nil?
8
- options[:range] ||= args[2] unless args[2].nil?
7
+ options[:time_zone] ||= args[0] unless args[0].nil?
8
+ options[:range] ||= args[1] unless args[1].nil?
9
9
 
10
- Groupdate::Magic.new(field, options).relation(args[0], self)
10
+ Groupdate::Magic.new(period, options).relation(field, self)
11
11
  end
12
12
  end
13
13
 
14
14
  def group_by_period(period, field, options = {})
15
15
  # to_sym is unsafe on user input, so convert to strings
16
- permitted_periods = ((options[:permit] || Groupdate::FIELDS).map(&:to_sym) & Groupdate::FIELDS).map(&:to_s)
16
+ permitted_periods = ((options[:permit] || Groupdate::PERIODS).map(&:to_sym) & Groupdate::PERIODS).map(&:to_s)
17
17
  if permitted_periods.include?(period.to_s)
18
18
  send("group_by_#{period}", field, options)
19
19
  else
@@ -1,3 +1,3 @@
1
1
  module Groupdate
2
- VERSION = "2.5.0"
2
+ VERSION = "2.5.1"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchkick.gemspec
4
- gemspec path: "../"
4
+ gemspec path: "../../"
5
5
 
6
6
  gem "activerecord", "~> 3.1.0"
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchkick.gemspec
4
- gemspec path: "../"
4
+ gemspec path: "../../"
5
5
 
6
6
  gem "activerecord", "~> 3.2.0"
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchkick.gemspec
4
- gemspec path: "../"
4
+ gemspec path: "../../"
5
5
 
6
6
  gem "activerecord", "~> 4.0.0"
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchkick.gemspec
4
- gemspec path: "../"
4
+ gemspec path: "../../"
5
5
 
6
6
  gem "activerecord", "~> 4.1.0"
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "activerecord", "~> 5.0.0.beta1"
@@ -5,6 +5,6 @@ class TestMysql < Minitest::Test
5
5
 
6
6
  def setup
7
7
  super
8
- User.establish_connection :adapter => "mysql2", :database => "groupdate_test", :username => "root"
8
+ User.establish_connection adapter: "mysql2", database: "groupdate_test", username: "root"
9
9
  end
10
10
  end
@@ -5,6 +5,10 @@ class TestPostgresql < Minitest::Test
5
5
 
6
6
  def setup
7
7
  super
8
- User.establish_connection :adapter => "postgresql", :database => "groupdate_test"
8
+ User.establish_connection adapter: "postgresql", database: "groupdate_test"
9
+ end
10
+
11
+ def test_no_column
12
+ assert_raises(ArgumentError) { User.group_by_day.first }
9
13
  end
10
14
  end
@@ -24,21 +24,24 @@ end
24
24
 
25
25
  # i18n
26
26
  I18n.enforce_available_locales = true
27
- I18n.backend.store_translations :de, :date => {
28
- :abbr_month_names => %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil)
27
+ I18n.backend.store_translations :de, date: {
28
+ abbr_month_names: %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil)
29
+ },
30
+ time: {
31
+ formats: {special: "%b %e, %Y"}
29
32
  }
30
33
 
31
34
  # migrations
32
35
  %w(postgresql mysql2).each do |adapter|
33
- ActiveRecord::Base.establish_connection :adapter => adapter, :database => "groupdate_test", :username => adapter == "mysql2" ? "root" : nil
36
+ ActiveRecord::Base.establish_connection adapter: adapter, database: "groupdate_test", username: adapter == "mysql2" ? "root" : nil
34
37
 
35
- ActiveRecord::Migration.create_table :users, :force => true do |t|
38
+ ActiveRecord::Migration.create_table :users, force: true do |t|
36
39
  t.string :name
37
40
  t.integer :score
38
41
  t.timestamp :created_at
39
42
  end
40
43
 
41
- ActiveRecord::Migration.create_table :posts, :force => true do |t|
44
+ ActiveRecord::Migration.create_table :posts, force: true do |t|
42
45
  t.references :user
43
46
  t.timestamp :created_at
44
47
  end
@@ -104,19 +107,19 @@ module TestGroupdate
104
107
  # day hour starts at 2 am
105
108
 
106
109
  def test_test_day_end_of_day_day_start_2am
107
- assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-04 01:59:59", false, :day_start => 2
110
+ assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-04 01:59:59", false, day_start: 2
108
111
  end
109
112
 
110
113
  def test_test_day_start_of_day_day_start_2am
111
- assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-03 02:00:00", false, :day_start => 2
114
+ assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-03 02:00:00", false, day_start: 2
112
115
  end
113
116
 
114
117
  def test_test_day_end_of_day_with_time_zone_day_start_2am
115
- assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-04 07:59:59", true, :day_start => 2
118
+ assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-04 07:59:59", true, day_start: 2
116
119
  end
117
120
 
118
121
  def test_test_day_start_of_day_with_time_zone_day_start_2am
119
- assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-03 09:00:00", true, :day_start => 2
122
+ assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-03 09:00:00", true, day_start: 2
120
123
  end
121
124
 
122
125
  # week
@@ -176,19 +179,19 @@ module TestGroupdate
176
179
  # week starting at 2am
177
180
 
178
181
  def test_week_end_of_week_day_start_2am
179
- assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-24 01:59:59", false, :day_start => 2
182
+ assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-24 01:59:59", false, day_start: 2
180
183
  end
181
184
 
182
185
  def test_week_start_of_week_day_start_2am
183
- assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-17 02:00:00", false, :day_start => 2
186
+ assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-17 02:00:00", false, day_start: 2
184
187
  end
185
188
 
186
189
  def test_week_end_of_week_day_with_time_zone_start_2am
187
- assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-24 08:59:59", true, :day_start => 2
190
+ assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-24 08:59:59", true, day_start: 2
188
191
  end
189
192
 
190
193
  def test_week_start_of_week_day_with_time_zone_start_2am
191
- assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-17 09:00:00", true, :day_start => 2
194
+ assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-17 09:00:00", true, day_start: 2
192
195
  end
193
196
 
194
197
  # month
@@ -212,19 +215,55 @@ module TestGroupdate
212
215
  # month starts at 2am
213
216
 
214
217
  def test_month_end_of_month_day_start_2am
215
- assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-04-01 01:59:59", false, :day_start => 2
218
+ assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-04-01 01:59:59", false, day_start: 2
216
219
  end
217
220
 
218
221
  def test_month_start_of_month_day_start_2am
219
- assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-03-01 02:00:00", false, :day_start => 2
222
+ assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-03-01 02:00:00", false, day_start: 2
220
223
  end
221
224
 
222
225
  def test_month_end_of_month_with_time_zone_day_start_2am
223
- assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-04-01 08:59:59", true, :day_start => 2
226
+ assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-04-01 08:59:59", true, day_start: 2
224
227
  end
225
228
 
226
229
  def test_month_start_of_month_with_time_zone_day_start_2am
227
- assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-03-01 10:00:00", true, :day_start => 2
230
+ assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-03-01 10:00:00", true, day_start: 2
231
+ end
232
+
233
+ # quarter
234
+
235
+ def test_quarter_end_of_quarter
236
+ assert_result_time :quarter, "2013-04-01 00:00:00 UTC", "2013-06-30 23:59:59"
237
+ end
238
+
239
+ def test_quarter_start_of_quarter
240
+ assert_result_time :quarter, "2013-04-01 00:00:00 UTC", "2013-04-01 00:00:00"
241
+ end
242
+
243
+ def test_quarter_end_of_quarter_with_time_zone
244
+ assert_result_time :quarter, "2013-04-01 00:00:00 PDT", "2013-07-01 06:59:59", true
245
+ end
246
+
247
+ def test_quarter_start_of_quarter_with_time_zone
248
+ assert_result_time :quarter, "2013-04-01 00:00:00 PDT", "2013-04-01 07:00:00", true
249
+ end
250
+
251
+ # quarter starts at 2am
252
+
253
+ def test_quarter_end_of_quarter_day_start_2am
254
+ assert_result_time :quarter, "2013-04-01 02:00:00 UTC", "2013-07-01 01:59:59", false, day_start: 2
255
+ end
256
+
257
+ def test_quarter_start_of_quarter_day_start_2am
258
+ assert_result_time :quarter, "2013-04-01 02:00:00 UTC", "2013-04-01 02:00:00", false, day_start: 2
259
+ end
260
+
261
+ def test_quarter_end_of_quarter_with_time_zone_day_start_2am
262
+ assert_result_time :quarter, "2013-01-01 02:00:00 PST", "2013-04-01 08:59:59", true, day_start: 2
263
+ end
264
+
265
+ def test_quarter_start_of_quarter_with_time_zone_day_start_2am
266
+ assert_result_time :quarter, "2013-01-01 02:00:00 PST", "2013-01-01 10:00:00", true, day_start: 2
228
267
  end
229
268
 
230
269
  # year
@@ -248,19 +287,19 @@ module TestGroupdate
248
287
  # year starts at 2am
249
288
 
250
289
  def test_year_end_of_year_day_start_2am
251
- assert_result_time :year, "2013-01-01 02:00:00 UTC", "2014-01-01 01:59:59", false, :day_start => 2
290
+ assert_result_time :year, "2013-01-01 02:00:00 UTC", "2014-01-01 01:59:59", false, day_start: 2
252
291
  end
253
292
 
254
293
  def test_year_start_of_year_day_start_2am
255
- assert_result_time :year, "2013-01-01 02:00:00 UTC", "2013-01-01 02:00:00", false, :day_start => 2
294
+ assert_result_time :year, "2013-01-01 02:00:00 UTC", "2013-01-01 02:00:00", false, day_start: 2
256
295
  end
257
296
 
258
297
  def test_year_end_of_year_with_time_zone_day_start_2am
259
- assert_result_time :year, "2013-01-01 02:00:00 PST", "2014-01-01 09:59:59", true, :day_start => 2
298
+ assert_result_time :year, "2013-01-01 02:00:00 PST", "2014-01-01 09:59:59", true, day_start: 2
260
299
  end
261
300
 
262
301
  def test_year_start_of_year_with_time_zone_day_start_2am
263
- assert_result_time :year, "2013-01-01 02:00:00 PST", "2013-01-01 10:00:00", true, :day_start => 2
302
+ assert_result_time :year, "2013-01-01 02:00:00 PST", "2013-01-01 10:00:00", true, day_start: 2
264
303
  end
265
304
 
266
305
  # hour of day
@@ -284,19 +323,19 @@ module TestGroupdate
284
323
  # hour of day starts at 2am
285
324
 
286
325
  def test_hour_of_day_end_of_day_day_start_2am
287
- assert_result :hour_of_day, 23, "2013-01-01 01:59:59", false, :day_start => 2
326
+ assert_result :hour_of_day, 23, "2013-01-01 01:59:59", false, day_start: 2
288
327
  end
289
328
 
290
329
  def test_hour_of_day_start_of_day_day_start_2am
291
- assert_result :hour_of_day, 0, "2013-01-01 02:00:00", false, :day_start => 2
330
+ assert_result :hour_of_day, 0, "2013-01-01 02:00:00", false, day_start: 2
292
331
  end
293
332
 
294
333
  def test_hour_of_day_end_of_day_with_time_zone_day_start_2am
295
- assert_result :hour_of_day, 23, "2013-01-01 09:59:59", true, :day_start => 2
334
+ assert_result :hour_of_day, 23, "2013-01-01 09:59:59", true, day_start: 2
296
335
  end
297
336
 
298
337
  def test_hour_of_day_start_of_day_with_time_zone_day_start_2am
299
- assert_result :hour_of_day, 0, "2013-01-01 10:00:00", true, :day_start => 2
338
+ assert_result :hour_of_day, 0, "2013-01-01 10:00:00", true, day_start: 2
300
339
  end
301
340
 
302
341
  # day of week
@@ -320,19 +359,19 @@ module TestGroupdate
320
359
  # day of week starts at 2am
321
360
 
322
361
  def test_day_of_week_end_of_day_day_start_2am
323
- assert_result :day_of_week, 3, "2013-01-03 01:59:59", false, :day_start => 2
362
+ assert_result :day_of_week, 3, "2013-01-03 01:59:59", false, day_start: 2
324
363
  end
325
364
 
326
365
  def test_day_of_week_start_of_day_day_start_2am
327
- assert_result :day_of_week, 3, "2013-01-02 02:00:00", false, :day_start => 2
366
+ assert_result :day_of_week, 3, "2013-01-02 02:00:00", false, day_start: 2
328
367
  end
329
368
 
330
369
  def test_day_of_week_end_of_day_with_time_zone_day_start_2am
331
- assert_result :day_of_week, 3, "2013-01-03 09:59:59", true, :day_start => 2
370
+ assert_result :day_of_week, 3, "2013-01-03 09:59:59", true, day_start: 2
332
371
  end
333
372
 
334
373
  def test_day_of_week_start_of_day_with_time_zone_day_start_2am
335
- assert_result :day_of_week, 3, "2013-01-02 10:00:00", true, :day_start => 2
374
+ assert_result :day_of_week, 3, "2013-01-02 10:00:00", true, day_start: 2
336
375
  end
337
376
 
338
377
  # day of month
@@ -360,19 +399,19 @@ module TestGroupdate
360
399
  # day of month starts at 2am
361
400
 
362
401
  def test_day_of_month_end_of_day_day_start_2am
363
- assert_result :day_of_month, 31, "2013-01-01 01:59:59", false, :day_start => 2
402
+ assert_result :day_of_month, 31, "2013-01-01 01:59:59", false, day_start: 2
364
403
  end
365
404
 
366
405
  def test_day_of_month_start_of_day_day_start_2am
367
- assert_result :day_of_month, 1, "2013-01-01 02:00:00", false, :day_start => 2
406
+ assert_result :day_of_month, 1, "2013-01-01 02:00:00", false, day_start: 2
368
407
  end
369
408
 
370
409
  def test_day_of_month_end_of_day_with_time_zone_day_start_2am
371
- assert_result :day_of_month, 31, "2013-01-01 09:59:59", true, :day_start => 2
410
+ assert_result :day_of_month, 31, "2013-01-01 09:59:59", true, day_start: 2
372
411
  end
373
412
 
374
413
  def test_day_of_month_start_of_day_with_time_zone_day_start_2am
375
- assert_result :day_of_month, 1, "2013-01-01 10:00:00", true, :day_start => 2
414
+ assert_result :day_of_month, 1, "2013-01-01 10:00:00", true, day_start: 2
376
415
  end
377
416
 
378
417
  # month of year
@@ -396,19 +435,19 @@ module TestGroupdate
396
435
  # month of year starts at 2am
397
436
 
398
437
  def test_month_of_year_end_of_month_day_start_2am
399
- assert_result :month_of_year, 12, "2013-01-01 01:59:59", false, :day_start => 2
438
+ assert_result :month_of_year, 12, "2013-01-01 01:59:59", false, day_start: 2
400
439
  end
401
440
 
402
441
  def test_month_of_year_start_of_month_day_start_2am
403
- assert_result :month_of_year, 1, "2013-01-01 02:00:00", false, :day_start => 2
442
+ assert_result :month_of_year, 1, "2013-01-01 02:00:00", false, day_start: 2
404
443
  end
405
444
 
406
445
  def test_month_of_year_end_of_month_with_time_zone_day_start_2am
407
- assert_result :month_of_year, 12, "2013-01-01 09:59:59", true, :day_start => 2
446
+ assert_result :month_of_year, 12, "2013-01-01 09:59:59", true, day_start: 2
408
447
  end
409
448
 
410
449
  def test_month_of_year_start_of_month_with_time_zone_day_start_2am
411
- assert_result :month_of_year, 1, "2013-01-01 10:00:00", true, :day_start => 2
450
+ assert_result :month_of_year, 1, "2013-01-01 10:00:00", true, day_start: 2
412
451
  end
413
452
 
414
453
  # zeros
@@ -465,6 +504,14 @@ module TestGroupdate
465
504
  assert_zeros :month, "2013-04-16 20:00:00 PDT", ["2013-03-01 00:00:00 PST", "2013-04-01 00:00:00 PDT", "2013-05-01 00:00:00 PDT"], "2013-03-01 00:00:00 PST", "2013-05-31 23:59:59 PDT", true
466
505
  end
467
506
 
507
+ def test_zeros_quarter
508
+ assert_zeros :quarter, "2013-04-16 20:00:00 UTC", ["2013-01-01 00:00:00 UTC", "2013-04-01 00:00:00 UTC", "2013-07-01 00:00:00 UTC"], "2013-01-01 00:00:00 UTC", "2013-09-30 23:59:59 UTC"
509
+ end
510
+
511
+ def test_zeros_quarter_time_zone
512
+ assert_zeros :quarter, "2013-04-16 20:00:00 PDT", ["2013-01-01 00:00:00 PST", "2013-04-01 00:00:00 PDT", "2013-07-01 00:00:00 PDT"], "2013-01-01 00:00:00 PST", "2013-09-30 23:59:59 PDT", true
513
+ end
514
+
468
515
  def test_zeros_year
469
516
  assert_zeros :year, "2013-04-16 20:00:00 UTC", ["2012-01-01 00:00:00 UTC", "2013-01-01 00:00:00 UTC", "2014-01-01 00:00:00 UTC"], "2012-01-01 00:00:00 UTC", "2014-12-31 23:59:59 UTC"
470
517
  end
@@ -573,10 +620,12 @@ module TestGroupdate
573
620
  end
574
621
 
575
622
  def test_order_hour_of_day_reverse
623
+ skip if ActiveRecord::VERSION::MAJOR == 5
576
624
  assert_equal 23, User.group_by_hour_of_day(:created_at).reverse_order.count.keys.first
577
625
  end
578
626
 
579
627
  def test_order_hour_of_day_order_reverse
628
+ skip if ActiveRecord::VERSION::MAJOR == 5
580
629
  assert_equal 0, User.group_by_hour_of_day(:created_at).order("hour_of_day desc").reverse_order.count.keys.first
581
630
  end
582
631
 
@@ -688,22 +737,22 @@ module TestGroupdate
688
737
  end
689
738
 
690
739
  def test_last
691
- create_user "2012-05-01 00:00:00 UTC"
692
- create_user "2014-05-01 00:00:00 UTC"
740
+ create_user "#{this_year - 3}-01-01 00:00:00 UTC"
741
+ create_user "#{this_year - 1}-01-01 00:00:00 UTC"
693
742
  expected = {
694
- utc.parse("2013-01-01 00:00:00 UTC") => 0,
695
- utc.parse("2014-01-01 00:00:00 UTC") => 1,
696
- utc.parse("2015-01-01 00:00:00 UTC") => 0
743
+ utc.parse("#{this_year - 2}-01-01 00:00:00 UTC") => 0,
744
+ utc.parse("#{this_year - 1}-01-01 00:00:00 UTC") => 1,
745
+ utc.parse("#{this_year}-01-01 00:00:00 UTC") => 0
697
746
  }
698
747
  assert_equal expected, User.group_by_year(:created_at, last: 3).count
699
748
  end
700
749
 
701
750
  def test_current
702
- create_user "2012-05-01 00:00:00 UTC"
703
- create_user "2014-05-01 00:00:00 UTC"
751
+ create_user "#{this_year - 3}-01-01 00:00:00 UTC"
752
+ create_user "#{this_year - 1}-01-01 00:00:00 UTC"
704
753
  expected = {
705
- utc.parse("2013-01-01 00:00:00 UTC") => 0,
706
- utc.parse("2014-01-01 00:00:00 UTC") => 1
754
+ utc.parse("#{this_year - 2}-01-01 00:00:00 UTC") => 0,
755
+ utc.parse("#{this_year - 1}-01-01 00:00:00 UTC") => 1
707
756
  }
708
757
  assert_equal expected, User.group_by_year(:created_at, last: 2, current: false).count
709
758
  end
@@ -718,6 +767,11 @@ module TestGroupdate
718
767
  assert_format :month, "March 2014", "%B %Y"
719
768
  end
720
769
 
770
+ def test_format_quarter
771
+ create_user "2014-03-05 00:00:00 UTC"
772
+ assert_format :quarter, "January 1, 2014", "%B %-e, %Y"
773
+ end
774
+
721
775
  def test_format_year
722
776
  create_user "2014-03-01 00:00:00 UTC"
723
777
  assert_format :year, "2014", "%Y"
@@ -758,6 +812,11 @@ module TestGroupdate
758
812
  assert_equal ({"Okt" => 1}), User.group_by_day(:created_at, format: "%b", locale: :de).count
759
813
  end
760
814
 
815
+ def test_format_locale_by_symbol
816
+ create_user "2014-10-01 00:00:00 UTC"
817
+ assert_equal ({"Okt 1, 2014" => 1}), User.group_by_day(:created_at, format: :special, locale: :de).count
818
+ end
819
+
761
820
  def test_format_locale_global
762
821
  create_user "2014-10-01 00:00:00 UTC"
763
822
  I18n.locale = :de
@@ -775,7 +834,7 @@ module TestGroupdate
775
834
  # permit
776
835
 
777
836
  def test_permit
778
- assert_raises(ArgumentError, "Unpermitted period") { User.group_by_period(:day, :created_at, permit: %w[week]).count }
837
+ assert_raises(ArgumentError, "Unpermitted period") { User.group_by_period(:day, :created_at, permit: %w(week)).count }
779
838
  end
780
839
 
781
840
  def test_permit_bad_period
@@ -791,11 +850,22 @@ module TestGroupdate
791
850
  end
792
851
 
793
852
  def test_permit_symbol_strings
794
- assert_equal ({}), User.group_by_period(:day, :created_at, permit: %w[day]).count
853
+ assert_equal ({}), User.group_by_period(:day, :created_at, permit: %w(day)).count
795
854
  end
796
855
 
797
856
  def test_permit_string_strings
798
- assert_equal ({}), User.group_by_period("day", :created_at, permit: %w[day]).count
857
+ assert_equal ({}), User.group_by_period("day", :created_at, permit: %w(day)).count
858
+ end
859
+
860
+ # default value
861
+
862
+ def test_default_value
863
+ create_user "#{this_year}-01-01 00:00:00 UTC"
864
+ expected = {
865
+ utc.parse("#{this_year - 1}-01-01 00:00:00 UTC") => nil,
866
+ utc.parse("#{this_year}-01-01 00:00:00 UTC") => 1
867
+ }
868
+ assert_equal expected, User.group_by_year(:created_at, last: 2, default_value: nil).count
799
869
  end
800
870
 
801
871
  # associations
@@ -870,7 +940,11 @@ module TestGroupdate
870
940
  end
871
941
 
872
942
  def create_user(created_at, score = 1)
873
- User.create! :name => "Andrew", :score => score, :created_at => utc.parse(created_at)
943
+ User.create! name: "Andrew", score: score, created_at: utc.parse(created_at)
944
+ end
945
+
946
+ def this_year
947
+ Time.now.utc.year
874
948
  end
875
949
 
876
950
  def utc
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groupdate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-29 00:00:00.000000000 Z
11
+ date: 2016-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -122,10 +122,6 @@ files:
122
122
  - LICENSE.txt
123
123
  - README.md
124
124
  - Rakefile
125
- - gemfiles/activerecord31.gemfile
126
- - gemfiles/activerecord32.gemfile
127
- - gemfiles/activerecord40.gemfile
128
- - gemfiles/activerecord41.gemfile
129
125
  - groupdate.gemspec
130
126
  - lib/groupdate.rb
131
127
  - lib/groupdate/active_record.rb
@@ -136,6 +132,11 @@ files:
136
132
  - lib/groupdate/series.rb
137
133
  - lib/groupdate/version.rb
138
134
  - test/enumerable_test.rb
135
+ - test/gemfiles/activerecord31.gemfile
136
+ - test/gemfiles/activerecord32.gemfile
137
+ - test/gemfiles/activerecord40.gemfile
138
+ - test/gemfiles/activerecord41.gemfile
139
+ - test/gemfiles/activerecord50.gemfile
139
140
  - test/mysql_test.rb
140
141
  - test/postgresql_test.rb
141
142
  - test/test_helper.rb
@@ -159,12 +160,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
160
  version: '0'
160
161
  requirements: []
161
162
  rubyforge_project:
162
- rubygems_version: 2.4.5
163
+ rubygems_version: 2.4.5.1
163
164
  signing_key:
164
165
  specification_version: 4
165
166
  summary: The simplest way to group temporal data
166
167
  test_files:
167
168
  - test/enumerable_test.rb
169
+ - test/gemfiles/activerecord31.gemfile
170
+ - test/gemfiles/activerecord32.gemfile
171
+ - test/gemfiles/activerecord40.gemfile
172
+ - test/gemfiles/activerecord41.gemfile
173
+ - test/gemfiles/activerecord50.gemfile
168
174
  - test/mysql_test.rb
169
175
  - test/postgresql_test.rb
170
176
  - test/test_helper.rb