mobility 0.8.8 → 1.0.0.alpha
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +56 -0
- data/Gemfile +52 -16
- data/Gemfile.lock +113 -52
- data/Guardfile +23 -1
- data/README.md +184 -92
- data/Rakefile +6 -4
- data/lib/mobility.rb +40 -166
- data/lib/mobility/active_record/translation.rb +1 -1
- data/lib/mobility/arel/nodes/pg_ops.rb +1 -1
- data/lib/mobility/backend.rb +19 -41
- data/lib/mobility/backends.rb +20 -0
- data/lib/mobility/backends/active_record.rb +4 -0
- data/lib/mobility/backends/active_record/column.rb +2 -0
- data/lib/mobility/backends/active_record/container.rb +4 -2
- data/lib/mobility/backends/active_record/hstore.rb +2 -0
- data/lib/mobility/backends/active_record/json.rb +2 -0
- data/lib/mobility/backends/active_record/jsonb.rb +2 -0
- data/lib/mobility/backends/active_record/key_value.rb +5 -3
- data/lib/mobility/backends/active_record/pg_hash.rb +1 -1
- data/lib/mobility/backends/active_record/serialized.rb +2 -0
- data/lib/mobility/backends/active_record/table.rb +5 -3
- data/lib/mobility/backends/column.rb +0 -6
- data/lib/mobility/backends/container.rb +2 -1
- data/lib/mobility/backends/hash.rb +39 -0
- data/lib/mobility/backends/hstore.rb +0 -1
- data/lib/mobility/backends/json.rb +0 -1
- data/lib/mobility/backends/jsonb.rb +0 -1
- data/lib/mobility/backends/key_value.rb +22 -14
- data/lib/mobility/backends/null.rb +2 -0
- data/lib/mobility/backends/sequel.rb +3 -0
- data/lib/mobility/backends/sequel/column.rb +2 -0
- data/lib/mobility/backends/sequel/container.rb +3 -1
- data/lib/mobility/backends/sequel/hstore.rb +2 -0
- data/lib/mobility/backends/sequel/json.rb +2 -0
- data/lib/mobility/backends/sequel/jsonb.rb +3 -1
- data/lib/mobility/backends/sequel/key_value.rb +8 -6
- data/lib/mobility/backends/sequel/serialized.rb +2 -0
- data/lib/mobility/backends/sequel/table.rb +5 -2
- data/lib/mobility/backends/serialized.rb +1 -3
- data/lib/mobility/backends/table.rb +14 -6
- data/lib/mobility/pluggable.rb +36 -0
- data/lib/mobility/plugin.rb +260 -0
- data/lib/mobility/plugins.rb +26 -25
- data/lib/mobility/plugins/active_model.rb +17 -0
- data/lib/mobility/plugins/active_model/cache.rb +26 -0
- data/lib/mobility/plugins/active_model/dirty.rb +310 -54
- data/lib/mobility/plugins/active_record.rb +34 -0
- data/lib/mobility/plugins/active_record/backend.rb +25 -0
- data/lib/mobility/plugins/active_record/cache.rb +28 -0
- data/lib/mobility/plugins/active_record/dirty.rb +72 -101
- data/lib/mobility/plugins/active_record/query.rb +48 -34
- data/lib/mobility/plugins/active_record/uniqueness_validation.rb +60 -0
- data/lib/mobility/plugins/attribute_methods.rb +28 -20
- data/lib/mobility/plugins/attributes.rb +70 -0
- data/lib/mobility/plugins/backend.rb +138 -0
- data/lib/mobility/plugins/backend_reader.rb +34 -0
- data/lib/mobility/plugins/cache.rb +59 -24
- data/lib/mobility/plugins/default.rb +22 -17
- data/lib/mobility/plugins/dirty.rb +12 -33
- data/lib/mobility/plugins/fallbacks.rb +51 -43
- data/lib/mobility/plugins/fallthrough_accessors.rb +26 -25
- data/lib/mobility/plugins/locale_accessors.rb +25 -35
- data/lib/mobility/plugins/presence.rb +28 -21
- data/lib/mobility/plugins/query.rb +8 -17
- data/lib/mobility/plugins/reader.rb +50 -0
- data/lib/mobility/plugins/sequel.rb +34 -0
- data/lib/mobility/plugins/sequel/backend.rb +25 -0
- data/lib/mobility/plugins/sequel/cache.rb +24 -0
- data/lib/mobility/plugins/sequel/dirty.rb +45 -32
- data/lib/mobility/plugins/sequel/query.rb +21 -6
- data/lib/mobility/plugins/writer.rb +44 -0
- data/lib/mobility/translations.rb +95 -0
- data/lib/mobility/version.rb +12 -1
- data/lib/rails/generators/mobility/templates/initializer.rb +95 -77
- metadata +51 -51
- metadata.gz.sig +0 -0
- data/lib/mobility/active_model.rb +0 -4
- data/lib/mobility/active_model/backend_resetter.rb +0 -26
- data/lib/mobility/active_record.rb +0 -23
- data/lib/mobility/active_record/backend_resetter.rb +0 -26
- data/lib/mobility/active_record/uniqueness_validator.rb +0 -60
- data/lib/mobility/attributes.rb +0 -324
- data/lib/mobility/backend/orm_delegator.rb +0 -44
- data/lib/mobility/backend_resetter.rb +0 -50
- data/lib/mobility/configuration.rb +0 -138
- data/lib/mobility/fallbacks.rb +0 -28
- data/lib/mobility/interface.rb +0 -0
- data/lib/mobility/loaded.rb +0 -4
- data/lib/mobility/plugins/active_record/attribute_methods.rb +0 -38
- data/lib/mobility/plugins/cache/translation_cacher.rb +0 -40
- data/lib/mobility/sequel.rb +0 -9
- data/lib/mobility/sequel/backend_resetter.rb +0 -23
- data/lib/mobility/translates.rb +0 -73
@@ -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
|
@@ -17,83 +17,339 @@ following methods:
|
|
17
17
|
- +title_previous_change+
|
18
18
|
- +restore_title!+
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
The following methods are also patched to work with translated attributes:
|
21
|
+
- +changed_attributes+
|
22
|
+
- +changes+
|
23
|
+
- +changed+
|
24
|
+
- +changed?+
|
25
|
+
- +previous_changes+
|
26
|
+
- +clear_attribute_changes+
|
27
|
+
- +restore_attributes+
|
28
|
+
|
29
|
+
In addition, the following ActiveModel attribute handler methods are also
|
30
|
+
patched to work with translated attributes:
|
31
|
+
- +attribute_changed?+
|
32
|
+
- +attribute_previously_changed?+
|
33
|
+
- +attribute_was+
|
34
|
+
|
35
|
+
(When using these methods, you must pass the attribute name along with its
|
36
|
+
locale suffix, so +title_en+, +title_pt_br+, etc.)
|
37
|
+
|
38
|
+
Other methods are also included for ActiveRecord models, see documentation on
|
39
|
+
the ActiveRecord dirty plugin for more information.
|
22
40
|
|
23
41
|
@see http://api.rubyonrails.org/classes/ActiveModel/Dirty.html Rails documentation for Active Model Dirty module
|
24
42
|
|
25
43
|
=end
|
26
44
|
module Dirty
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
model.send(:attribute_will_change!, locale_accessor)
|
37
|
-
end
|
38
|
-
super
|
45
|
+
extend Plugin
|
46
|
+
|
47
|
+
requires :dirty, include: false
|
48
|
+
|
49
|
+
initialize_hook do
|
50
|
+
if options[:dirty]
|
51
|
+
define_dirty_methods(names)
|
52
|
+
include dirty_handler_methods
|
53
|
+
end
|
39
54
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
|
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)
|
58
|
+
|
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) }
|
63
|
+
|
64
|
+
backend_class.include BackendMethods
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Overridden in AR::Dirty plugin to define a different HandlerMethods module
|
71
|
+
def dirty_handler_methods
|
72
|
+
HandlerMethods
|
73
|
+
end
|
74
|
+
|
75
|
+
def active_model_dirty_class?(klass)
|
76
|
+
klass.ancestors.include?(::ActiveModel::Dirty)
|
77
|
+
end
|
78
|
+
|
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
|
+
mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args)
|
51
84
|
end
|
85
|
+
end
|
86
|
+
|
87
|
+
define_method "restore_#{name}!" do
|
88
|
+
locale_accessor = Dirty.append_locale(name)
|
89
|
+
if mutations_from_mobility.attribute_changed?(locale_accessor)
|
90
|
+
__send__("#{name}=", mutations_from_mobility.attribute_was(locale_accessor))
|
91
|
+
mutations_from_mobility.restore_attribute!(locale_accessor)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# This private method override is necessary to make
|
97
|
+
# +restore_attributes+ (which is public) work with translated
|
98
|
+
# attributes.
|
99
|
+
define_method :restore_attribute! do |attr|
|
100
|
+
attribute_names.include?(attr.to_s) ? send("restore_#{attr}!") : super(attr)
|
101
|
+
end
|
102
|
+
private :restore_attribute!
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.append_locale(attr_name)
|
106
|
+
Mobility.normalize_locale_accessor(attr_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Module builder which mimics dirty method handlers on a given dirty class.
|
110
|
+
# Used to mimic ActiveModel::Dirty and ActiveRecord::Dirty, which have
|
111
|
+
# similar but slightly different sets of handler methods. Doing it this
|
112
|
+
# way with introspection allows us to support basically all AR/AM
|
113
|
+
# versions without changes here.
|
114
|
+
class HandlerMethodsBuilder < Module
|
115
|
+
attr_reader :klass
|
52
116
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
117
|
+
# @param [Class] klass Dirty class to mimic
|
118
|
+
def initialize(klass)
|
119
|
+
@klass = klass
|
120
|
+
define_handler_methods
|
121
|
+
end
|
122
|
+
|
123
|
+
def each_pattern(attr_name)
|
124
|
+
patterns.each do |pattern|
|
125
|
+
yield pattern % attr_name, pattern % 'attribute'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def define_handler_methods
|
130
|
+
public_patterns.each do |pattern|
|
131
|
+
method_name = pattern % 'attribute'
|
132
|
+
|
133
|
+
module_eval <<-EOM, __FILE__, __LINE__ + 1
|
134
|
+
def #{method_name}(attr_name, *rest)
|
135
|
+
if (mutations_from_mobility.attribute_changed?(attr_name) ||
|
136
|
+
mutations_from_mobility.attribute_previously_changed?(attr_name))
|
137
|
+
mutations_from_mobility.send(#{method_name.inspect}, attr_name, *rest)
|
138
|
+
else
|
139
|
+
super
|
57
140
|
end
|
58
141
|
end
|
142
|
+
EOM
|
59
143
|
end
|
144
|
+
end
|
60
145
|
|
61
|
-
|
62
|
-
|
146
|
+
# Get method suffixes. Creating an object just to get the list of
|
147
|
+
# suffixes is simplest given they change from Rails version to version.
|
148
|
+
def patterns
|
149
|
+
@patterns ||=
|
150
|
+
(klass.attribute_method_matchers.map { |p| "#{p.prefix}%s#{p.suffix}" } - excluded_patterns)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def public_patterns
|
156
|
+
@public_patterns ||= patterns.select do |p|
|
157
|
+
klass.public_method_defined?(p % 'attribute')
|
63
158
|
end
|
64
|
-
private :restore_attribute!
|
65
159
|
end
|
66
160
|
|
67
|
-
def
|
68
|
-
|
161
|
+
def excluded_patterns
|
162
|
+
['%s', 'restore_%s!']
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Module which defines generic handler methods like
|
167
|
+
# +attribute_changed?+ that are patched to work with translated
|
168
|
+
# attributes.
|
169
|
+
HandlerMethods = HandlerMethodsBuilder.new(Class.new { include ::ActiveModel::Dirty })
|
170
|
+
|
171
|
+
module InstanceMethods
|
172
|
+
def changed_attributes
|
173
|
+
super.merge(mutations_from_mobility.changed_attributes)
|
174
|
+
end
|
175
|
+
|
176
|
+
def changes_applied
|
177
|
+
super
|
178
|
+
mutations_from_mobility.finalize_changes
|
179
|
+
end
|
180
|
+
|
181
|
+
def changes
|
182
|
+
super.merge(mutations_from_mobility.changes)
|
183
|
+
end
|
184
|
+
|
185
|
+
def changed
|
186
|
+
# uniq is required for Rails < 6.0
|
187
|
+
(super + mutations_from_mobility.changed).uniq
|
188
|
+
end
|
189
|
+
|
190
|
+
def changed?
|
191
|
+
super || mutations_from_mobility.changed?
|
192
|
+
end
|
193
|
+
|
194
|
+
def previous_changes
|
195
|
+
super.merge(mutations_from_mobility.previous_changes)
|
196
|
+
end
|
197
|
+
|
198
|
+
def clear_changes_information
|
199
|
+
@mutations_from_mobility = nil
|
200
|
+
super
|
201
|
+
end
|
202
|
+
|
203
|
+
def clear_attribute_changes(attr_names)
|
204
|
+
attr_names.each { |attr_name| mutations_from_mobility.restore_attribute!(attr_name) }
|
205
|
+
super
|
69
206
|
end
|
70
207
|
|
71
208
|
private
|
72
209
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
210
|
+
def mutations_from_mobility
|
211
|
+
@mutations_from_mobility ||= MobilityMutationTracker.new(self)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# @note Seriously, I really don't want to reproduce all of
|
216
|
+
# ActiveModel::Dirty here, but having fought with upstream changes
|
217
|
+
# many many times I finally decided it's more future-proof to just
|
218
|
+
# re-implement the stuff we need here, to avoid weird breakage.
|
219
|
+
#
|
220
|
+
# Although this is somewhat ugly, at least it's explicit and since
|
221
|
+
# it's self-defined (rather than hooking into fickle private methods
|
222
|
+
# in Rails), it won't break all of a sudden. We just need to ensure
|
223
|
+
# that specs are up-to-date with the latest weird dirty method
|
224
|
+
# pattern Rails has decided to support.
|
225
|
+
class MobilityMutationTracker
|
226
|
+
OPTION_NOT_GIVEN = Object.new
|
227
|
+
|
228
|
+
attr_reader :previous_changes
|
229
|
+
|
230
|
+
def initialize(model)
|
231
|
+
@model = model
|
232
|
+
@current_changes = {}.with_indifferent_access
|
233
|
+
@previous_changes = {}.with_indifferent_access
|
234
|
+
end
|
235
|
+
|
236
|
+
def finalize_changes
|
237
|
+
@previous_changes = changes
|
238
|
+
@current_changes = {}.with_indifferent_access
|
239
|
+
end
|
240
|
+
|
241
|
+
def changed
|
242
|
+
attr_names.select { |attr_name| attribute_changed?(attr_name) }
|
243
|
+
end
|
244
|
+
|
245
|
+
def changed_attributes
|
246
|
+
attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
|
247
|
+
if attribute_changed?(attr_name)
|
248
|
+
result[attr_name] = attribute_was(attr_name)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def changes
|
254
|
+
attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
|
255
|
+
if change = attribute_change(attr_name)
|
256
|
+
result.merge!(attr_name => change)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def changed?
|
262
|
+
attr_names.any? { |attr| attribute_changed?(attr) }
|
263
|
+
end
|
264
|
+
|
265
|
+
def attribute_change(attr_name)
|
266
|
+
if attribute_changed?(attr_name)
|
267
|
+
[attribute_was(attr_name), fetch_value(attr_name)]
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def attribute_previous_change(attr_name)
|
272
|
+
previous_changes[attr_name]
|
273
|
+
end
|
274
|
+
|
275
|
+
def attribute_previously_was(attr_name)
|
276
|
+
if attribute_previously_changed?(attr_name)
|
277
|
+
# Calling +first+ here fetches the value before change from the
|
278
|
+
# hash.
|
279
|
+
previous_changes[attr_name].first
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def attribute_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN)
|
284
|
+
current_changes.include?(attr_name) &&
|
285
|
+
(OPTION_NOT_GIVEN == from || attribute_was(attr_name) == from) &&
|
286
|
+
(OPTION_NOT_GIVEN == to || fetch_value(attr_name) == to)
|
287
|
+
end
|
288
|
+
|
289
|
+
def attribute_previously_changed?(attr_name)
|
290
|
+
previous_changes.include?(attr_name)
|
291
|
+
end
|
292
|
+
|
293
|
+
def attribute_was(attr_name)
|
294
|
+
if attribute_changed?(attr_name)
|
295
|
+
current_changes[attr_name]
|
296
|
+
else
|
297
|
+
fetch_value(attr_name)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def attribute_will_change!(attr_name)
|
302
|
+
current_changes[attr_name] = fetch_value(attr_name) unless current_changes.include?(attr_name)
|
303
|
+
end
|
304
|
+
|
305
|
+
def restore_attribute!(attr_name)
|
306
|
+
current_changes.delete(attr_name)
|
307
|
+
end
|
308
|
+
|
309
|
+
# These are for ActiveRecord, but we'll define them here.
|
310
|
+
alias_method :saved_change_to_attribute?, :attribute_previously_changed?
|
311
|
+
alias_method :saved_change_to_attribute, :attribute_previous_change
|
312
|
+
alias_method :attribute_before_last_save, :attribute_previously_was
|
313
|
+
alias_method :will_save_change_to_attribute?, :attribute_changed?
|
314
|
+
alias_method :attribute_change_to_be_saved, :attribute_change
|
315
|
+
alias_method :attribute_in_database, :attribute_was
|
316
|
+
|
317
|
+
private
|
318
|
+
attr_reader :model, :current_changes
|
319
|
+
|
320
|
+
def attr_names
|
321
|
+
current_changes.keys
|
322
|
+
end
|
323
|
+
|
324
|
+
def fetch_value(attr_name)
|
325
|
+
model.__send__(attr_name)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
module BackendMethods
|
330
|
+
# @!group Backend Accessors
|
331
|
+
# @!macro backend_writer
|
332
|
+
# @param [Hash] options
|
333
|
+
def write(locale, value, options = {})
|
334
|
+
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
|
335
|
+
if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
|
336
|
+
mutations_from_mobility.restore_attribute!(locale_accessor)
|
337
|
+
elsif read(locale, options.merge(locale: true)) != value
|
338
|
+
mutations_from_mobility.attribute_will_change!(locale_accessor)
|
93
339
|
end
|
340
|
+
super
|
341
|
+
end
|
342
|
+
# @!endgroup
|
343
|
+
|
344
|
+
private
|
345
|
+
|
346
|
+
def mutations_from_mobility
|
347
|
+
model.send(:mutations_from_mobility)
|
94
348
|
end
|
95
349
|
end
|
96
350
|
end
|
97
351
|
end
|
352
|
+
|
353
|
+
register_plugin(:active_model_dirty, ActiveModel::Dirty)
|
98
354
|
end
|
99
355
|
end
|
@@ -1,6 +1,40 @@
|
|
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 :active_record_backend, include: :after
|
19
|
+
requires :active_record_dirty
|
20
|
+
requires :active_record_cache
|
21
|
+
requires :active_record_query
|
22
|
+
requires :active_record_uniqueness_validation
|
23
|
+
|
24
|
+
included_hook do |klass|
|
25
|
+
unless active_record_class?(klass)
|
26
|
+
name = klass.name || klass.to_s
|
27
|
+
raise TypeError, "#{name} should be a subclass of ActiveRecord::Base to use the active_record plugin"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def active_record_class?(klass)
|
34
|
+
klass < ::ActiveRecord::Base
|
35
|
+
end
|
4
36
|
end
|
37
|
+
|
38
|
+
register_plugin(:active_record, ActiveRecord)
|
5
39
|
end
|
6
40
|
end
|