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 | 139 | |
140 | 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 | 154 | ## Arrays and Hashes |
143 | 155 | |
144 | 156 | ```ruby | ... | ... |
lib/groupdate/enumerable.rb
... | ... | @@ -8,4 +8,14 @@ module Enumerable |
8 | 8 | end |
9 | 9 | end |
10 | 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 | 21 | end | ... | ... |
lib/groupdate/scopes.rb
... | ... | @@ -10,5 +10,15 @@ module Groupdate |
10 | 10 | Groupdate::Magic.new(field, options).relation(args[0], self) |
11 | 11 | end |
12 | 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 | 23 | end |
14 | 24 | end | ... | ... |
test/enumerable_test.rb
... | ... | @@ -19,6 +19,6 @@ class TestEnumerable < Minitest::Test |
19 | 19 | end |
20 | 20 | |
21 | 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 | 23 | end |
24 | 24 | end | ... | ... |
test/test_helper.rb
... | ... | @@ -739,6 +739,28 @@ module TestGroupdate |
739 | 739 | assert_equal ({[1, "Sun"] => 1}), User.group(:score).group_by_week(:created_at, format: "%a").count |
740 | 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 | 764 | # associations |
743 | 765 | |
744 | 766 | def test_associations |
... | ... | @@ -807,7 +829,7 @@ module TestGroupdate |
807 | 829 | end |
808 | 830 | |
809 | 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 | 833 | end |
812 | 834 | |
813 | 835 | def create_user(created_at, score = 1) | ... | ... |