Commit a933debf35b5f6a077e5aa29d7b7b6557fdc2e1c
1 parent
f509b2a3
Exists in
master
and in
13 other branches
Added dynamic grouping - #80
Showing
6 changed files
with
59 additions
and
4 deletions
Show diff stats
CHANGELOG.md
README.md
@@ -139,6 +139,18 @@ User.group_by_hour_of_day(:created_at, format: "%l %P").count.keys.first # 12 am | @@ -139,6 +139,18 @@ User.group_by_hour_of_day(:created_at, format: "%l %P").count.keys.first # 12 am | ||
139 | 139 | ||
140 | Takes a `String`, which is passed to [strftime](http://strfti.me/), or a `Proc`. You can pass a locale with the `locale` option. | 140 | Takes a `String`, which is passed to [strftime](http://strfti.me/), or a `Proc`. You can pass a locale with the `locale` option. |
141 | 141 | ||
142 | +### Dynamic Grouping [master, may change] | ||
143 | + | ||
144 | +```ruby | ||
145 | +User.group_by_period(:day, :created_at).count | ||
146 | +``` | ||
147 | + | ||
148 | +Limit groupings with the `permit` option. | ||
149 | + | ||
150 | +```ruby | ||
151 | +User.group_by_period(params[:period], :created_at, permit: %w[day week]).count | ||
152 | +``` | ||
153 | + | ||
142 | ## Arrays and Hashes | 154 | ## Arrays and Hashes |
143 | 155 | ||
144 | ```ruby | 156 | ```ruby |
lib/groupdate/enumerable.rb
@@ -8,4 +8,14 @@ module Enumerable | @@ -8,4 +8,14 @@ module Enumerable | ||
8 | end | 8 | end |
9 | end | 9 | end |
10 | end | 10 | end |
11 | + | ||
12 | + def group_by_period(period, options = {}, &block) | ||
13 | + # 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) | ||
15 | + if permitted_periods.include?(period.to_s) | ||
16 | + send("group_by_#{period}", options, &block) | ||
17 | + else | ||
18 | + raise ArgumentError, "Unpermitted period" | ||
19 | + end | ||
20 | + end | ||
11 | end | 21 | end |
lib/groupdate/scopes.rb
@@ -10,5 +10,15 @@ module Groupdate | @@ -10,5 +10,15 @@ module Groupdate | ||
10 | Groupdate::Magic.new(field, options).relation(args[0], self) | 10 | Groupdate::Magic.new(field, options).relation(args[0], self) |
11 | end | 11 | end |
12 | 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::FIELDS).map(&:to_sym) & Groupdate::FIELDS).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 | ||
13 | end | 23 | end |
14 | end | 24 | end |
test/enumerable_test.rb
@@ -19,6 +19,6 @@ class TestEnumerable < Minitest::Test | @@ -19,6 +19,6 @@ class TestEnumerable < Minitest::Test | ||
19 | end | 19 | end |
20 | 20 | ||
21 | def call_method(method, field, options) | 21 | def call_method(method, field, options) |
22 | - Hash[User.all.to_a.send(:"group_by_#{method}", options) { |u| u.send(field) }.map { |k, v| [k, v.size] }] | 22 | + Hash[User.all.to_a.group_by_period(method, options) { |u| u.send(field) }.map { |k, v| [k, v.size] }] |
23 | end | 23 | end |
24 | end | 24 | end |
test/test_helper.rb
@@ -739,6 +739,28 @@ module TestGroupdate | @@ -739,6 +739,28 @@ module TestGroupdate | ||
739 | assert_equal ({[1, "Sun"] => 1}), User.group(:score).group_by_week(:created_at, format: "%a").count | 739 | assert_equal ({[1, "Sun"] => 1}), User.group(:score).group_by_week(:created_at, format: "%a").count |
740 | end | 740 | end |
741 | 741 | ||
742 | + # permit | ||
743 | + | ||
744 | + def test_permit | ||
745 | + assert_raises(ArgumentError, "Unpermitted period") { User.group_by_period(:day, :created_at, permit: %w[week]).count } | ||
746 | + end | ||
747 | + | ||
748 | + def test_permit_symbol_symbols | ||
749 | + assert_equal ({}), User.group_by_period(:day, :created_at, permit: %i[day]).count | ||
750 | + end | ||
751 | + | ||
752 | + def test_permit_string_symbols | ||
753 | + assert_equal ({}), User.group_by_period("day", :created_at, permit: %i[day]).count | ||
754 | + end | ||
755 | + | ||
756 | + def test_permit_symbol_strings | ||
757 | + assert_equal ({}), User.group_by_period(:day, :created_at, permit: %w[day]).count | ||
758 | + end | ||
759 | + | ||
760 | + def test_permit_string_strings | ||
761 | + assert_equal ({}), User.group_by_period("day", :created_at, permit: %w[day]).count | ||
762 | + end | ||
763 | + | ||
742 | # associations | 764 | # associations |
743 | 765 | ||
744 | def test_associations | 766 | def test_associations |
@@ -807,7 +829,7 @@ module TestGroupdate | @@ -807,7 +829,7 @@ module TestGroupdate | ||
807 | end | 829 | end |
808 | 830 | ||
809 | def call_method(method, field, options) | 831 | def call_method(method, field, options) |
810 | - User.send(:"group_by_#{method}", field, options).count | 832 | + User.group_by_period(method, field, options).count |
811 | end | 833 | end |
812 | 834 | ||
813 | def create_user(created_at, score = 1) | 835 | def create_user(created_at, score = 1) |