activerecord-has_count 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/benchmarks/Gemfile +0 -1
- data/benchmarks/benchmark.rb +53 -23
- data/lib/active_record/associations/preloader/has_count.rb +15 -0
- data/lib/activerecord-has_count/version.rb +1 -1
- data/spec/models/reply.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d2c85db920895de37cc5f38524f2fb8ae76b3eb
|
4
|
+
data.tar.gz: 9ad1ad18db8c6fc038328a30490bba0d1593b632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a100ee2738250cc1049089571609d7d7c166c198576440d4c3d9a52f6da78c5bc0d02dcef8b133e6dc8b7eb9bdc9281aeec53f5d495a33fd31c5f19db054657
|
7
|
+
data.tar.gz: 62e8e5db5e59aa2b792344733501881db3df81e53bea8779634220668335f3f648a0b83dbcaf7018f163f45621199f3fd46bc8e7848a345344ceb84ce2092b3a
|
data/benchmarks/Gemfile
CHANGED
data/benchmarks/benchmark.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "benchmark"
|
2
2
|
require "pry"
|
3
3
|
require "active_record"
|
4
|
-
require "activerecord-import"
|
5
4
|
require "activerecord-has_count"
|
6
5
|
|
7
6
|
spec_dir = File.expand_path("../../spec", __FILE__)
|
@@ -11,57 +10,88 @@ database_yml = File.join(spec_dir, "database.yml")
|
|
11
10
|
ActiveRecord::Base.configurations["bench"] = YAML.load_file(database_yml)["bench"]
|
12
11
|
ActiveRecord::Base.establish_connection :bench
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
def silently_execute(&block)
|
14
|
+
stdout_old = $stdout.dup
|
15
|
+
$stdout.reopen("/tmp/bench")
|
16
|
+
block.call
|
17
|
+
$stdout.flush
|
18
|
+
$stdout.reopen stdout_old
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert_equal(expect, actual)
|
22
|
+
raise "Expected #{expect}, but got #{actual}" if expect != actual
|
23
|
+
end
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
silently_execute do
|
26
|
+
ActiveRecord::Schema.define do
|
27
|
+
create_table :tweets, force: true do |t|
|
28
|
+
t.column :replies_count_cache, :integer
|
29
|
+
t.column :created_at, :datetime
|
30
|
+
t.column :updated_at, :datetime
|
31
|
+
end
|
32
|
+
|
33
|
+
create_table :replies, force: true do |t|
|
34
|
+
t.column :tweet_id, :integer
|
35
|
+
t.column :created_at, :datetime
|
36
|
+
t.column :updated_at, :datetime
|
37
|
+
end
|
38
|
+
add_index :replies, [:tweet_id], name: "index_replies_on_tweet_id", using: :btree
|
24
39
|
end
|
25
40
|
end
|
26
41
|
|
27
42
|
[Tweet, Reply].each(&:delete_all)
|
28
43
|
|
29
|
-
TWEET_COUNT =
|
30
|
-
REPLY_COUNT =
|
44
|
+
TWEET_COUNT = 10
|
45
|
+
REPLY_COUNT = 1000
|
31
46
|
|
32
47
|
TWEET_COUNT.times do
|
33
|
-
tweet = Tweet.create
|
48
|
+
tweet = Tweet.create(replies_count_cache: 0)
|
34
49
|
|
35
50
|
replies = REPLY_COUNT.times.map do
|
36
|
-
Reply.
|
51
|
+
Reply.create(tweet: tweet)
|
37
52
|
end
|
38
|
-
Reply.import(replies, validate: false)
|
39
53
|
end
|
40
54
|
|
41
|
-
Benchmark.
|
42
|
-
bench.report("
|
55
|
+
Benchmark.bm do |bench|
|
56
|
+
bench.report("counter_cache ") do
|
57
|
+
tweets = Tweet.first(TWEET_COUNT)
|
58
|
+
|
59
|
+
tweets.each do |t|
|
60
|
+
assert_equal(REPLY_COUNT, t.replies_count_cache)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
bench.report("N+1 COUNT query ") do
|
43
65
|
tweets = Tweet.first(TWEET_COUNT)
|
44
66
|
|
45
|
-
tweets.each
|
67
|
+
tweets.each do |t|
|
68
|
+
assert_equal(REPLY_COUNT, t.replies.count)
|
69
|
+
end
|
46
70
|
end
|
47
71
|
|
48
|
-
bench.report("LEFT JOIN") do
|
72
|
+
bench.report("LEFT JOIN ") do
|
49
73
|
tweets = Tweet.joins('LEFT JOIN replies ON tweets.id = replies.tweet_id').
|
50
74
|
select('tweets.*, COUNT(replies.id) AS replies_count').
|
51
75
|
group('tweets.id').first(TWEET_COUNT)
|
52
76
|
|
53
|
-
tweets.each
|
77
|
+
tweets.each do |t|
|
78
|
+
assert_equal(REPLY_COUNT, t.replies_count)
|
79
|
+
end
|
54
80
|
end
|
55
81
|
|
56
82
|
bench.report("preloaded has_count") do
|
57
83
|
tweets = Tweet.preload(:replies_count).first(TWEET_COUNT)
|
58
84
|
|
59
|
-
tweets.each
|
85
|
+
tweets.each do |t|
|
86
|
+
assert_equal(REPLY_COUNT, t.replies_count)
|
87
|
+
end
|
60
88
|
end
|
61
89
|
|
62
|
-
bench.report("
|
90
|
+
bench.report("preloaded has_many ") do
|
63
91
|
tweets = Tweet.preload(:replies).first(TWEET_COUNT)
|
64
92
|
|
65
|
-
tweets.each
|
93
|
+
tweets.each do |t|
|
94
|
+
assert_equal(REPLY_COUNT, t.replies.size)
|
95
|
+
end
|
66
96
|
end
|
67
97
|
end
|
@@ -20,6 +20,21 @@ module ActiveRecord
|
|
20
20
|
association.target = count
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
24
|
+
def load_slices(slices)
|
25
|
+
@preloaded_records = slices.flat_map { |slice|
|
26
|
+
records_for(slice)
|
27
|
+
}
|
28
|
+
|
29
|
+
@preloaded_records.map { |record|
|
30
|
+
key = record
|
31
|
+
[record, key]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def query_scope(ids)
|
36
|
+
scope.where(association_key.in(ids)).pluck(association_key_name)
|
37
|
+
end
|
23
38
|
end
|
24
39
|
|
25
40
|
private
|
data/spec/models/reply.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,7 @@ ActiveRecord::Base.establish_connection :test
|
|
15
15
|
|
16
16
|
ActiveRecord::Schema.define do
|
17
17
|
create_table :tweets, force: true do |t|
|
18
|
-
t.column :
|
18
|
+
t.column :replies_count_cache, :integer
|
19
19
|
t.column :created_at, :datetime
|
20
20
|
t.column :updated_at, :datetime
|
21
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-has_count
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|