calculate-all 0.3.1 → 0.4.0

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
  SHA256:
3
- metadata.gz: f15872602a35e41a3619150837e69840e82da1d2a42bd058a7c6986092024a97
4
- data.tar.gz: f3665c7b64a083c5f24fd861e6ef22a5dde177e4a68eab9638449e26f89e2dc7
3
+ metadata.gz: d3928cde50fac04c8f8602ab9e83c685d190e8466febbb2c0314cf962182f99c
4
+ data.tar.gz: 83f9636ffda1f25e0faabc5454a4c731648371ba20572e5df53357f72e9b5708
5
5
  SHA512:
6
- metadata.gz: 5d7ed4f530ff56be9378644b209add40b415bedf363425599a10a7d3fc14b1d0cb0920dd6744f5c334ae83f0ec9296b161d8bc387a2e4f93c1a849d7764e571a
7
- data.tar.gz: 164b353805bf7fdd12e10087186c20a805231f68922c4d46a42e7c8f02307165d36592cbcf0c67d2a27f61e6dbb43c9cd7ab2934b9a64112ef239cf4e50edf05
6
+ metadata.gz: 0a13ddf4a236a27bebbdf1bf7f316c1137eff5eb6cfb3a0589a0f91dfa0548b6167cc4441173ca0ce4b174a156092aa50185ec5f111e54f6c0e75ee3c738d430
7
+ data.tar.gz: 95f229487220d5bb23ef2a6a50b9aef7a782e25b627c3d87716690a0673fc6890e28c3ab023481f475837a0d595baac84078ef31841c0e3b135081c61eda47b9
@@ -8,6 +8,8 @@ jobs:
8
8
  include:
9
9
  - ruby: "3.4"
10
10
  gemfile: Gemfile
11
+ - ruby: "3.2"
12
+ gemfile: gemfiles/activerecord71.gemfile
11
13
  - ruby: "3.1"
12
14
  gemfile: gemfiles/activerecord70.gemfile
13
15
  - ruby: "3.0"
@@ -16,11 +18,9 @@ jobs:
16
18
  gemfile: gemfiles/activerecord60.gemfile
17
19
  - ruby: "2.6"
18
20
  gemfile: gemfiles/activerecord52.gemfile
19
- - ruby: "2.6"
20
- gemfile: gemfiles/activerecord51.gemfile
21
21
  - ruby: "2.6"
22
22
  gemfile: gemfiles/activerecord50.gemfile
23
- - ruby: "2.3"
23
+ - ruby: "2.6"
24
24
  gemfile: gemfiles/activerecord42.gemfile
25
25
  runs-on: ubuntu-latest
26
26
  env:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.4.0
2
+
3
+ * Add #async_calculate_all for rails > 7.1
4
+ * Drop support for ruby < 2.6, groupdate < 4
5
+
1
6
  ## 0.3.1
2
7
 
3
8
  * Fix some arguments exceptions
data/README.md CHANGED
@@ -8,7 +8,10 @@ in a single request, with support for grouping.
8
8
 
9
9
  Should be useful for dashboards, timeseries stats, and charts.
10
10
 
11
- Currently tested with PostgreSQL, MySQL and SQLite3, ruby >= 2.3, rails >= 4, groupdate >= 4.
11
+ Currently tested with PostgreSQL, MySQL and SQLite3, ruby >= 2.6, rails >= 4, groupdate >= 4.
12
+
13
+ With rails >= 7.1, `#async_calculate_all` is also available, which does the same but in a separate
14
+ db connection and ruby thread, and returns `ActiveRecord::Promise`
12
15
 
13
16
  ## Usage
14
17
 
@@ -48,6 +51,16 @@ stats = Order.group(:department_id).group(:payment_method).order(:payment_method
48
51
  # }
49
52
  ```
50
53
 
54
+ ```ruby
55
+ stats_by_department = Order.group(:department_id).async_calculate_all(:count, :price_sum)
56
+ # continue with some other expensive stuff
57
+
58
+ # later, in some view
59
+ stats_by_department.value.each do |department_id, stats|
60
+ # ...
61
+ end
62
+ ```
63
+
51
64
  ## Rationale
52
65
 
53
66
  Active Record makes it really easy to use most common database aggregate functions like COUNT(), MAX(), MIN(), AVG(), SUM().
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 2.3.0'
21
+ spec.required_ruby_version = ">= 2.6.0"
22
22
 
23
23
  spec.add_dependency "activesupport", ">= 4.0.0"
24
24
  end
@@ -6,7 +6,7 @@ gem "rake"
6
6
  gem "minitest", "~> 5.0"
7
7
  gem "minitest-reporters"
8
8
  gem "activerecord", "~> 4.2.0"
9
- gem "groupdate", "~> 3.0.0"
9
+ gem "groupdate", "~> 4.0.0"
10
10
  gem "pg", "~> 0.15"
11
11
  gem "mysql2"
12
12
  gem "sqlite3", "~> 1.3.0"
@@ -5,8 +5,8 @@ gemspec path: ".."
5
5
  gem "rake"
6
6
  gem "minitest"
7
7
  gem "minitest-reporters"
8
- gem "activerecord", "~> 5.1.0"
9
- gem "groupdate", "~> 5.0.0"
8
+ gem "activerecord", "~> 7.1.0"
9
+ gem "groupdate", "~> 6.0.0"
10
10
  gem "pg"
11
11
  gem "mysql2"
12
- gem "sqlite3"
12
+ gem "sqlite3", "~> 1.4"
@@ -1,3 +1,3 @@
1
1
  module CalculateAll
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/calculate-all.rb CHANGED
@@ -11,7 +11,7 @@ module CalculateAll
11
11
  return_plain_values = true
12
12
  end
13
13
 
14
- named_expressions = expression_shortcuts.map { |name| [name, name] }.to_h.merge(named_expressions)
14
+ named_expressions = expression_shortcuts.index_by(&:itself).merge(named_expressions)
15
15
 
16
16
  named_expressions.transform_values! do |shortcut|
17
17
  Helpers.decode_expression_shortcut(shortcut, group_values)
@@ -25,48 +25,55 @@ module CalculateAll
25
25
  value_mapping = named_expressions.transform_values { |column| columns.index(column) }
26
26
  columns.map! { |column| column.is_a?(String) ? Arel.sql(column) : column }
27
27
 
28
- results = {}
29
- pluck(*columns).each do |row|
30
- # If pluck called with a single argument
31
- # it will return an array of scalars instead of array of arrays
32
- row = [row] if columns.size == 1
33
-
34
- key = if group_values.size == 0
35
- :ALL
36
- elsif group_values.size == 1
37
- # If only one group is provided, the resulting key is just a scalar value
38
- row.first
39
- else
40
- # if multiple groups, the key will be an array.
41
- row.first(group_values.size)
42
- end
28
+ pluck(*columns).then do |rows|
29
+ results = rows.to_h do |row|
30
+ # If pluck called with a single argument
31
+ # it will return an array of scalars instead of array of arrays
32
+ row = [row] if columns.size == 1
43
33
 
44
- value = value_mapping.transform_values { |index| row[index] }
34
+ key = if group_values.size == 0
35
+ :ALL
36
+ elsif group_values.size == 1
37
+ # If only one group is provided, the resulting key is just a scalar value
38
+ row.first
39
+ else
40
+ # if multiple groups, the key will be an array.
41
+ row.first(group_values.size)
42
+ end
45
43
 
46
- value = value.values.last if return_plain_values
44
+ value = value_mapping.transform_values { |index| row[index] }
47
45
 
48
- results[key] = value
49
- end
46
+ value = value.values.last if return_plain_values
50
47
 
51
- # Additional groupdate magic of filling empty periods with defaults
52
- if defined?(Groupdate.process_result)
53
- # Since that hash is the same instance for every backfilled row, at least
54
- # freeze it to prevent surprise modifications across multiple rows in the calling code.
55
- default_value = return_plain_values ? nil : {}.freeze
56
- results = Groupdate.process_result(self, results, default_value: default_value)
57
- end
48
+ [key, value]
49
+ end
50
+
51
+ # Additional groupdate magic of filling empty periods with defaults
52
+ if defined?(Groupdate.process_result)
53
+ # Since that hash is the same instance for every backfilled row, at least
54
+ # freeze it to prevent surprise modifications across multiple rows in the calling code.
55
+ default_value = return_plain_values ? nil : {}.freeze
56
+ results = Groupdate.process_result(self, results, default_value: default_value)
57
+ end
58
58
 
59
- if block
60
- results.transform_values! do |value|
61
- return_plain_values ? block.call(value) : block.call(**value)
59
+ if block
60
+ results.transform_values! do |value|
61
+ return_plain_values ? block.call(value) : block.call(**value)
62
+ end
63
+ end
64
+
65
+ # Return unwrapped hash directly for scope without any .group()
66
+ if group_values.empty?
67
+ results[:ALL]
68
+ else
69
+ results
62
70
  end
63
71
  end
72
+ end
64
73
 
65
- # Return unwrapped hash directly for scope without any .group()
66
- if group_values.empty?
67
- results[:ALL]
68
- else
69
- results
74
+ if Gem::Version.new(ActiveRecord.version) >= Gem::Version.new('7.1.0')
75
+ def async_calculate_all(*expression_shortcuts, **named_expressions, &block)
76
+ async.calculate_all(*expression_shortcuts, **named_expressions, &block)
70
77
  end
71
78
  end
72
79
 
@@ -103,9 +110,16 @@ module CalculateAll
103
110
  end
104
111
 
105
112
  module Querying
106
- # @see CalculateAll#calculate_all
107
- def calculate_all(*args, **kwargs, &block)
108
- all.calculate_all(*args, **kwargs, &block)
113
+ # see CalculateAll#calculate_all
114
+ def calculate_all(*expression_shortcuts, **named_expressions, &block)
115
+ all.calculate_all(*expression_shortcuts, **named_expressions, &block)
116
+ end
117
+
118
+ if Gem::Version.new(ActiveRecord.version) >= Gem::Version.new('7.1.0')
119
+ # see CalculateAll#async_calculate_all
120
+ def async_calculate_all(*expression_shortcuts, **named_expressions, &block)
121
+ all.async_calculate_all(*expression_shortcuts, **named_expressions, &block)
122
+ end
109
123
  end
110
124
  end
111
125
  end
@@ -117,9 +131,4 @@ ActiveSupport.on_load(:active_record) do
117
131
  # Make the calculate_all method available for all ActiveRecord::Base classes
118
132
  # You can for example call Orders.calculate_all(:count, :sum_cents)
119
133
  ActiveRecord::Base.extend CalculateAll::Querying
120
-
121
- # A hack for groupdate 3.0 since it checks if the calculate_all method is defined
122
- # on the ActiveRecord::Calculations module. It is never called but it is just
123
- # needed for the check.
124
- ActiveRecord::Calculations.include CalculateAll::Querying
125
134
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calculate-all
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Trofimenko
@@ -42,11 +42,11 @@ files:
42
42
  - calculate-all.gemspec
43
43
  - gemfiles/activerecord42.gemfile
44
44
  - gemfiles/activerecord50.gemfile
45
- - gemfiles/activerecord51.gemfile
46
45
  - gemfiles/activerecord52.gemfile
47
46
  - gemfiles/activerecord60.gemfile
48
47
  - gemfiles/activerecord61.gemfile
49
48
  - gemfiles/activerecord70.gemfile
49
+ - gemfiles/activerecord71.gemfile
50
50
  - lib/calculate-all.rb
51
51
  - lib/calculate-all/version.rb
52
52
  homepage: http://github.com/codesnik/calculate-all
@@ -60,7 +60,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 2.3.0
63
+ version: 2.6.0
64
64
  required_rubygems_version: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="