active_model_cachers 2.1.6 → 2.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +9 -9
  3. data/.travis.yml +8 -1
  4. data/CHANGELOG.md +67 -62
  5. data/CODE_OF_CONDUCT.md +48 -48
  6. data/LICENSE.txt +21 -21
  7. data/README.md +1 -1
  8. data/Rakefile +10 -10
  9. data/active_model_cachers.gemspec +7 -0
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/gemfiles/3.2.gemfile +11 -11
  13. data/gemfiles/4.2.gemfile +11 -11
  14. data/gemfiles/5.0.gemfile +11 -11
  15. data/gemfiles/5.1.gemfile +11 -11
  16. data/gemfiles/5.2.gemfile +11 -11
  17. data/gemfiles/6.0.gemfile +11 -0
  18. data/lib/active_model_cachers.rb +0 -0
  19. data/lib/active_model_cachers/active_record/attr_model.rb +124 -124
  20. data/lib/active_model_cachers/active_record/cacher.rb +97 -97
  21. data/lib/active_model_cachers/active_record/extension.rb +119 -119
  22. data/lib/active_model_cachers/active_record/global_callbacks.rb +67 -67
  23. data/lib/active_model_cachers/cache_service.rb +151 -151
  24. data/lib/active_model_cachers/cache_service_factory.rb +55 -55
  25. data/lib/active_model_cachers/column_value_cache.rb +47 -47
  26. data/lib/active_model_cachers/config.rb +6 -6
  27. data/lib/active_model_cachers/false_object.rb +5 -5
  28. data/lib/active_model_cachers/hook/associations.rb +43 -43
  29. data/lib/active_model_cachers/hook/dependencies.rb +38 -38
  30. data/lib/active_model_cachers/hook/on_model_delete.rb +29 -29
  31. data/lib/active_model_cachers/nil_object.rb +5 -5
  32. data/lib/active_model_cachers/patches/patch_rails_3.rb +49 -49
  33. data/lib/active_model_cachers/patches/uninitialized_attribute.rb +9 -9
  34. data/lib/active_model_cachers/version.rb +4 -4
  35. metadata +10 -4
@@ -1,11 +1,11 @@
1
- source 'https://rubygems.org'
2
-
3
- gem "activerecord", "~> 5.0.0"
4
- gem "request_store", "~> 1.4.0"
5
-
6
- group :test do
7
- gem "simplecov"
8
- end
9
-
10
- gemspec :path => "../"
11
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.0.0'
4
+ gem 'request_store', '~> 1.4.0'
5
+
6
+ group :test do
7
+ gem 'simplecov'
8
+ gem 'sqlite3', '~> 1.3.6'
9
+ end
10
+
11
+ gemspec path: '../'
@@ -1,11 +1,11 @@
1
- source 'https://rubygems.org'
2
-
3
- gem "activerecord", "~> 5.1.0"
4
- gem "request_store", "~> 1.4.0"
5
-
6
- group :test do
7
- gem "simplecov"
8
- end
9
-
10
- gemspec :path => "../"
11
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.1.0'
4
+ gem 'request_store', '~> 1.4.0'
5
+
6
+ group :test do
7
+ gem 'simplecov'
8
+ gem 'sqlite3', '~> 1.3.6'
9
+ end
10
+
11
+ gemspec path: '../'
@@ -1,11 +1,11 @@
1
- source 'https://rubygems.org'
2
-
3
- gem "activerecord", "~> 5.2.0"
4
- gem "request_store", "~> 1.4.0"
5
-
6
- group :test do
7
- gem "simplecov"
8
- end
9
-
10
- gemspec :path => "../"
11
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.2.0'
4
+ gem 'request_store', '~> 1.4.0'
5
+
6
+ group :test do
7
+ gem 'simplecov'
8
+ gem 'sqlite3', '~> 1.3.6'
9
+ end
10
+
11
+ gemspec path: '../'
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 6.0.0'
4
+ gem 'request_store', '~> 1.4.1'
5
+
6
+ group :test do
7
+ gem 'simplecov'
8
+ gem 'sqlite3', '~> 1.4.1'
9
+ end
10
+
11
+ gemspec path: '../'
File without changes
@@ -1,124 +1,124 @@
1
- # frozen_string_literal: true
2
- module ActiveModelCachers
3
- module ActiveRecord
4
- class AttrModel
5
- attr_reader :klass, :column, :reflect
6
-
7
- def initialize(klass, column, primary_key: nil, foreign_key: nil)
8
- @klass = klass
9
- @column = column
10
- @primary_key = primary_key
11
- @foreign_key = foreign_key
12
- @reflect = klass.reflect_on_association(column)
13
- end
14
-
15
- def association?
16
- return (@reflect != nil)
17
- end
18
-
19
- def class_name
20
- return if not association?
21
- return @reflect.class_name
22
- end
23
-
24
- def join_table
25
- return nil if @reflect == nil
26
- options = @reflect.options
27
- return options[:through] if options[:through]
28
- return (options[:join_table] || @reflect.send(:derive_join_table)) if @reflect.macro == :has_and_belongs_to_many
29
- return nil
30
- end
31
-
32
- def join_table_class_name
33
- join_table.try{|table_name| @klass.reflect_on_association(table_name).try(:class_name) || through_klass.name }
34
- end
35
-
36
- def through_reflection
37
- @klass.new.association(@column).reflection.through_reflection
38
- end
39
-
40
- def through_klass
41
- through_reflection.try(:klass) || through_klass_for_rails_3
42
- end
43
-
44
- def belongs_to?
45
- return false if not association?
46
- return @reflect.belongs_to?
47
- end
48
-
49
- def has_one?
50
- return false if not association?
51
- #return @reflect.has_one? # Rails 3 doesn't have this method
52
- return false if @reflect.collection?
53
- return false if @reflect.belongs_to?
54
- return true
55
- end
56
-
57
- def primary_key
58
- return @primary_key if @primary_key
59
- return if not association?
60
- return (@reflect.belongs_to? ? @reflect.klass : @reflect.active_record).primary_key
61
- end
62
-
63
- def foreign_key(reverse: false)
64
- return @foreign_key if @foreign_key
65
- return if not association?
66
- # key may be symbol if specify foreign_key in association options
67
- return @reflect.chain.last.foreign_key.to_s if reverse and join_table
68
- return (@reflect.belongs_to? == reverse ? primary_key : @reflect.foreign_key).to_s
69
- end
70
-
71
- def single_association?
72
- return false if not association?
73
- return !collection?
74
- end
75
-
76
- def collection?
77
- return false if not association?
78
- return @reflect.collection?
79
- end
80
-
81
- def query_model(binding, id)
82
- return query_self(binding, id) if @column == nil
83
- return query_association(binding, id) if association?
84
- return query_attribute(binding, id)
85
- end
86
-
87
- def extract_class_and_column
88
- return [class_name, nil] if single_association?
89
- return [@klass.to_s, @column]
90
- end
91
-
92
- private
93
-
94
- def query_self(binding, id)
95
- return binding if binding.is_a?(::ActiveRecord::Base)
96
- return @klass.find_by(primary_key => id)
97
- end
98
-
99
- def query_attribute(binding, id)
100
- return binding.send(@column) if binding.is_a?(::ActiveRecord::Base) and binding.has_attribute?(@column)
101
- return @klass.where(id: id).limit(1).pluck(@column).first
102
- end
103
-
104
- def query_association(binding, id)
105
- return binding.association(@column).load_target if binding.is_a?(::ActiveRecord::Base)
106
- id = @reflect.active_record.where(id: id).limit(1).pluck(foreign_key).first if foreign_key != 'id'
107
- case
108
- when collection? ; return id ? @reflect.klass.where(@reflect.foreign_key => id).to_a : []
109
- when has_one? ; return id ? @reflect.klass.find_by(foreign_key(reverse: true) => id) : nil
110
- else ; return id ? @reflect.klass.find_by(primary_key => id) : nil
111
- end
112
- end
113
-
114
- def through_klass_for_rails_3
115
- const_name = "HABTM_#{@reflect.klass.name.pluralize}"
116
- @klass.const_defined?(const_name) ? @klass.const_get(const_name) : @klass.const_set(const_name, create_through_klass_for_rails_3)
117
- end
118
-
119
- def create_through_klass_for_rails_3
120
- Class.new(::ActiveRecord::Base).tap{|s| s.table_name = join_table }
121
- end
122
- end
123
- end
124
- end
1
+ # frozen_string_literal: true
2
+ module ActiveModelCachers
3
+ module ActiveRecord
4
+ class AttrModel
5
+ attr_reader :klass, :column, :reflect
6
+
7
+ def initialize(klass, column, primary_key: nil, foreign_key: nil)
8
+ @klass = klass
9
+ @column = column
10
+ @primary_key = primary_key
11
+ @foreign_key = foreign_key
12
+ @reflect = klass.reflect_on_association(column)
13
+ end
14
+
15
+ def association?
16
+ return (@reflect != nil)
17
+ end
18
+
19
+ def class_name
20
+ return if not association?
21
+ return @reflect.class_name
22
+ end
23
+
24
+ def join_table
25
+ return nil if @reflect == nil
26
+ options = @reflect.options
27
+ return options[:through] if options[:through]
28
+ return (options[:join_table] || @reflect.send(:derive_join_table)) if @reflect.macro == :has_and_belongs_to_many
29
+ return nil
30
+ end
31
+
32
+ def join_table_class_name
33
+ join_table.try{|table_name| @klass.reflect_on_association(table_name).try(:class_name) || through_klass.name }
34
+ end
35
+
36
+ def through_reflection
37
+ @klass.new.association(@column).reflection.through_reflection
38
+ end
39
+
40
+ def through_klass
41
+ through_reflection.try(:klass) || through_klass_for_rails_3
42
+ end
43
+
44
+ def belongs_to?
45
+ return false if not association?
46
+ return @reflect.belongs_to?
47
+ end
48
+
49
+ def has_one?
50
+ return false if not association?
51
+ #return @reflect.has_one? # Rails 3 doesn't have this method
52
+ return false if @reflect.collection?
53
+ return false if @reflect.belongs_to?
54
+ return true
55
+ end
56
+
57
+ def primary_key
58
+ return @primary_key if @primary_key
59
+ return if not association?
60
+ return (@reflect.belongs_to? ? @reflect.klass : @reflect.active_record).primary_key
61
+ end
62
+
63
+ def foreign_key(reverse: false)
64
+ return @foreign_key if @foreign_key
65
+ return if not association?
66
+ # key may be symbol if specify foreign_key in association options
67
+ return @reflect.chain.last.foreign_key.to_s if reverse and join_table
68
+ return (@reflect.belongs_to? == reverse ? primary_key : @reflect.foreign_key).to_s
69
+ end
70
+
71
+ def single_association?
72
+ return false if not association?
73
+ return !collection?
74
+ end
75
+
76
+ def collection?
77
+ return false if not association?
78
+ return @reflect.collection?
79
+ end
80
+
81
+ def query_model(binding, id)
82
+ return query_self(binding, id) if @column == nil
83
+ return query_association(binding, id) if association?
84
+ return query_attribute(binding, id)
85
+ end
86
+
87
+ def extract_class_and_column
88
+ return [class_name, nil] if single_association?
89
+ return [@klass.to_s, @column]
90
+ end
91
+
92
+ private
93
+
94
+ def query_self(binding, id)
95
+ return binding if binding.is_a?(::ActiveRecord::Base)
96
+ return @klass.find_by(primary_key => id)
97
+ end
98
+
99
+ def query_attribute(binding, id)
100
+ return binding.send(@column) if binding.is_a?(::ActiveRecord::Base) and binding.has_attribute?(@column)
101
+ return @klass.where(id: id).limit(1).pluck(@column).first
102
+ end
103
+
104
+ def query_association(binding, id)
105
+ return binding.association(@column).load_target if binding.is_a?(::ActiveRecord::Base)
106
+ id = @reflect.active_record.where(id: id).limit(1).pluck(foreign_key).first if foreign_key != 'id'
107
+ case
108
+ when collection? ; return id ? @reflect.klass.where(@reflect.foreign_key => id).to_a : []
109
+ when has_one? ; return id ? @reflect.klass.find_by(foreign_key(reverse: true) => id) : nil
110
+ else ; return id ? @reflect.klass.find_by(primary_key => id) : nil
111
+ end
112
+ end
113
+
114
+ def through_klass_for_rails_3
115
+ const_name = "HABTM_#{@reflect.klass.name.pluralize}"
116
+ @klass.const_defined?(const_name) ? @klass.const_get(const_name) : @klass.const_set(const_name, create_through_klass_for_rails_3)
117
+ end
118
+
119
+ def create_through_klass_for_rails_3
120
+ Class.new(::ActiveRecord::Base).tap{|s| s.table_name = join_table }
121
+ end
122
+ end
123
+ end
124
+ end
@@ -1,97 +1,97 @@
1
- # frozen_string_literal: true
2
- module ActiveModelCachers
3
- module ActiveRecord
4
- class Cacher
5
- @defined_map = {}
6
-
7
- class << self
8
- def get_cacher_klass(klass)
9
- @defined_map[klass] ||= create_cacher_klass_at(klass)
10
- end
11
-
12
- def define_cacher_method(attr, primary_key, service_klasses)
13
- cacher_klass = get_cacher_klass(attr.klass)
14
- method = attr.column
15
- return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
16
- cacher_klass.send(:define_methods, method, {
17
- method => ->{ exec_by(attr, primary_key, service_klasses, :get) },
18
- "peek_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :peek) },
19
- "clean_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :clean_cache) },
20
- })
21
- end
22
-
23
- def define_find_by(attr, primary_key, service_klasses)
24
- if @find_by_mapping == nil
25
- @find_by_mapping = {}
26
- define_methods(:find_by, {
27
- :find_by => ->(args){ exec_find_by(args, :get) },
28
- :peek_by => ->(args){ exec_find_by(args, :peek) },
29
- :clean_by => ->(args){ exec_find_by(args, :clean_cache) },
30
- })
31
- end
32
- @find_by_mapping[primary_key] = [attr, service_klasses]
33
- end
34
-
35
- private
36
-
37
- def define_methods(attribute, methods_mapping)
38
- if attributes.include?(attribute)
39
- methods_mapping.keys.each{|s| undef_method(s) }
40
- else
41
- attributes << attribute
42
- end
43
- methods_mapping.each{|method, block| define_method(method, &block) }
44
- end
45
-
46
- def get_data_from_find_by_mapping(primary_key)
47
- return if @find_by_mapping == nil
48
- return @find_by_mapping[primary_key]
49
- end
50
-
51
- def create_cacher_klass_at(target)
52
- cacher_klass = Class.new(self)
53
- cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
54
- cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
55
- cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
56
- cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }
57
-
58
- target.define_singleton_method(:cacher_at){|id| cacher_klass.new(id: id) }
59
- target.define_singleton_method(:cacher){ cacher_klass.new }
60
- target.send(:define_method, :cacher){ cacher_klass.new(model: self) }
61
- return cacher_klass
62
- end
63
- end
64
-
65
- def initialize(id: nil, model: nil)
66
- @id = id
67
- @model = model
68
- end
69
-
70
- private
71
-
72
- def exec_find_by(args, method) # e.g. args = {course_id: xx}
73
- primary_key = args.keys.sort.first # Support only one key now.
74
- attr, service_klasses = self.class.send(:get_data_from_find_by_mapping, primary_key)
75
- return if service_klasses == nil
76
- return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
77
- end
78
-
79
- def exec_by(attr, primary_key, service_klasses, method, data: nil)
80
- bindings = [@model]
81
- reflects = (attr.belongs_to? ? [] : [attr.reflect])
82
- if @model and attr.association?
83
- if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
84
- association = @model.association(attr.column)
85
- bindings << association.load_target if association.loaded?
86
- end
87
- end
88
- data ||= (@model ? @model.send(primary_key) : nil) || @id
89
- service_klasses.each_with_index do |service_klass, index|
90
- data = service_klass.instance(data).send(method, binding: bindings[index], reflect: reflects[index])
91
- return if data == nil
92
- end
93
- return data
94
- end
95
- end
96
- end
97
- end
1
+ # frozen_string_literal: true
2
+ module ActiveModelCachers
3
+ module ActiveRecord
4
+ class Cacher
5
+ @defined_map = {}
6
+
7
+ class << self
8
+ def get_cacher_klass(klass)
9
+ @defined_map[klass] ||= create_cacher_klass_at(klass)
10
+ end
11
+
12
+ def define_cacher_method(attr, primary_key, service_klasses)
13
+ cacher_klass = get_cacher_klass(attr.klass)
14
+ method = attr.column
15
+ return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
16
+ cacher_klass.send(:define_methods, method, {
17
+ method => ->{ exec_by(attr, primary_key, service_klasses, :get) },
18
+ "peek_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :peek) },
19
+ "clean_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :clean_cache) },
20
+ })
21
+ end
22
+
23
+ def define_find_by(attr, primary_key, service_klasses)
24
+ if @find_by_mapping == nil
25
+ @find_by_mapping = {}
26
+ define_methods(:find_by, {
27
+ :find_by => ->(args){ exec_find_by(args, :get) },
28
+ :peek_by => ->(args){ exec_find_by(args, :peek) },
29
+ :clean_by => ->(args){ exec_find_by(args, :clean_cache) },
30
+ })
31
+ end
32
+ @find_by_mapping[primary_key] = [attr, service_klasses]
33
+ end
34
+
35
+ private
36
+
37
+ def define_methods(attribute, methods_mapping)
38
+ if attributes.include?(attribute)
39
+ methods_mapping.keys.each{|s| undef_method(s) }
40
+ else
41
+ attributes << attribute
42
+ end
43
+ methods_mapping.each{|method, block| define_method(method, &block) }
44
+ end
45
+
46
+ def get_data_from_find_by_mapping(primary_key)
47
+ return if @find_by_mapping == nil
48
+ return @find_by_mapping[primary_key]
49
+ end
50
+
51
+ def create_cacher_klass_at(target)
52
+ cacher_klass = Class.new(self)
53
+ cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
54
+ cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
55
+ cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
56
+ cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }
57
+
58
+ target.define_singleton_method(:cacher_at){|id| cacher_klass.new(id: id) }
59
+ target.define_singleton_method(:cacher){ cacher_klass.new }
60
+ target.send(:define_method, :cacher){ cacher_klass.new(model: self) }
61
+ return cacher_klass
62
+ end
63
+ end
64
+
65
+ def initialize(id: nil, model: nil)
66
+ @id = id
67
+ @model = model
68
+ end
69
+
70
+ private
71
+
72
+ def exec_find_by(args, method) # e.g. args = {course_id: xx}
73
+ primary_key = args.keys.sort.first # Support only one key now.
74
+ attr, service_klasses = self.class.send(:get_data_from_find_by_mapping, primary_key)
75
+ return if service_klasses == nil
76
+ return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
77
+ end
78
+
79
+ def exec_by(attr, primary_key, service_klasses, method, data: nil)
80
+ bindings = [@model]
81
+ reflects = (attr.belongs_to? ? [] : [attr.reflect])
82
+ if @model and attr.association?
83
+ if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
84
+ association = @model.association(attr.column)
85
+ bindings << association.load_target if association.loaded?
86
+ end
87
+ end
88
+ data ||= (@model ? @model.send(primary_key) : nil) || @id
89
+ service_klasses.each_with_index do |service_klass, index|
90
+ data = service_klass.instance(data).send(method, binding: bindings[index], reflect: reflects[index])
91
+ return if data == nil
92
+ end
93
+ return data
94
+ end
95
+ end
96
+ end
97
+ end