eager_group 0.5.0 → 0.6.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +9 -3
- data/Rakefile +1 -1
- data/benchmark.rb +9 -7
- data/bin/console +4 -3
- data/eager_group.gemspec +19 -18
- data/lib/active_record/with_eager_group.rb +31 -0
- data/lib/eager_group.rb +24 -17
- data/lib/eager_group/active_record_base.rb +3 -1
- data/lib/eager_group/active_record_relation.rb +4 -3
- data/lib/eager_group/definition.rb +2 -0
- data/lib/eager_group/preloader.rb +36 -30
- data/lib/eager_group/version.rb +3 -1
- metadata +35 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22abe02d6bafe11c49460a72d251e3686f007796
|
4
|
+
data.tar.gz: c4df75c16f76a672fc4b6dcfea0f5fe80399c064
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33cd73103c6cb2597a13e640b028b7c2bfc75982ed3746355b07b758cb3810f5923fdb7967a4e102591d0aa07b51453d0473be94c2d5b2036f123e9286395ddd
|
7
|
+
data.tar.gz: 61e0c3121f8504b094e11807a0f377f16c406b26973feea5a631152d0437465131720c0586870cee4e54e5f748bc01f976d3c4da78562ff741e6575a0b663002
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# EagerGroup
|
2
2
|
|
3
3
|
[](http://travis-ci.org/xinminlabs/eager_group)
|
4
|
+
[](https://awesomecode.io/repos/xinminlabs/eager_group)
|
4
6
|
|
5
7
|
[More explaination on our blog](http://blog.xinminlabs.com/2015/06/29/eager_group/)
|
6
8
|
|
@@ -28,7 +30,7 @@ or
|
|
28
30
|
SELECT "posts".* FROM "posts";
|
29
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;
|
30
32
|
|
31
|
-
It
|
33
|
+
It supports Rails 4.x and Rails 5.x
|
32
34
|
|
33
35
|
## Installation
|
34
36
|
|
@@ -87,14 +89,18 @@ when querying
|
|
87
89
|
EagerGroup will execute `GROUP BY` sqls for you then set the value of
|
88
90
|
attributes.
|
89
91
|
|
90
|
-
`define_eager_group` will define a method in model.
|
91
|
-
You can call the `definition_name` directly for convenience,
|
92
|
+
`define_eager_group` will define a method in model.
|
93
|
+
You can call the `definition_name` directly for convenience,
|
92
94
|
but it would not help you to fix n+1 aggregate sql issue.
|
93
95
|
|
94
96
|
post = Post.first
|
95
97
|
post.commets_average_rating
|
96
98
|
post.approved_comments_count
|
97
99
|
|
100
|
+
## Advanced
|
101
|
+
|
102
|
+
User.limit(10).includes(:posts).eager_group(posts: [:comments_average_rating, :approved_comments_count])
|
103
|
+
|
98
104
|
## Benchmark
|
99
105
|
|
100
106
|
I wrote a benchmark script [here][1], it queries approved comments count
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/benchmark.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Calculating -------------------------------------
|
2
4
|
# Without EagerGroup 2.000 i/100ms
|
3
5
|
# With EagerGroup 28.000 i/100ms
|
@@ -28,7 +30,7 @@ class Comment < ActiveRecord::Base
|
|
28
30
|
end
|
29
31
|
|
30
32
|
# create database eager_group_benchmark;
|
31
|
-
ActiveRecord::Base.establish_connection(:
|
33
|
+
ActiveRecord::Base.establish_connection(adapter: 'mysql2', database: 'eager_group_benchmark', server: '/tmp/mysql.socket', username: 'root')
|
32
34
|
|
33
35
|
ActiveRecord::Base.connection.tables.each do |table|
|
34
36
|
ActiveRecord::Base.connection.drop_table(table)
|
@@ -37,13 +39,13 @@ end
|
|
37
39
|
ActiveRecord::Schema.define do
|
38
40
|
self.verbose = false
|
39
41
|
|
40
|
-
create_table :posts, :
|
42
|
+
create_table :posts, force: true do |t|
|
41
43
|
t.string :title
|
42
44
|
t.string :body
|
43
45
|
t.timestamps null: false
|
44
46
|
end
|
45
47
|
|
46
|
-
create_table :comments, :
|
48
|
+
create_table :comments, force: true do |t|
|
47
49
|
t.string :body
|
48
50
|
t.string :status
|
49
51
|
t.integer :rating
|
@@ -57,26 +59,26 @@ comments_size = 1000
|
|
57
59
|
|
58
60
|
posts = []
|
59
61
|
posts_size.times do |i|
|
60
|
-
posts << Post.new(:
|
62
|
+
posts << Post.new(title: "Title #{i}", body: "Body #{i}")
|
61
63
|
end
|
62
64
|
Post.import posts
|
63
65
|
post_ids = Post.all.pluck(:id)
|
64
66
|
|
65
67
|
comments = []
|
66
68
|
comments_size.times do |i|
|
67
|
-
comments << Comment.new(:
|
69
|
+
comments << Comment.new(body: "Comment #{i}", post_id: post_ids[i % 100], status: %w[approved deleted][i % 2], rating: i % 5 + 1)
|
68
70
|
end
|
69
71
|
Comment.import comments
|
70
72
|
|
71
73
|
Benchmark.ips do |x|
|
72
|
-
x.report(
|
74
|
+
x.report('Without EagerGroup') do
|
73
75
|
Post.limit(20).each do |post|
|
74
76
|
post.comments.approved.count
|
75
77
|
post.comments.approved.average('rating')
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
|
-
x.report(
|
81
|
+
x.report('With EagerGroup') do
|
80
82
|
Post.eager_group(:approved_comments_count, :comments_average_rating).limit(20).each do |post|
|
81
83
|
post.approved_comments_count
|
82
84
|
post.comments_average_rating
|
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'eager_group'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "eager_group"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start
|
data/eager_group.gemspec
CHANGED
@@ -1,30 +1,31 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'eager_group/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'eager_group'
|
8
9
|
spec.version = EagerGroup::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Richard Huang']
|
11
|
+
spec.email = ['flyerhzm@gmail.com']
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
13
|
+
spec.summary = 'Fix n+1 aggregate sql functions'
|
14
|
+
spec.description = 'Fix n+1 aggregate sql functions for rails'
|
15
|
+
spec.homepage = 'https://github.com/xinminlabs/eager_group'
|
15
16
|
|
16
|
-
spec.license
|
17
|
+
spec.license = 'MIT'
|
17
18
|
|
18
19
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
20
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ['lib']
|
22
23
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'activerecord'
|
25
|
+
spec.add_development_dependency 'activerecord-import'
|
26
|
+
spec.add_development_dependency 'benchmark-ips'
|
27
|
+
spec.add_development_dependency 'bundler'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
30
|
+
spec.add_development_dependency 'sqlite3', '~> 1.3'
|
30
31
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module WithEagerGroup
|
5
|
+
def exec_queries
|
6
|
+
records = super
|
7
|
+
EagerGroup::Preloader.new(klass, records, eager_group_values).run if eager_group_values.present?
|
8
|
+
records
|
9
|
+
end
|
10
|
+
|
11
|
+
def eager_group(*args)
|
12
|
+
check_if_method_has_arguments!('eager_group', args)
|
13
|
+
spawn.eager_group!(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def eager_group!(*args)
|
17
|
+
self.eager_group_values += args
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def eager_group_values
|
22
|
+
@values[:eager_group] || []
|
23
|
+
end
|
24
|
+
|
25
|
+
def eager_group_values=(values)
|
26
|
+
raise ImmutableRelation if @loaded
|
27
|
+
|
28
|
+
@values[:eager_group] = values
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/eager_group.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'eager_group/
|
4
|
-
require 'eager_group/active_record_relation'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eager_group/version'
|
5
4
|
|
6
5
|
module EagerGroup
|
7
6
|
autoload :Preloader, 'eager_group/preloader'
|
@@ -12,36 +11,44 @@ module EagerGroup
|
|
12
11
|
end
|
13
12
|
|
14
13
|
module ClassMethods
|
15
|
-
attr_reader :
|
14
|
+
attr_reader :eager_group_definitions
|
16
15
|
|
17
16
|
# class Post
|
18
17
|
# define_eager_group :comments_avergage_rating, :comments, :average, :rating
|
19
18
|
# define_eager_group :approved_comments_count, :comments, :count, :*, -> { approved }
|
20
19
|
# end
|
21
20
|
def define_eager_group(attr, association, aggregate_function, column_name, scope = nil)
|
22
|
-
|
23
|
-
@
|
24
|
-
@
|
25
|
-
|
26
|
-
define_method attr,
|
21
|
+
send :attr_accessor, attr
|
22
|
+
@eager_group_definitions ||= {}
|
23
|
+
@eager_group_definitions[attr] = Definition.new association, aggregate_function, column_name, scope
|
24
|
+
|
25
|
+
define_method attr, lambda { |*args|
|
27
26
|
query_result_cache = instance_variable_get("@#{attr}")
|
28
|
-
if args.blank? && query_result_cache.present?
|
29
|
-
|
30
|
-
end
|
27
|
+
return query_result_cache if args.blank? && query_result_cache.present?
|
28
|
+
|
31
29
|
preload_eager_group(attr, *args)
|
32
30
|
instance_variable_get("@#{attr}")
|
33
|
-
|
34
|
-
|
31
|
+
}
|
32
|
+
|
35
33
|
define_method "#{attr}=" do |val|
|
36
34
|
instance_variable_set("@#{attr}", val)
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
38
|
+
|
41
39
|
private
|
40
|
+
|
42
41
|
def preload_eager_group(*eager_group_value)
|
43
42
|
EagerGroup::Preloader.new(self.class, [self], [eager_group_value]).run
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
|
-
|
46
|
+
require 'active_record'
|
47
|
+
ActiveRecord::Base.class_eval do
|
48
|
+
include EagerGroup
|
49
|
+
class << self
|
50
|
+
delegate :eager_group, to: :all
|
51
|
+
end
|
52
|
+
end
|
53
|
+
require 'active_record/with_eager_group'
|
54
|
+
ActiveRecord::Relation.send :prepend, ActiveRecord::WithEagerGroup
|
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ActiveRecord::Relation
|
2
4
|
# Post.all.eager_group(:approved_comments_count, :comments_average_rating)
|
3
5
|
|
4
6
|
def exec_queries_with_eager_group
|
5
7
|
records = exec_queries_without_eager_group
|
6
|
-
if eager_group_values.present?
|
7
|
-
EagerGroup::Preloader.new(self.klass, records, eager_group_values).run
|
8
|
-
end
|
8
|
+
EagerGroup::Preloader.new(klass, records, eager_group_values).run if eager_group_values.present?
|
9
9
|
records
|
10
10
|
end
|
11
11
|
alias_method_chain :exec_queries, :eager_group
|
@@ -26,6 +26,7 @@ class ActiveRecord::Relation
|
|
26
26
|
|
27
27
|
def eager_group_values=(values)
|
28
28
|
raise ImmutableRelation if @loaded
|
29
|
+
|
29
30
|
@values[:eager_group] = values
|
30
31
|
end
|
31
32
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module EagerGroup
|
2
4
|
class Preloader
|
3
5
|
def initialize(klass, records, eager_group_values)
|
@@ -9,40 +11,44 @@ module EagerGroup
|
|
9
11
|
# Preload aggregate functions
|
10
12
|
def run
|
11
13
|
primary_key = @klass.primary_key
|
12
|
-
record_ids = @records.map { |record| record.send primary_key }
|
13
14
|
@eager_group_values.each do |eager_group_value|
|
14
|
-
|
15
|
-
if
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
else
|
23
|
-
[]
|
24
|
-
end
|
25
|
-
}
|
15
|
+
definition_key, arguments = eager_group_value.is_a?(Array) ? [eager_group_value.shift, eager_group_value] : [eager_group_value, nil]
|
16
|
+
if definition_key.is_a?(Hash)
|
17
|
+
association_name, definition_key = *definition_key.first
|
18
|
+
@records = @records.flat_map { |record| record.send(association_name) }
|
19
|
+
@klass = @records.first.class
|
20
|
+
end
|
21
|
+
record_ids = @records.map { |record| record.send(primary_key) }
|
22
|
+
next unless definition = @klass.eager_group_definitions[definition_key]
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
24
|
+
reflection = @klass.reflect_on_association(definition.association)
|
25
|
+
association_class = reflection.klass
|
26
|
+
association_class = association_class.instance_exec(*arguments, &definition.scope) if definition.scope
|
27
|
+
|
28
|
+
if reflection.through_reflection
|
29
|
+
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)
|
35
|
+
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)
|
40
|
+
end
|
41
|
+
@records.each do |record|
|
42
|
+
id = record.send(primary_key)
|
43
|
+
record.send("#{definition_key}=", aggregate_hash[id] || 0)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def polymophic_as_condition(reflection)
|
51
|
+
reflection.type ? { reflection.name => { reflection.type => @klass.base_class.name } } : []
|
52
|
+
end
|
47
53
|
end
|
48
54
|
end
|
data/lib/eager_group/version.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eager_group
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.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:
|
11
|
+
date: 2018-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,89 +25,89 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: activerecord-import
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: benchmark-ips
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '10.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '10.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: sqlite3
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '1.3'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '1.3'
|
111
111
|
description: Fix n+1 aggregate sql functions for rails
|
112
112
|
email:
|
113
113
|
- flyerhzm@gmail.com
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- bin/console
|
127
127
|
- bin/setup
|
128
128
|
- eager_group.gemspec
|
129
|
+
- lib/active_record/with_eager_group.rb
|
129
130
|
- lib/eager_group.rb
|
130
131
|
- lib/eager_group/active_record_base.rb
|
131
132
|
- lib/eager_group/active_record_relation.rb
|
@@ -152,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
153
|
version: '0'
|
153
154
|
requirements: []
|
154
155
|
rubyforge_project:
|
155
|
-
rubygems_version: 2.
|
156
|
+
rubygems_version: 2.6.14
|
156
157
|
signing_key:
|
157
158
|
specification_version: 4
|
158
159
|
summary: Fix n+1 aggregate sql functions
|