mobility 0.8.13 → 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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -2
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +63 -0
  5. data/Gemfile +5 -2
  6. data/Gemfile.lock +39 -20
  7. data/README.md +183 -93
  8. data/lib/mobility.rb +101 -169
  9. data/lib/mobility/backend.rb +27 -51
  10. data/lib/mobility/backends.rb +20 -0
  11. data/lib/mobility/backends/active_record.rb +4 -0
  12. data/lib/mobility/backends/active_record/column.rb +3 -1
  13. data/lib/mobility/backends/active_record/container.rb +10 -11
  14. data/lib/mobility/backends/active_record/hstore.rb +6 -4
  15. data/lib/mobility/backends/active_record/json.rb +5 -3
  16. data/lib/mobility/backends/active_record/jsonb.rb +5 -3
  17. data/lib/mobility/backends/active_record/key_value.rb +31 -13
  18. data/lib/mobility/backends/active_record/pg_hash.rb +1 -1
  19. data/lib/mobility/backends/active_record/serialized.rb +6 -0
  20. data/lib/mobility/backends/active_record/table.rb +17 -10
  21. data/lib/mobility/backends/column.rb +0 -6
  22. data/lib/mobility/backends/container.rb +10 -1
  23. data/lib/mobility/backends/hash.rb +39 -0
  24. data/lib/mobility/backends/hash_valued.rb +4 -0
  25. data/lib/mobility/backends/hstore.rb +0 -1
  26. data/lib/mobility/backends/json.rb +0 -1
  27. data/lib/mobility/backends/jsonb.rb +1 -2
  28. data/lib/mobility/backends/key_value.rb +31 -26
  29. data/lib/mobility/backends/null.rb +2 -0
  30. data/lib/mobility/backends/sequel.rb +37 -2
  31. data/lib/mobility/backends/sequel/column.rb +2 -0
  32. data/lib/mobility/backends/sequel/container.rb +11 -9
  33. data/lib/mobility/backends/sequel/hstore.rb +3 -1
  34. data/lib/mobility/backends/sequel/json.rb +3 -0
  35. data/lib/mobility/backends/sequel/jsonb.rb +3 -1
  36. data/lib/mobility/backends/sequel/key_value.rb +87 -18
  37. data/lib/mobility/backends/sequel/pg_hash.rb +6 -6
  38. data/lib/mobility/backends/sequel/serialized.rb +6 -0
  39. data/lib/mobility/backends/sequel/table.rb +22 -9
  40. data/lib/mobility/backends/serialized.rb +1 -3
  41. data/lib/mobility/backends/table.rb +39 -31
  42. data/lib/mobility/pluggable.rb +56 -0
  43. data/lib/mobility/plugin.rb +260 -0
  44. data/lib/mobility/plugins.rb +27 -24
  45. data/lib/mobility/plugins/active_model.rb +17 -0
  46. data/lib/mobility/plugins/active_model/cache.rb +26 -0
  47. data/lib/mobility/plugins/active_model/dirty.rb +119 -78
  48. data/lib/mobility/plugins/active_record.rb +37 -0
  49. data/lib/mobility/plugins/active_record/backend.rb +27 -0
  50. data/lib/mobility/plugins/active_record/cache.rb +28 -0
  51. data/lib/mobility/plugins/active_record/dirty.rb +34 -17
  52. data/lib/mobility/plugins/active_record/query.rb +43 -31
  53. data/lib/mobility/plugins/active_record/uniqueness_validation.rb +64 -0
  54. data/lib/mobility/plugins/arel.rb +125 -0
  55. data/lib/mobility/plugins/arel/nodes.rb +15 -0
  56. data/lib/mobility/plugins/arel/nodes/pg_ops.rb +134 -0
  57. data/lib/mobility/plugins/attribute_methods.rb +29 -20
  58. data/lib/mobility/plugins/attributes.rb +72 -0
  59. data/lib/mobility/plugins/backend.rb +161 -0
  60. data/lib/mobility/plugins/backend_reader.rb +34 -0
  61. data/lib/mobility/plugins/cache.rb +68 -26
  62. data/lib/mobility/plugins/default.rb +22 -17
  63. data/lib/mobility/plugins/dirty.rb +12 -33
  64. data/lib/mobility/plugins/fallbacks.rb +52 -44
  65. data/lib/mobility/plugins/fallthrough_accessors.rb +19 -23
  66. data/lib/mobility/plugins/locale_accessors.rb +22 -35
  67. data/lib/mobility/plugins/presence.rb +28 -21
  68. data/lib/mobility/plugins/query.rb +8 -17
  69. data/lib/mobility/plugins/reader.rb +50 -0
  70. data/lib/mobility/plugins/sequel.rb +34 -0
  71. data/lib/mobility/plugins/sequel/backend.rb +25 -0
  72. data/lib/mobility/plugins/sequel/cache.rb +24 -0
  73. data/lib/mobility/plugins/sequel/dirty.rb +34 -23
  74. data/lib/mobility/plugins/sequel/query.rb +21 -6
  75. data/lib/mobility/plugins/writer.rb +44 -0
  76. data/lib/mobility/translations.rb +95 -0
  77. data/lib/mobility/version.rb +12 -1
  78. data/lib/rails/generators/mobility/templates/create_string_translations.rb +0 -1
  79. data/lib/rails/generators/mobility/templates/create_text_translations.rb +0 -1
  80. data/lib/rails/generators/mobility/templates/initializer.rb +104 -78
  81. metadata +35 -40
  82. metadata.gz.sig +0 -0
  83. data/lib/mobility/active_model.rb +0 -4
  84. data/lib/mobility/active_model/backend_resetter.rb +0 -26
  85. data/lib/mobility/active_record.rb +0 -23
  86. data/lib/mobility/active_record/backend_resetter.rb +0 -26
  87. data/lib/mobility/active_record/model_translation.rb +0 -14
  88. data/lib/mobility/active_record/string_translation.rb +0 -10
  89. data/lib/mobility/active_record/text_translation.rb +0 -10
  90. data/lib/mobility/active_record/translation.rb +0 -14
  91. data/lib/mobility/active_record/uniqueness_validator.rb +0 -60
  92. data/lib/mobility/arel.rb +0 -49
  93. data/lib/mobility/arel/nodes.rb +0 -13
  94. data/lib/mobility/arel/nodes/pg_ops.rb +0 -132
  95. data/lib/mobility/arel/visitor.rb +0 -61
  96. data/lib/mobility/attributes.rb +0 -324
  97. data/lib/mobility/backend/orm_delegator.rb +0 -44
  98. data/lib/mobility/backend_resetter.rb +0 -50
  99. data/lib/mobility/configuration.rb +0 -138
  100. data/lib/mobility/fallbacks.rb +0 -28
  101. data/lib/mobility/interface.rb +0 -0
  102. data/lib/mobility/loaded.rb +0 -4
  103. data/lib/mobility/plugins/active_record/attribute_methods.rb +0 -38
  104. data/lib/mobility/plugins/cache/translation_cacher.rb +0 -40
  105. data/lib/mobility/sequel.rb +0 -9
  106. data/lib/mobility/sequel/backend_resetter.rb +0 -23
  107. data/lib/mobility/sequel/column_changes.rb +0 -28
  108. data/lib/mobility/sequel/hash_initializer.rb +0 -21
  109. data/lib/mobility/sequel/model_translation.rb +0 -20
  110. data/lib/mobility/sequel/sql.rb +0 -16
  111. data/lib/mobility/sequel/string_translation.rb +0 -10
  112. data/lib/mobility/sequel/text_translation.rb +0 -10
  113. data/lib/mobility/sequel/translation.rb +0 -53
  114. data/lib/mobility/translates.rb +0 -73
@@ -2,35 +2,38 @@ module Mobility
2
2
  =begin
3
3
 
4
4
  Plugins allow modular customization of backends independent of the backend
5
- itself. They are enabled through the {Configuration.plugins} configuration
6
- setting, which takes an array of symbols corresponding to plugin names. The
7
- order of these names is important since it determines the order in which
8
- plugins will be applied.
5
+ itself. They are enabled through {Mobility::Translations.plugins} (delegated to
6
+ from {Mobility.configure}), which takes a block within which plugins can be
7
+ declared in any order (dependencies will be resolved).
9
8
 
10
- So if our {Configuration.plugins} is an array +[:foo]+, and we call
11
- `translates` on our model, +Post+, like this:
9
+ =end
10
+ module Plugins
11
+ @plugins = {}
12
+ @names = {}
12
13
 
13
- class Post
14
- translates :title, foo: true
15
- end
14
+ class << self
15
+ # @param [Symbol] name Name of plugin to load.
16
+ def load_plugin(name)
17
+ return name if Module === name || name.nil?
16
18
 
17
- Then the +Foo+ plugin will be applied with the option value +true+. Applying a
18
- module calls a class method, +apply+ (in this case +Foo.apply+), which takes
19
- two arguments:
19
+ unless (plugin = @plugins[name])
20
+ require "mobility/plugins/#{name}"
21
+ raise LoadError, "plugin #{name} did not register itself correctly in Mobility::Plugins" unless (plugin = @plugins[name])
22
+ end
23
+ plugin
24
+ end
20
25
 
21
- - an instance of the {Attributes} class, +attributes+, from which the backend
22
- can configure the backend class (+attributes.backend_class+) and the model
23
- (+attributes.model_class+), and the +attributes+ module itself (which
24
- will be included into the backend).
25
- - the value of the +option+ passed into the model with +translates+ (in this
26
- case, +true+).
26
+ # @param [Module] plugin Plugin module to lookup. Plugin must already be loaded.
27
+ def lookup_name(plugin)
28
+ @names.fetch(plugin)
29
+ end
27
30
 
28
- Typically, the plugin will include a module into either
29
- +attributes.backend_class+ or +attributes+ itself, configured according to the
30
- option value. For examples, see classes under the {Mobility::Plugins} namespace.
31
+ def register_plugin(name, plugin)
32
+ @plugins[name] = plugin
33
+ @names[plugin] = name
34
+ end
31
35
 
32
- =end
33
- module Plugins
34
- OPTION_UNSET = Object.new
36
+ class LoadError < Error; end
37
+ end
35
38
  end
36
39
  end
@@ -1,6 +1,23 @@
1
+ require_relative "./active_model/dirty"
2
+ require_relative "./active_model/cache"
3
+
1
4
  module Mobility
2
5
  module Plugins
6
+ =begin
7
+
8
+ Plugin for ActiveModel models. In practice, this is simply a wrapper to include
9
+ a few plugins which apply to models which include ActiveModel::Dirty but are
10
+ not ActiveRecord models.
11
+
12
+ =end
3
13
  module ActiveModel
14
+ extend Plugin
15
+
16
+ requires :active_model_dirty
17
+ requires :active_model_cache
18
+ requires :backend, include: :before
4
19
  end
20
+
21
+ register_plugin(:active_model, ActiveModel)
5
22
  end
6
23
  end
@@ -0,0 +1,26 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Mobility
4
+ module Plugins
5
+ module ActiveModel
6
+ =begin
7
+
8
+ Adds hooks to clear Mobility cache when AM dirty reset methods are called.
9
+
10
+ =end
11
+ module Cache
12
+ extend Plugin
13
+
14
+ requires :cache, include: false
15
+
16
+ included_hook do |klass, _|
17
+ if options[:cache]
18
+ define_cache_hooks(klass, :changes_applied, :clear_changes_information)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ register_plugin(:active_model_cache, ActiveModel::Cache)
25
+ end
26
+ end
@@ -42,106 +42,138 @@ the ActiveRecord dirty plugin for more information.
42
42
 
43
43
  =end
44
44
  module Dirty
45
- # Builds module which adds suffix/prefix methods for translated
46
- # attributes so they act like normal dirty-tracked attributes.
47
- class MethodsBuilder < Module
48
- delegate :dirty_class, :handler_methods_module, :method_patterns, to: :class
45
+ extend Plugin
49
46
 
50
- def initialize(*attribute_names)
51
- define_dirty_methods(attribute_names)
47
+ requires :dirty, include: false
48
+
49
+ initialize_hook do
50
+ if options[:dirty]
51
+ define_dirty_methods(names)
52
+ include dirty_handler_methods
52
53
  end
54
+ end
53
55
 
54
- def included(model_class)
55
- model_class.include InstanceMethods
56
- model_class.include handler_methods_module
56
+ included_hook do |klass, backend_class|
57
+ raise TypeError, "#{name} should include ActiveModel::Dirty to use the active_model plugin" unless active_model_dirty_class?(klass)
57
58
 
58
- # In earlier versions of Rails, these methods are private
59
- %i[clear_attribute_changes clear_changes_information changes_applied].each do |method_name|
60
- if dirty_class.private_instance_methods.include?(method_name)
61
- model_class.class_eval { private method_name }
62
- end
63
- end
64
- end
59
+ if options[:dirty]
60
+ private_methods = InstanceMethods.instance_methods & klass.private_instance_methods
61
+ klass.include InstanceMethods
62
+ klass.class_eval { private(*private_methods) }
65
63
 
66
- def append_locale(attr_name)
67
- Mobility.normalize_locale_accessor(attr_name)
64
+ backend_class.include BackendMethods
68
65
  end
66
+ end
69
67
 
70
- private
68
+ private
71
69
 
72
- def define_dirty_methods(attribute_names)
73
- m = self
70
+ # Overridden in AR::Dirty plugin to define a different HandlerMethods module
71
+ def dirty_handler_methods
72
+ HandlerMethods
73
+ end
74
74
 
75
- attribute_names.each do |name|
76
- method_patterns.each do |pattern|
77
- define_method(pattern % name) do |*args|
78
- mutations_from_mobility.send(pattern % 'attribute', m.append_locale(name), *args)
79
- end
80
- end
75
+ def active_model_dirty_class?(klass)
76
+ klass.ancestors.include?(::ActiveModel::Dirty)
77
+ end
81
78
 
82
- define_method "restore_#{name}!" do
83
- locale_accessor = m.append_locale(name)
84
- if mutations_from_mobility.attribute_changed?(locale_accessor)
85
- __send__("#{name}=", mutations_from_mobility.attribute_was(locale_accessor))
86
- mutations_from_mobility.restore_attribute!(locale_accessor)
79
+ def define_dirty_methods(attribute_names)
80
+ attribute_names.each do |name|
81
+ dirty_handler_methods.each_pattern(name) do |method_name, attribute_method|
82
+ define_method(method_name) do |*args|
83
+ # for %s_changed?(from:, to:) pattern
84
+ if (kwargs = args.last).is_a?(Hash)
85
+ mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args[0,-1], **kwargs)
86
+ else
87
+ mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args)
87
88
  end
88
89
  end
89
90
  end
90
91
 
91
- # This private method override is necessary to make
92
- # +restore_attributes+ (which is public) work with translated
93
- # attributes.
94
- define_method :restore_attribute! do |attr|
95
- attribute_names.include?(attr.to_s) ? send("restore_#{attr}!") : super(attr)
96
- end
97
- private :restore_attribute!
98
- end
99
-
100
- class << self
101
- def handler_methods_module
102
- @handler_methods_module ||= (AttributeHandlerMethods.new.tap do |mod|
103
- public_method_patterns.each do |pattern|
104
- method_name = pattern % 'attribute'
105
-
106
- mod.module_eval <<-EOM, __FILE__, __LINE__ + 1
107
- def #{method_name}(attr_name, *rest)
108
- if (mutations_from_mobility.attribute_changed?(attr_name) ||
109
- mutations_from_mobility.attribute_previously_changed?(attr_name))
110
- mutations_from_mobility.send(#{method_name.inspect}, attr_name, *rest)
111
- else
112
- super
113
- end
114
- end
115
- EOM
116
- end
117
- end)
92
+ define_method "restore_#{name}!" do
93
+ locale_accessor = Dirty.append_locale(name)
94
+ if mutations_from_mobility.attribute_changed?(locale_accessor)
95
+ __send__("#{name}=", mutations_from_mobility.attribute_was(locale_accessor))
96
+ mutations_from_mobility.restore_attribute!(locale_accessor)
97
+ end
118
98
  end
99
+ end
100
+
101
+ # This private method override is necessary to make
102
+ # +restore_attributes+ (which is public) work with translated
103
+ # attributes.
104
+ define_method :restore_attribute! do |attr|
105
+ attribute_names.include?(attr.to_s) ? send("restore_#{attr}!") : super(attr)
106
+ end
107
+ private :restore_attribute!
108
+ end
119
109
 
120
- # Get method suffixes. Creating an object just to get the list of
121
- # suffixes is simplest given they change from Rails version to version.
122
- def method_patterns
123
- @method_patterns ||=
124
- (dirty_class.attribute_method_matchers.map { |p| "#{p.prefix}%s#{p.suffix}" } - excluded_method_patterns)
110
+ def self.append_locale(attr_name)
111
+ Mobility.normalize_locale_accessor(attr_name)
112
+ end
113
+
114
+ # Module builder which mimics dirty method handlers on a given dirty class.
115
+ # Used to mimic ActiveModel::Dirty and ActiveRecord::Dirty, which have
116
+ # similar but slightly different sets of handler methods. Doing it this
117
+ # way with introspection allows us to support basically all AR/AM
118
+ # versions without changes here.
119
+ class HandlerMethodsBuilder < Module
120
+ attr_reader :klass
121
+
122
+ # @param [Class] klass Dirty class to mimic
123
+ def initialize(klass)
124
+ @klass = klass
125
+ define_handler_methods
126
+ end
127
+
128
+ def each_pattern(attr_name)
129
+ patterns.each do |pattern|
130
+ yield pattern % attr_name, pattern % 'attribute'
125
131
  end
132
+ end
133
+
134
+ def define_handler_methods
135
+ public_patterns.each do |pattern|
136
+ method_name = pattern % 'attribute'
126
137
 
127
- def public_method_patterns
128
- @public_method_patterns ||= method_patterns.select do |p|
129
- !dirty_class.private_instance_methods.include?(:"#{p % 'attribute'}")
138
+ kwargs = pattern == '%s_changed?' ? ', **kwargs' : ''
139
+ module_eval <<-EOM, __FILE__, __LINE__ + 1
140
+ def #{method_name}(attr_name, *rest#{kwargs})
141
+ if (mutations_from_mobility.attribute_changed?(attr_name) ||
142
+ mutations_from_mobility.attribute_previously_changed?(attr_name))
143
+ mutations_from_mobility.send(#{method_name.inspect}, attr_name, *rest#{kwargs})
144
+ else
145
+ super
146
+ end
130
147
  end
148
+ EOM
131
149
  end
150
+ end
132
151
 
133
- def dirty_class
134
- @dirty_class ||= Class.new { include ::ActiveModel::Dirty }
135
- end
152
+ # Get method suffixes. Creating an object just to get the list of
153
+ # suffixes is simplest given they change from Rails version to version.
154
+ def patterns
155
+ @patterns ||=
156
+ (klass.attribute_method_matchers.map { |p| "#{p.prefix}%s#{p.suffix}" } - excluded_patterns)
157
+ end
136
158
 
137
- private
159
+ private
138
160
 
139
- def excluded_method_patterns
140
- ['%s', 'restore_%s!']
161
+ def public_patterns
162
+ @public_patterns ||= patterns.select do |p|
163
+ klass.public_method_defined?(p % 'attribute')
141
164
  end
142
165
  end
166
+
167
+ def excluded_patterns
168
+ ['%s', 'restore_%s!']
169
+ end
143
170
  end
144
171
 
172
+ # Module which defines generic handler methods like
173
+ # +attribute_changed?+ that are patched to work with translated
174
+ # attributes.
175
+ HandlerMethods = HandlerMethodsBuilder.new(Class.new { include ::ActiveModel::Dirty })
176
+
145
177
  module InstanceMethods
146
178
  def changed_attributes
147
179
  super.merge(mutations_from_mobility.changed_attributes)
@@ -186,9 +218,16 @@ the ActiveRecord dirty plugin for more information.
186
218
  end
187
219
  end
188
220
 
189
- # Give the module builder a name so it's easier to see in the model's ancestors
190
- class AttributeHandlerMethods < Module; end
191
-
221
+ # @note Seriously, I really don't want to reproduce all of
222
+ # ActiveModel::Dirty here, but having fought with upstream changes
223
+ # many many times I finally decided it's more future-proof to just
224
+ # re-implement the stuff we need here, to avoid weird breakage.
225
+ #
226
+ # Although this is somewhat ugly, at least it's explicit and since
227
+ # it's self-defined (rather than hooking into fickle private methods
228
+ # in Rails), it won't break all of a sudden. We just need to ensure
229
+ # that specs are up-to-date with the latest weird dirty method
230
+ # pattern Rails has decided to support.
192
231
  class MobilityMutationTracker
193
232
  OPTION_NOT_GIVEN = Object.new
194
233
 
@@ -297,11 +336,11 @@ the ActiveRecord dirty plugin for more information.
297
336
  # @!group Backend Accessors
298
337
  # @!macro backend_writer
299
338
  # @param [Hash] options
300
- def write(locale, value, options = {})
339
+ def write(locale, value, **options)
301
340
  locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
302
341
  if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
303
342
  mutations_from_mobility.restore_attribute!(locale_accessor)
304
- elsif read(locale, options.merge(locale: true)) != value
343
+ elsif read(locale, **options.merge(locale: true)) != value
305
344
  mutations_from_mobility.attribute_will_change!(locale_accessor)
306
345
  end
307
346
  super
@@ -316,5 +355,7 @@ the ActiveRecord dirty plugin for more information.
316
355
  end
317
356
  end
318
357
  end
358
+
359
+ register_plugin(:active_model_dirty, ActiveModel::Dirty)
319
360
  end
320
361
  end
@@ -1,6 +1,43 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./active_record/backend"
3
+ require_relative "./active_record/dirty"
4
+ require_relative "./active_record/cache"
5
+ require_relative "./active_record/query"
6
+ require_relative "./active_record/uniqueness_validation"
7
+
1
8
  module Mobility
9
+ =begin
10
+
11
+ Plugin for ActiveRecord models.
12
+
13
+ =end
2
14
  module Plugins
3
15
  module ActiveRecord
16
+ extend Plugin
17
+
18
+ requires :arel
19
+
20
+ requires :active_record_backend, include: :after
21
+ requires :active_record_dirty
22
+ requires :active_record_cache
23
+ requires :active_record_query
24
+ requires :active_record_uniqueness_validation
25
+
26
+
27
+ included_hook do |klass|
28
+ unless active_record_class?(klass)
29
+ name = klass.name || klass.to_s
30
+ raise TypeError, "#{name} should be a subclass of ActiveRecord::Base to use the active_record plugin"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def active_record_class?(klass)
37
+ klass < ::ActiveRecord::Base
38
+ end
4
39
  end
40
+
41
+ register_plugin(:active_record, ActiveRecord)
5
42
  end
6
43
  end
@@ -0,0 +1,27 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Mobility
4
+ module Plugins
5
+ module ActiveRecord
6
+ module Backend
7
+ extend Plugin
8
+
9
+ requires :backend, include: :before
10
+
11
+ def load_backend(backend)
12
+ if Symbol === backend
13
+ require "mobility/backends/active_record/#{backend}"
14
+ Backends.load_backend("active_record_#{backend}".to_sym)
15
+ else
16
+ super
17
+ end
18
+ rescue LoadError => e
19
+ raise unless e.message =~ /active_record\/#{backend}/
20
+ super
21
+ end
22
+ end
23
+ end
24
+
25
+ register_plugin(:active_record_backend, ActiveRecord::Backend)
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen-string-literal: true
2
+ require "mobility/plugins/active_model/cache"
3
+
4
+ module Mobility
5
+ module Plugins
6
+ module ActiveRecord
7
+ =begin
8
+
9
+ Resets cache on calls to +reload+, in addition to other AM dirty reset
10
+ methods.
11
+
12
+ =end
13
+ module Cache
14
+ extend Plugin
15
+
16
+ requires :cache, include: false
17
+
18
+ included_hook do |klass, _|
19
+ if options[:cache]
20
+ define_cache_hooks(klass, :changes_applied, :clear_changes_information, :reload)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ register_plugin(:active_record_cache, ActiveRecord::Cache)
27
+ end
28
+ end