calculate_in_group 0.0.1 → 0.0.2

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
  SHA256:
3
- metadata.gz: c5a7b900a5d475fc22804562ef0bac072706dcb251219b5be5c06c302f5dd75a
4
- data.tar.gz: 73fa7ceb228a9704acc409ba00b99af5d307b9cfe8739a09496097481ee5b7d0
3
+ metadata.gz: a355bb8d2b965bf9e26129775305e20c02b7d8fed65331e63aa058c4ea4d26d7
4
+ data.tar.gz: 2179b1820693525eea6ce4ba9a28d25f0c2351133c0dccad55ac90a0130178d9
5
5
  SHA512:
6
- metadata.gz: 80974131cdfb53dfc1279c516a61c72565ae29a3cc2bd181823298158a7fae24360e7fae377ab4e174984c2d4657650b93ac4d3b5b647f4bca084998d81667ab
7
- data.tar.gz: 0d6c1989fa40e2dd60e77f1897467a05dd36caf2ee581d60884e176688c0bf501c7ecb0cc940c3eb04ef25bef5f04c2689e51a70db07ead31925ebd2ae55e027
6
+ metadata.gz: 4c4988070914bff246095f5fdce43e3fa77aa1f020760fd6857ce88750f2c675e301c61c4aa9ae9cb9d81a144f498fcf6a840284f62bf8bf45d2654710cf91f7
7
+ data.tar.gz: 302d7f0906ddee7951cd7a23cb2b4248de37bb3a6686e10b7d7f261b5615a39edd92747a7e4232c50709d22ed9fc4c5fbd8f73539ca01fa706b0cec065a36edf
data/README.md CHANGED
@@ -1,11 +1,46 @@
1
- # CalculateInGroup
2
- Short description and motivation.
1
+ # calculate_in_group
2
+
3
+ [![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
4
+ [![https://www.patreon.com/igorkasyanchuk](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/patron.svg?raw=true)](https://www.patreon.com/igorkasyanchuk)
5
+
6
+ Group ActiveRecord models with ranges. No more need to SQL with complex statements. Make your life easier :)
7
+
8
+ Can solve problems like "I need to group users by age in different categories." or "I need to do some calculations for the reports/charts".
9
+
10
+ Easy to use, just add to Gemfile `gem "calculate_in_group"` and call `calculate_in_group` on your model.
3
11
 
4
12
  ## Usage
5
- How to use my plugin.
13
+
14
+ See below how to group your model by ranges or arrays and run aggregations for them in one SQL query.
15
+
16
+ ```ruby
17
+ # Grouping can be used with :count, :average, :sum, :maximum, :minimum.
18
+
19
+ # Group with Ranges
20
+ User.calculate_in_group(:count, :age, [...10, 10...50, 50..] # => {"...10"=>1, "10...50"=>3, "50.."=>3}
21
+ User.calculate_in_group(:count, :created_at, { "old" => 12.hours.ago..1.minutes.ago, "new" => Time.now..10.hours.from_now }) # => {"old" => 2, "new" => 1}
22
+
23
+ # Group with arrays or just values
24
+ User.calculate_in_group(:count, :role, "with_permissions" => ["admin", "moderator"], "no_permissions" => "user") # => {"with_permissions" => 3, "no_permissions" => 3}
25
+
26
+ # Other agg functions
27
+ User.calculate_in_group(:average, :age, "young" => 0..25, "old" => 60..100) # => {"young" => 11.0, "old" => 80.0}
28
+ User.calculate_in_group(:average, :age, "young" => 0..25, "old" => 60...100) # => {"young" => 11.0, "old" => 60.0}
29
+ User.calculate_in_group(:maximum, :age, "young" => 0..25, "old" => 60..100) # => {"young" => 20, "old" => 100}
30
+ User.calculate_in_group(:minimum, :age, "young" => 0..25, "old" => 60..100) # => {"young" => 3, "old" => 60}
31
+ User.calculate_in_group(:sum, :age, "young" => 0..25, "old" => 60..100) # => {"young" => 33, "old" => 160}
32
+ User.calculate_in_group(:sum, :age, {"young" => 0..25, "old" => 60..100}) # => {"young" => 33, "old" => 160}
33
+
34
+ # You can specify "other values" (with custom label) which are out of ranges
35
+ User.calculate_in_group(:count, :age, {"young" => 10, "average" => 25, "old" => 60}, {include_nil: "OTHER"}) # => {"young" => 1, "old" => 1, "OTHER" => 7}
36
+
37
+ # You can specify default value for keys which are missing in query
38
+ User.calculate_in_group(:count, :age, {"young" => 10, "average" => 25, "old" => 60}, { default_for_missing: 0 }) # => {"young" => 1, "old" => 1, "average" => 0}
39
+
40
+ # SEE MORE EXAMLES in test/calculate_in_group_test.rb
41
+ ```
6
42
 
7
43
  ## Installation
8
- Add this line to your application's Gemfile:
9
44
 
10
45
  ```ruby
11
46
  gem "calculate_in_group"
@@ -16,19 +51,16 @@ And then execute:
16
51
  $ bundle
17
52
  ```
18
53
 
19
- Or install it yourself as:
20
- ```bash
21
- $ gem install calculate_in_group
22
- ```
23
-
24
54
  ## Testing
25
55
 
26
- ruby test/calculate_in_group_test.rb
56
+ `ruby test/calculate_in_group_test.rb`.
27
57
 
28
58
  Not sure, why rake test doesn't works for me :)
29
59
 
30
60
  ## Contributing
31
- Contribution directions go here.
61
+
62
+ You are welcome to contribute or share your ideas.
32
63
 
33
64
  ## License
65
+
34
66
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,3 +1,3 @@
1
1
  module CalculateInGroup
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -3,10 +3,12 @@ require "calculate_in_group/railtie"
3
3
 
4
4
  module CalculateInGroup
5
5
  module QueryMethods
6
- def calculate_in_group(operation_type, field, groups = {}, options = {})
6
+ def calculate_in_group(operation_type, field, groups, options = {})
7
7
  # check if arguments are good
8
+ raise ArgumentError.new("Please specify options for groups. Check the documentation") if groups.empty?
8
9
  raise ArgumentError.new("Operation #{operation_type} not supported. Try to use: :count, :average, :sum, :maximum, :minimum") if ![:count, :average, :sum, :maximum, :minimum].include?(operation_type.to_s.to_sym)
9
10
  raise ArgumentError.new("Column #{field} not found in `#{table_name}`") if !column_names.include?(field.to_s)
11
+ raise ArgumentError.new("Groups `#{groups}` can be array or hash. Check the documentation") unless groups.is_a?(Array) || groups.is_a?(Hash)
10
12
 
11
13
  # init variables
12
14
  table = self.arel_table
@@ -14,14 +16,29 @@ module CalculateInGroup
14
16
  operation_attribute = "__#{operation_type}_all"
15
17
  query = Arel::Nodes::Case.new
16
18
  conditions = []
19
+ groupings = groups.is_a?(Array) ? groups.inject({}) {|res, e| res[e.to_s] = e; res} : groups
17
20
 
18
21
  # build conditions
19
- groups.each do |(k, v)|
22
+ groupings.each do |(k, v)|
20
23
  c = case v
21
24
  when Range
22
25
  # range could be endless, so we need to compact and build correct SQL for "between"
23
26
  a = table[field].gteq(v.begin) if v.begin
24
- b = table[field].lteq(v.end) if v.end
27
+ if v.end
28
+ b = if v.exclude_end? # e.g. 5...10 => [5,6,7,8,9]
29
+ # [3] pry(#<CalculateInGroupTest>)> a = 0...10
30
+ # a.to_a => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
31
+ # [4] pry(#<CalculateInGroupTest>)> a.exclude_end?
32
+ # => true
33
+ table[field].lt(v.end)
34
+ else
35
+ # [1] pry(#<CalculateInGroupTest>)> a = 0..10
36
+ # a.to_a => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
37
+ # [2] pry(#<CalculateInGroupTest>)> a.exclude_end?
38
+ # => false
39
+ table[field].lteq(v.end) # e.g. 5..10 => [5,6,7,8,9,10]
40
+ end
41
+ end
25
42
  [a, b].compact.inject(&:and)
26
43
  when Array
27
44
  # SQL "IN"
@@ -60,7 +77,7 @@ module CalculateInGroup
60
77
 
61
78
  # check if we need to build full hash with all grouped fields
62
79
  if options.has_key?(:default_for_missing)
63
- (groups.keys.map(&:to_s) - result.keys).each do |k|
80
+ (groupings.keys.map(&:to_s) - result.keys).each do |k|
64
81
  result[k] = options[:default_for_missing]
65
82
  end
66
83
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calculate_in_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk