groupdate 2.5.0 → 2.5.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.
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