detached_counter_cache 1.0.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 +7 -0
- data/lib/detached_counter_cache.rb +97 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a227c3581209c33f4267ca0312b003796dd19224
|
4
|
+
data.tar.gz: 0628b8b5c5a2428a7326e9ad4c28ebe74666316d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a5b3ea7a6e2d13fdba1e43d36fe21e159ed0094659ba9b0a38753161a47124e22e1060f565a818f46c02a0a6ecede41f7a102d6ef3b1f59d45c4bdc5b244979
|
7
|
+
data.tar.gz: a55c5678be71fdf32b3f9f035c2a9ed570bce44bea3fb28f62e033a077a53c1d2ffb4df952a5d0f62295c347286c2f9fa310a6f0126b6e5e4191d32907644662
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ActiveRecordExtensions
|
2
|
+
module DetachedCounterCache
|
3
|
+
module Base
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :detached_counter_cache_table_names, :detached_counter_cache_placeholders
|
8
|
+
self.detached_counter_cache_table_names = []
|
9
|
+
self.detached_counter_cache_placeholders = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
alias_method_chain :update_counters, :detached_counters
|
13
|
+
alias_method_chain :belongs_to, :detached_counters
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def belongs_to_with_detached_counters(association_id, options = {})
|
19
|
+
if add_detached_counter_cache = options.delete(:detached_counter_cache)
|
20
|
+
placeholder = DetachedCounterCachePlaceholder.new
|
21
|
+
options[:counter_cache] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
belongs_to_without_detached_counters(association_id, options)
|
25
|
+
|
26
|
+
if add_detached_counter_cache
|
27
|
+
reflection = reflections[association_id.to_s]
|
28
|
+
placeholder.reflection = reflection
|
29
|
+
|
30
|
+
klass = reflection.klass
|
31
|
+
klass.detached_counter_cache_table_names += [placeholder.detached_counter_cache_table_name]
|
32
|
+
klass.detached_counter_cache_placeholders = klass.detached_counter_cache_placeholders.merge(reflection.counter_cache_column.to_s => placeholder)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_counters_with_detached_counters(id, counters)
|
37
|
+
detached_counters = []
|
38
|
+
counters.each do |column_name, value|
|
39
|
+
if detached_counter_cache_placeholders.has_key? column_name.to_s
|
40
|
+
detached_counters << [detached_counter_cache_placeholders[column_name.to_s], value]
|
41
|
+
counters.delete(column_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
detached_counters.each do |placeholder, value|
|
46
|
+
self.connection.execute(<<-SQL
|
47
|
+
INSERT INTO `#{placeholder.detached_counter_cache_table_name}` (#{placeholder.reflection.foreign_key}, count) VALUES (#{id}, #{value})
|
48
|
+
ON DUPLICATE KEY UPDATE count = count + #{value}
|
49
|
+
SQL
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
update_counters_without_detached_counters(id, counters) unless counters.blank?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module HasManyAssociation
|
59
|
+
extend ActiveSupport::Concern
|
60
|
+
|
61
|
+
included do
|
62
|
+
alias_method_chain :count_records, :detached_counters
|
63
|
+
end
|
64
|
+
|
65
|
+
def count_records_with_detached_counters
|
66
|
+
potential_table_name = [@owner.class.table_name, @reflection.klass.table_name, 'counts'].join('_')
|
67
|
+
|
68
|
+
if (@owner.class.detached_counter_cache_table_names || []).include?(potential_table_name)
|
69
|
+
DetachedCounterCache.count_from_connection(
|
70
|
+
@owner.class.connection,
|
71
|
+
potential_table_name,
|
72
|
+
@reflection.foreign_key,
|
73
|
+
@owner.id
|
74
|
+
)
|
75
|
+
else
|
76
|
+
count_records_without_detached_counters
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class DetachedCounterCachePlaceholder
|
82
|
+
attr_accessor :reflection
|
83
|
+
|
84
|
+
def detached_counter_cache_table_name
|
85
|
+
[reflection.klass.table_name, reflection.active_record.table_name, 'counts'].join('_')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.count_from_connection(connection, potential_table_name, foreign_key, owner_id)
|
90
|
+
row = connection.select_all("SELECT count FROM `#{potential_table_name}` WHERE #{foreign_key} = #{owner_id}")[0]
|
91
|
+
row.blank? ? 0 : row['count'].to_i
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
ActiveRecord::Base.send( :include, ActiveRecordExtensions::DetachedCounterCache::Base )
|
97
|
+
ActiveRecord::Associations::HasManyAssociation.send( :include, ActiveRecordExtensions::DetachedCounterCache::HasManyAssociation )
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: detached_counter_cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Grim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mysql2
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: database_cleaner
|
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'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: wwtd
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: counter cache that lives in its own table
|
98
|
+
email: stopdropandrew@gmail.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- lib/detached_counter_cache.rb
|
104
|
+
homepage: https://github.com/kongregate/detached_counter_cache
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.5.1
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: counter cache that lives in its own table
|
128
|
+
test_files: []
|