eager_group 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://secure.travis-ci.org/xinminlabs/eager_group.png)](http://travis-ci.org/xinminlabs/eager_group)
|
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)
|
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
|