eager_group 0.6.0 → 0.8.0

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
- SHA1:
3
- metadata.gz: 22abe02d6bafe11c49460a72d251e3686f007796
4
- data.tar.gz: c4df75c16f76a672fc4b6dcfea0f5fe80399c064
2
+ SHA256:
3
+ metadata.gz: 516b00c6397d1a6b397b165687091079118a48ed39fc0afce4542d3cf4f7f481
4
+ data.tar.gz: 9bf3083695c819003574f3971d2a592443320af92dc98c1ff36b302c87718889
5
5
  SHA512:
6
- metadata.gz: 33cd73103c6cb2597a13e640b028b7c2bfc75982ed3746355b07b758cb3810f5923fdb7967a4e102591d0aa07b51453d0473be94c2d5b2036f123e9286395ddd
7
- data.tar.gz: 61e0c3121f8504b094e11807a0f377f16c406b26973feea5a631152d0437465131720c0586870cee4e54e5f748bc01f976d3c4da78562ff741e6575a0b663002
6
+ metadata.gz: 389265b557184c2d3f3c0207340c8bd65086a38fb8e0b2b168a4c14ed37f82b5bcb0ee89ab7a48da528bfbcf2174c1c89dcc0fd917eade1de9c184cad3238e9b
7
+ data.tar.gz: 6e5e9bd946a9d333bda2087578ac47b98d57ab0cb8347adc9577f582124e1ca9a571fdddeaa28da48644aca0f9d0546f1ee323149742b2c0868d5d6c324354da
@@ -1,5 +1,25 @@
1
1
  # Next Release
2
2
 
3
+ ## 0.8.0 (10/21/2019)
4
+
5
+ * Support `has_and_belongs_to_many`
6
+
7
+ ## 0.7.2 (10/10/2019)
8
+
9
+ * Simplify `association_klass` for `first_object` and `last_object`
10
+
11
+ ## 0.7.1 (08/23/2019)
12
+
13
+ * Set `eager_group_definitions` by `mattr_accessor`
14
+
15
+ ## 0.7.0 (08/22/2019)
16
+
17
+ * Add `first_object` and `last_object` aggregation
18
+
19
+ ## 0.6.1 (03/05/2018)
20
+
21
+ * Skip preload when association is empty
22
+
3
23
  ## 0.6.0 (12/15/2018)
4
24
 
5
25
  * Support hash as `eager_group` argument
data/README.md CHANGED
@@ -1,36 +1,44 @@
1
1
  # EagerGroup
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/xinminlabs/eager_group.png)](http://travis-ci.org/xinminlabs/eager_group)
3
+ [![Build Status](https://secure.travis-ci.org/flyerhzm/eager_group.png)](http://travis-ci.org/flyerhzm/eager_group)
4
4
  [![AwesomeCode Status for
5
- xinminlabs/eager_group](https://awesomecode.io/projects/e5386790-9420-4003-831a-c9a8c8a48108/status)](https://awesomecode.io/repos/xinminlabs/eager_group)
5
+ flyerhzm/eager_group](https://awesomecode.io/projects/e5386790-9420-4003-831a-c9a8c8a48108/status)](https://awesomecode.io/repos/flyerhzm/eager_group)
6
6
 
7
- [More explaination on our blog](http://blog.xinminlabs.com/2015/06/29/eager_group/)
7
+ [More explaination on our blog](http://blog.flyerhzm.com/2015/06/29/eager_group/)
8
8
 
9
9
  Fix n+1 aggregate sql functions for rails, like
10
10
 
11
- SELECT "posts".* FROM "posts";
12
- SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 1 AND "comments"."status" = 'approved'
13
- SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 2 AND "comments"."status" = 'approved'
14
- SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 3 AND "comments"."status" = 'approved'
11
+ ```
12
+ SELECT "posts".* FROM "posts";
13
+ SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 1 AND "comments"."status" = 'approved'
14
+ SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 2 AND "comments"."status" = 'approved'
15
+ SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 3 AND "comments"."status" = 'approved'
16
+ ```
15
17
 
16
18
  =>
17
19
 
18
- SELECT "posts".* FROM "posts";
19
- SELECT COUNT(*) AS count_all, post_id AS post_id FROM "comments" WHERE "comments"."post_id" IN (1, 2, 3) AND "comments"."status" = 'approved' GROUP BY post_id;
20
+ ```
21
+ SELECT "posts".* FROM "posts";
22
+ SELECT COUNT(*) AS count_all, post_id AS post_id FROM "comments" WHERE "comments"."post_id" IN (1, 2, 3) AND "comments"."status" = 'approved' GROUP BY post_id;
23
+ ```
20
24
 
21
25
  or
22
26
 
23
- SELECT "posts".* FROM "posts";
24
- SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 1;
25
- SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 2;
26
- SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 3;
27
+ ```
28
+ SELECT "posts".* FROM "posts";
29
+ SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 1;
30
+ SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 2;
31
+ SELECT AVG("comments"."rating") AS avg_id FROM "comments" WHERE "comments"."post_id" = 3;
32
+ ```
27
33
 
28
34
  =>
29
35
 
30
- SELECT "posts".* FROM "posts";
31
- SELECT AVG("comments"."rating") AS average_comments_rating, post_id AS post_id FROM "comments" WHERE "comments"."post_id" IN (1, 2, 3) GROUP BY post_id;
36
+ ```
37
+ SELECT "posts".* FROM "posts";
38
+ SELECT AVG("comments"."rating") AS average_comments_rating, post_id AS post_id FROM "comments" WHERE "comments"."post_id" IN (1, 2, 3) GROUP BY post_id;
39
+ ```
32
40
 
33
- It supports Rails 4.x and Rails 5.x
41
+ It supports Rails 4.x, Rails 5.x and Rails 6.x
34
42
 
35
43
  ## Installation
36
44
 
@@ -42,29 +50,35 @@ gem 'eager_group'
42
50
 
43
51
  And then execute:
44
52
 
45
- $ bundle
53
+ ```
54
+ $ bundle
55
+ ```
46
56
 
47
57
  Or install it yourself as:
48
58
 
49
- $ gem install eager_group
59
+ ```
60
+ $ gem install eager_group
61
+ ```
50
62
 
51
63
  ## Usage
52
64
 
53
65
  First you need to define what aggregate function you want to eager
54
66
  load.
55
67
 
56
- class Post < ActiveRecord::Base
57
- has_many :comments
68
+ ```ruby
69
+ class Post < ActiveRecord::Base
70
+ has_many :comments
58
71
 
59
- define_eager_group :comments_average_rating, :comments, :average, :rating
60
- define_eager_group :approved_comments_count, :comments, :count, :*, -> { approved }
61
- end
72
+ define_eager_group :comments_average_rating, :comments, :average, :rating
73
+ define_eager_group :approved_comments_count, :comments, :count, :*, -> { approved }
74
+ end
62
75
 
63
- class Comment < ActiveRecord::Base
64
- belongs_to :post
76
+ class Comment < ActiveRecord::Base
77
+ belongs_to :post
65
78
 
66
- scope :approved, -> { where(status: 'approved') }
67
- end
79
+ scope :approved, -> { where(status: 'approved') }
80
+ end
81
+ ```
68
82
 
69
83
  The parameters for `define_eager_group` are as follows
70
84
 
@@ -73,18 +87,22 @@ method, it also generates a method with the same name to fetch the
73
87
  result.
74
88
  * `association`, association name you want to aggregate.
75
89
  * `aggregate_function`, aggregate sql function, can be one of `average`,
76
- `count`, `maximum`, `minimum`, `sum`.
90
+ `count`, `maximum`, `minimum`, `sum`, I define 2 additional aggregate
91
+ function `first_object` and `last_object` to eager load first and last
92
+ association objects.
77
93
  * `column_name`, aggregate column name, it can be `:*` for `count`
78
94
  * `scope`, scope is optional, it's used to filter data for aggregation.
79
95
 
80
96
  Then you can use `eager_group` to fix n+1 aggregate sql functions
81
97
  when querying
82
98
 
83
- posts = Post.all.eager_group(:comments_average_rating, :approved_comments_count)
84
- posts.each do |post|
85
- post.comments_average_rating
86
- post.approved_comments_count
87
- end
99
+ ```ruby
100
+ posts = Post.all.eager_group(:comments_average_rating, :approved_comments_count)
101
+ posts.each do |post|
102
+ post.comments_average_rating
103
+ post.approved_comments_count
104
+ end
105
+ ```
88
106
 
89
107
  EagerGroup will execute `GROUP BY` sqls for you then set the value of
90
108
  attributes.
@@ -93,13 +111,51 @@ attributes.
93
111
  You can call the `definition_name` directly for convenience,
94
112
  but it would not help you to fix n+1 aggregate sql issue.
95
113
 
96
- post = Post.first
97
- post.commets_average_rating
98
- post.approved_comments_count
114
+ ```
115
+ post = Post.first
116
+ post.commets_average_rating
117
+ post.approved_comments_count
118
+ ```
99
119
 
100
120
  ## Advanced
101
121
 
102
- User.limit(10).includes(:posts).eager_group(posts: [:comments_average_rating, :approved_comments_count])
122
+ `eager_group` through association
123
+
124
+ ```ruby
125
+ User.limit(10).includes(:posts).eager_group(posts: [:comments_average_rating, :approved_comments_count])
126
+ ```
127
+
128
+ pass parameter to scope
129
+
130
+ ```ruby
131
+ class Post < ActiveRecord::Base
132
+ has_many :comments
133
+
134
+ define_eager_group :comments_average_rating_by_author, :comments, :average, :rating, ->(author, ignore) { by_author(author, ignore) }
135
+ end
136
+
137
+ posts = Post.all.eager_group([:comments_average_rating_by_author, author, true])
138
+ posts.each { |post| post.comments_average_rating_by_author }
139
+ ```
140
+
141
+ `first_object` and `last_object` aggregation to eager load first and
142
+ last association objects.
143
+
144
+ ```ruby
145
+ class Post < ActiveRecord::Base
146
+ has_many :comments
147
+
148
+ define_eager_group :first_comment, :comments, :first_object, :id
149
+ define_eager_group :last_comment, :comments, :last_object, :id
150
+ end
151
+
152
+ posts = Post.all.eager_group(:first_comment, :last_comment)
153
+ posts.each do |post|
154
+ post.first_comment
155
+ post.last_comment
156
+ end
157
+ ```
158
+
103
159
 
104
160
  ## Benchmark
105
161
 
@@ -109,6 +165,6 @@ times faster, WOW!
109
165
 
110
166
  ## Contributing
111
167
 
112
- Bug reports and pull requests are welcome on GitHub at https://github.com/xinminlabs/eager_group.
168
+ Bug reports and pull requests are welcome on GitHub at https://github.com/flyerhzm/eager_group.
113
169
 
114
- [1]: https://github.com/xinminlabs/eager_group/blob/master/benchmark.rb
170
+ [1]: https://github.com/flyerhzm/eager_group/blob/master/benchmark.rb
@@ -30,11 +30,11 @@ class Comment < ActiveRecord::Base
30
30
  end
31
31
 
32
32
  # create database eager_group_benchmark;
33
- ActiveRecord::Base.establish_connection(adapter: 'mysql2', database: 'eager_group_benchmark', server: '/tmp/mysql.socket', username: 'root')
33
+ ActiveRecord::Base.establish_connection(
34
+ adapter: 'mysql2', database: 'eager_group_benchmark', server: '/tmp/mysql.socket', username: 'root'
35
+ )
34
36
 
35
- ActiveRecord::Base.connection.tables.each do |table|
36
- ActiveRecord::Base.connection.drop_table(table)
37
- end
37
+ ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
38
38
 
39
39
  ActiveRecord::Schema.define do
40
40
  self.verbose = false
@@ -55,18 +55,19 @@ ActiveRecord::Schema.define do
55
55
  end
56
56
 
57
57
  posts_size = 100
58
- comments_size = 1000
58
+ comments_size = 1_000
59
59
 
60
60
  posts = []
61
- posts_size.times do |i|
62
- posts << Post.new(title: "Title #{i}", body: "Body #{i}")
63
- end
61
+ posts_size.times { |i| posts << Post.new(title: "Title #{i}", body: "Body #{i}") }
64
62
  Post.import posts
65
63
  post_ids = Post.all.pluck(:id)
66
64
 
67
65
  comments = []
68
66
  comments_size.times do |i|
69
- comments << Comment.new(body: "Comment #{i}", post_id: post_ids[i % 100], status: %w[approved deleted][i % 2], rating: i % 5 + 1)
67
+ comments <<
68
+ Comment.new(
69
+ body: "Comment #{i}", post_id: post_ids[i % 100], status: %w[approved deleted][i % 2], rating: i % 5 + 1
70
+ )
70
71
  end
71
72
  Comment.import comments
72
73
 
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = 'Fix n+1 aggregate sql functions'
14
14
  spec.description = 'Fix n+1 aggregate sql functions for rails'
15
- spec.homepage = 'https://github.com/xinminlabs/eager_group'
15
+ spec.homepage = 'https://github.com/flyerhzm/eager_group'
16
16
 
17
17
  spec.license = 'MIT'
18
18
 
@@ -23,9 +23,10 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_development_dependency 'activerecord'
25
25
  spec.add_development_dependency 'activerecord-import'
26
+ spec.add_development_dependency 'activesupport'
26
27
  spec.add_development_dependency 'benchmark-ips'
27
28
  spec.add_development_dependency 'bundler'
28
29
  spec.add_development_dependency 'rake', '~> 10.0'
29
30
  spec.add_development_dependency 'rspec', '~> 3.3'
30
- spec.add_development_dependency 'sqlite3', '~> 1.3'
31
+ spec.add_development_dependency 'sqlite3'
31
32
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/module/attribute_accessors'
3
4
  require 'eager_group/version'
4
5
 
5
6
  module EagerGroup
@@ -11,7 +12,7 @@ module EagerGroup
11
12
  end
12
13
 
13
14
  module ClassMethods
14
- attr_reader :eager_group_definitions
15
+ mattr_accessor :eager_group_definitions, default: {}
15
16
 
16
17
  # class Post
17
18
  # define_eager_group :comments_avergage_rating, :comments, :average, :rating
@@ -19,16 +20,16 @@ module EagerGroup
19
20
  # end
20
21
  def define_eager_group(attr, association, aggregate_function, column_name, scope = nil)
21
22
  send :attr_accessor, attr
22
- @eager_group_definitions ||= {}
23
- @eager_group_definitions[attr] = Definition.new association, aggregate_function, column_name, scope
23
+ eager_group_definitions[attr] = Definition.new(association, aggregate_function, column_name, scope)
24
24
 
25
- define_method attr, lambda { |*args|
26
- query_result_cache = instance_variable_get("@#{attr}")
27
- return query_result_cache if args.blank? && query_result_cache.present?
25
+ define_method attr,
26
+ lambda { |*args|
27
+ query_result_cache = instance_variable_get("@#{attr}")
28
+ return query_result_cache if args.blank? && query_result_cache.present?
28
29
 
29
- preload_eager_group(attr, *args)
30
- instance_variable_get("@#{attr}")
31
- }
30
+ preload_eager_group(attr, *args)
31
+ instance_variable_get("@#{attr}")
32
+ }
32
33
 
33
34
  define_method "#{attr}=" do |val|
34
35
  instance_variable_set("@#{attr}", val)
@@ -51,4 +52,4 @@ ActiveRecord::Base.class_eval do
51
52
  end
52
53
  end
53
54
  require 'active_record/with_eager_group'
54
- ActiveRecord::Relation.send :prepend, ActiveRecord::WithEagerGroup
55
+ ActiveRecord::Relation.prepend ActiveRecord::WithEagerGroup
@@ -2,7 +2,7 @@
2
2
 
3
3
  module EagerGroup
4
4
  class Definition
5
- attr_reader :association, :aggregate_function, :column_name, :scope
5
+ attr_reader :association, :column_name, :scope
6
6
 
7
7
  def initialize(association, aggregate_function, column_name, scope)
8
8
  @association = association
@@ -10,5 +10,20 @@ module EagerGroup
10
10
  @column_name = column_name
11
11
  @scope = scope
12
12
  end
13
+
14
+ def aggregation_function
15
+ return :maximum if @aggregate_function.to_sym == :last_object
16
+ return :minimum if @aggregate_function.to_sym == :first_object
17
+
18
+ @aggregate_function
19
+ end
20
+
21
+ def need_load_object
22
+ %i[first_object last_object].include?(@aggregate_function.to_sym)
23
+ end
24
+
25
+ def default_value
26
+ %i[first_object last_object].include?(@aggregate_function.to_sym) ? nil : 0
27
+ end
13
28
  end
14
29
  end
@@ -12,35 +12,54 @@ module EagerGroup
12
12
  def run
13
13
  primary_key = @klass.primary_key
14
14
  @eager_group_values.each do |eager_group_value|
15
- definition_key, arguments = eager_group_value.is_a?(Array) ? [eager_group_value.shift, eager_group_value] : [eager_group_value, nil]
15
+ definition_key, arguments =
16
+ eager_group_value.is_a?(Array) ? [eager_group_value.shift, eager_group_value] : [eager_group_value, nil]
17
+
16
18
  if definition_key.is_a?(Hash)
17
19
  association_name, definition_key = *definition_key.first
18
20
  @records = @records.flat_map { |record| record.send(association_name) }
21
+ next if @records.empty?
22
+
19
23
  @klass = @records.first.class
20
24
  end
21
25
  record_ids = @records.map { |record| record.send(primary_key) }
22
- next unless definition = @klass.eager_group_definitions[definition_key]
26
+ unless definition = @klass.eager_group_definitions[definition_key]
27
+ next
28
+ end
23
29
 
24
30
  reflection = @klass.reflect_on_association(definition.association)
25
31
  association_class = reflection.klass
26
32
  association_class = association_class.instance_exec(*arguments, &definition.scope) if definition.scope
27
33
 
28
- if reflection.through_reflection
34
+ if reflection.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection)
35
+ foreign_key = "#{reflection.join_table}.#{reflection.foreign_key}"
36
+ aggregate_hash =
37
+ @klass.joins(reflection.name).where(foreign_key => record_ids).where(
38
+ polymophic_as_condition(reflection)
39
+ )
40
+ .group(foreign_key)
41
+ .send(definition.aggregation_function, definition.column_name)
42
+ elsif reflection.through_reflection
29
43
  foreign_key = "#{reflection.through_reflection.name}.#{reflection.through_reflection.foreign_key}"
30
- aggregate_hash = association_class.joins(reflection.through_reflection.name)
31
- .where(foreign_key => record_ids)
32
- .where(polymophic_as_condition(reflection.through_reflection))
33
- .group(foreign_key)
34
- .send(definition.aggregate_function, definition.column_name)
44
+ aggregate_hash =
45
+ association_class.joins(reflection.through_reflection.name).where(foreign_key => record_ids).where(
46
+ polymophic_as_condition(reflection.through_reflection)
47
+ )
48
+ .group(foreign_key)
49
+ .send(definition.aggregation_function, definition.column_name)
35
50
  else
36
- aggregate_hash = association_class.where(reflection.foreign_key => record_ids)
37
- .where(polymophic_as_condition(reflection))
38
- .group(reflection.foreign_key)
39
- .send(definition.aggregate_function, definition.column_name)
51
+ aggregate_hash =
52
+ association_class.where(reflection.foreign_key => record_ids).where(polymophic_as_condition(reflection))
53
+ .group(reflection.foreign_key)
54
+ .send(definition.aggregation_function, definition.column_name)
55
+ end
56
+ if definition.need_load_object
57
+ aggregate_objects = reflection.klass.find(aggregate_hash.values).each_with_object({}) { |o, h| h[o.id] = o }
58
+ aggregate_hash.keys.each { |key| aggregate_hash[key] = aggregate_objects[aggregate_hash[key]] }
40
59
  end
41
60
  @records.each do |record|
42
61
  id = record.send(primary_key)
43
- record.send("#{definition_key}=", aggregate_hash[id] || 0)
62
+ record.send("#{definition_key}=", aggregate_hash[id] || definition.default_value)
44
63
  end
45
64
  end
46
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EagerGroup
4
- VERSION = '0.6.0'
4
+ VERSION = '0.8.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eager_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-15 00:00:00.000000000 Z
11
+ date: 2019-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: benchmark-ips
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -98,16 +112,16 @@ dependencies:
98
112
  name: sqlite3
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - "~>"
115
+ - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: '1.3'
117
+ version: '0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - "~>"
122
+ - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: '1.3'
124
+ version: '0'
111
125
  description: Fix n+1 aggregate sql functions for rails
112
126
  email:
113
127
  - flyerhzm@gmail.com
@@ -128,12 +142,10 @@ files:
128
142
  - eager_group.gemspec
129
143
  - lib/active_record/with_eager_group.rb
130
144
  - lib/eager_group.rb
131
- - lib/eager_group/active_record_base.rb
132
- - lib/eager_group/active_record_relation.rb
133
145
  - lib/eager_group/definition.rb
134
146
  - lib/eager_group/preloader.rb
135
147
  - lib/eager_group/version.rb
136
- homepage: https://github.com/xinminlabs/eager_group
148
+ homepage: https://github.com/flyerhzm/eager_group
137
149
  licenses:
138
150
  - MIT
139
151
  metadata: {}
@@ -152,8 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
164
  - !ruby/object:Gem::Version
153
165
  version: '0'
154
166
  requirements: []
155
- rubyforge_project:
156
- rubygems_version: 2.6.14
167
+ rubygems_version: 3.0.3
157
168
  signing_key:
158
169
  specification_version: 4
159
170
  summary: Fix n+1 aggregate sql functions
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveRecord::Base
4
- class <<self
5
- # Post.eager_group(:approved_comments_count, :comments_average_rating)
6
- delegate :eager_group, to: :all
7
- end
8
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveRecord::Relation
4
- # Post.all.eager_group(:approved_comments_count, :comments_average_rating)
5
-
6
- def exec_queries_with_eager_group
7
- records = exec_queries_without_eager_group
8
- EagerGroup::Preloader.new(klass, records, eager_group_values).run if eager_group_values.present?
9
- records
10
- end
11
- alias_method_chain :exec_queries, :eager_group
12
-
13
- def eager_group(*args)
14
- check_if_method_has_arguments!('eager_group', args)
15
- spawn.eager_group!(*args)
16
- end
17
-
18
- def eager_group!(*args)
19
- self.eager_group_values += args
20
- self
21
- end
22
-
23
- def eager_group_values
24
- @values[:eager_group] || []
25
- end
26
-
27
- def eager_group_values=(values)
28
- raise ImmutableRelation if @loaded
29
-
30
- @values[:eager_group] = values
31
- end
32
- end