mobility 0.8.8 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 157698dc2cfdf847b956ae45dd3ff8c447800053b07b3b68bf848feefc8e690f
4
- data.tar.gz: b711720dae3e3eb480bcd630045daa56873b03f101b623b707c0eb8735b5936a
3
+ metadata.gz: 792cd0d08532672e8bef3620b2e0741c6dab8bbe7105b80638ac5c0468e02a43
4
+ data.tar.gz: 76d31ca70d2b207c9612284a934f10b2ea0d68ad56f98ee92e03207323239841
5
5
  SHA512:
6
- metadata.gz: 22843bcb2a06b050a0b38fe76a970097ea0e1082c2095414419ad1f32fd980f21f7a9853bb471c18a9c6c8bb5786652b0f42e3a6577d17ae103257ddf19da0fe
7
- data.tar.gz: 0527fabbd7ed167e6431b8ce2bc9239cf99c13c6f0d2ac9e3074896423fa459453091b54471b43c74f17bbbc2c44af89452854c59313b071828eacc236940590
6
+ metadata.gz: c8194524ecaa6bd398d911b028f9a4029e374db423887ac1a7e21b68e501290531284c718733795df08b6d9d173033188bb28ac57c1aca9b897271788a812a7c
7
+ data.tar.gz: a89d634b7350cf01758cc929d36e354376ac9c2f9ee08b183e24f0200377756ba6950cd5d80b62b045527cbb43cf5a0c1e739564f1890b81bbfbcf68c8800cd5
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## 0.8
4
4
 
5
+ ### 0.8.9 (October 25, 2019)
6
+ * Fix Dirty plugin to work with Rails 6
7
+ ([#343](https://github.com/shioyama/mobility/pull/343),
8
+ [#348](https://github.com/shioyama/mobility/pull/348),
9
+ [#352](https://github.com/shioyama/mobility/pull/352) on master branch, plus
10
+ [#351](https://github.com/shioyama/mobility/pull/351) to sync to 0-8-stable
11
+ branch). Summary of changes
12
+ [here](https://github.com/shioyama/mobility/pull/347#issuecomment-544742401).
13
+
5
14
  ### 0.8.8 (September 18, 2019)
6
15
  * Accept any number of arguments to `Arel::Visitors::Visitor#visit`
7
16
  ([#339](https://github.com/shioyama/mobility/pull/339)). (Thanks to
data/Gemfile CHANGED
@@ -11,11 +11,11 @@ group :development, :test do
11
11
  gem 'activerecord', '>= 4.2.6', '< 5.0'
12
12
  elsif ENV['RAILS_VERSION'] == '5.1'
13
13
  gem 'activerecord', '>= 5.1', '< 5.2'
14
- elsif ENV['RAILS_VERSION'] == 'latest'
15
- gem 'activerecord', '>= 6.0.0.beta1'
16
- else # Default is Rails 5.2
14
+ elsif ENV['RAILS_VERSION'] == '5.2'
17
15
  gem 'activerecord', '>= 5.2.0', '< 5.3'
18
16
  gem 'railties', '>= 5.2.0.rc2', '< 5.3'
17
+ else # Default is Rails 6.0
18
+ gem 'activerecord', '>= 6.0.0', '< 6.1'
19
19
  end
20
20
  gem "generator_spec", '~> 0.9.4'
21
21
  elsif ENV['ORM'] == 'sequel'
@@ -31,7 +31,11 @@ group :development, :test do
31
31
  platforms :ruby do
32
32
  gem 'guard-rspec'
33
33
  gem 'pry-byebug'
34
- gem 'sqlite3', '~> 1.3.6'
34
+ if ENV['ORM'] == 'active_record' && ENV['RAILS_VERSION'] < '5.2'
35
+ gem 'sqlite3', '~> 1.3.13'
36
+ else
37
+ gem 'sqlite3', '~> 1.4.1'
38
+ end
35
39
  gem 'mysql2', '~> 0.4.9'
36
40
  gem 'pg', '< 1.0'
37
41
  end
data/README.md CHANGED
@@ -51,7 +51,7 @@ Installation
51
51
  Add this line to your application's Gemfile:
52
52
 
53
53
  ```ruby
54
- gem 'mobility', '~> 0.8.8'
54
+ gem 'mobility', '~> 0.8.9'
55
55
  ```
56
56
 
57
57
  Mobility is cryptographically signed. To be sure the gem you install hasn't
@@ -68,7 +68,7 @@ installation of unsigned dependencies.
68
68
  ### ActiveRecord (Rails)
69
69
 
70
70
  Requirements:
71
- - ActiveRecord >= 5.0
71
+ - ActiveRecord >= 5.0 (including 6.0)
72
72
 
73
73
  (Support for most backends and features is also supported with
74
74
  ActiveRecord/Rails 4.2, but there are some tests still failing. To see exactly
@@ -17,81 +17,302 @@ following methods:
17
17
  - +title_previous_change+
18
18
  - +restore_title!+
19
19
 
20
- In addition, the private method +restore_attribute!+ will also restore the
21
- value of the translated attribute if passed to it.
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
- # @!group Backend Accessors
28
- # @!macro backend_writer
29
- # @param [Hash] options
30
- def write(locale, value, options = {})
31
- locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
32
- if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
33
- model.send(:attributes_changed_by_setter).except!(locale_accessor)
34
- elsif read(locale, options.merge(locale: true)) != value
35
- model.send(:mobility_changed_attributes) << locale_accessor
36
- model.send(:attribute_will_change!, locale_accessor)
37
- end
38
- super
39
- end
40
- # @!endgroup
41
-
42
45
  # Builds module which adds suffix/prefix methods for translated
43
46
  # attributes so they act like normal dirty-tracked attributes.
44
47
  class MethodsBuilder < Module
48
+ delegate :dirty_class, :handler_methods_module, :method_patterns, to: :class
49
+
45
50
  def initialize(*attribute_names)
51
+ define_dirty_methods(attribute_names)
52
+ end
53
+
54
+ def included(model_class)
55
+ model_class.include InstanceMethods
56
+ model_class.include handler_methods_module
57
+
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
65
+
66
+ def append_locale(attr_name)
67
+ Mobility.normalize_locale_accessor(attr_name)
68
+ end
69
+
70
+ private
71
+
72
+ def define_dirty_methods(attribute_names)
73
+ m = self
74
+
46
75
  attribute_names.each do |name|
47
- method_suffixes.each do |suffix|
48
- define_method "#{name}#{suffix}" do
49
- __send__("attribute#{suffix}", Mobility.normalize_locale_accessor(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)
50
79
  end
51
80
  end
52
81
 
53
82
  define_method "restore_#{name}!" do
54
- locale_accessor = Mobility.normalize_locale_accessor(name)
55
- if attribute_changed?(locale_accessor)
56
- __send__("#{name}=", changed_attributes[locale_accessor])
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)
57
87
  end
58
88
  end
59
89
  end
60
90
 
91
+ # This private method override is necessary to make
92
+ # +restore_attributes+ (which is public) work with translated
93
+ # attributes.
61
94
  define_method :restore_attribute! do |attr|
62
95
  attribute_names.include?(attr.to_s) ? send("restore_#{attr}!") : super(attr)
63
96
  end
64
97
  private :restore_attribute!
65
98
  end
66
99
 
67
- def included(model_class)
68
- model_class.include ChangedAttributes
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)
118
+ end
119
+
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)
125
+ end
126
+
127
+ def public_method_patterns
128
+ @public_method_patterns ||= method_patterns.select do |p|
129
+ !dirty_class.private_instance_methods.include?(:"#{p % 'attribute'}")
130
+ end
131
+ end
132
+
133
+ def dirty_class
134
+ @dirty_class ||= Class.new { include ::ActiveModel::Dirty }
135
+ end
136
+
137
+ private
138
+
139
+ def excluded_method_patterns
140
+ ['%s', 'restore_%s!']
141
+ end
142
+ end
143
+ end
144
+
145
+ module InstanceMethods
146
+ def changed_attributes
147
+ super.merge(mutations_from_mobility.changed_attributes)
148
+ end
149
+
150
+ def changes_applied
151
+ super
152
+ mutations_from_mobility.finalize_changes
153
+ end
154
+
155
+ def changes
156
+ super.merge(mutations_from_mobility.changes)
157
+ end
158
+
159
+ def changed
160
+ # uniq is required for Rails < 6.0
161
+ (super + mutations_from_mobility.changed).uniq
162
+ end
163
+
164
+ def changed?
165
+ super || mutations_from_mobility.changed?
166
+ end
167
+
168
+ def previous_changes
169
+ super.merge(mutations_from_mobility.previous_changes)
170
+ end
171
+
172
+ def clear_changes_information
173
+ @mutations_from_mobility = nil
174
+ super
175
+ end
176
+
177
+ def clear_attribute_changes(attr_names)
178
+ attr_names.each { |attr_name| mutations_from_mobility.restore_attribute!(attr_name) }
179
+ super
69
180
  end
70
181
 
71
182
  private
72
183
 
73
- # Get method suffixes. Creating an object just to get the list of
74
- # suffixes is not very efficient, but the most reliable way given that
75
- # they change from Rails version to version.
76
- def method_suffixes
77
- @method_suffixes ||=
78
- Class.new do
79
- include ::ActiveModel::Dirty
80
- end.attribute_method_matchers.map(&:suffix).select { |m| m =~ /\A_/ }
81
- end
82
-
83
- # Tracks which translated attributes have been changed, separate from
84
- # the default tracking of changes in ActiveModel/ActiveRecord Dirty.
85
- # This is required in order for the Mobility ActiveRecord Dirty
86
- # plugin to correctly read the value of locale accessors like
87
- # +title_en+ in dirty tracking.
88
- module ChangedAttributes
89
- private
184
+ def mutations_from_mobility
185
+ @mutations_from_mobility ||= MobilityMutationTracker.new(self)
186
+ end
187
+ end
188
+
189
+ # Give the module builder a name so it's easier to see in the model's ancestors
190
+ class AttributeHandlerMethods < Module; end
191
+
192
+ class MobilityMutationTracker
193
+ OPTION_NOT_GIVEN = Object.new
194
+
195
+ attr_reader :previous_changes
196
+
197
+ def initialize(model)
198
+ @model = model
199
+ @current_changes = {}.with_indifferent_access
200
+ @previous_changes = {}.with_indifferent_access
201
+ end
202
+
203
+ def finalize_changes
204
+ @previous_changes = changes
205
+ @current_changes = {}.with_indifferent_access
206
+ end
207
+
208
+ def changed
209
+ attr_names.select { |attr_name| attribute_changed?(attr_name) }
210
+ end
211
+
212
+ def changed_attributes
213
+ attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
214
+ if attribute_changed?(attr_name)
215
+ result[attr_name] = attribute_was(attr_name)
216
+ end
217
+ end
218
+ end
219
+
220
+ def changes
221
+ attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
222
+ if change = attribute_change(attr_name)
223
+ result.merge!(attr_name => change)
224
+ end
225
+ end
226
+ end
227
+
228
+ def changed?
229
+ attr_names.any? { |attr| attribute_changed?(attr) }
230
+ end
231
+
232
+ def attribute_change(attr_name)
233
+ if attribute_changed?(attr_name)
234
+ [attribute_was(attr_name), fetch_value(attr_name)]
235
+ end
236
+ end
237
+
238
+ def attribute_previous_change(attr_name)
239
+ previous_changes[attr_name]
240
+ end
90
241
 
91
- def mobility_changed_attributes
92
- @mobility_changed_attributes ||= Set.new
242
+ def attribute_previously_was(attr_name)
243
+ if attribute_previously_changed?(attr_name)
244
+ # Calling +first+ here fetches the value before change from the
245
+ # hash.
246
+ previous_changes[attr_name].first
93
247
  end
94
248
  end
249
+
250
+ def attribute_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN)
251
+ current_changes.include?(attr_name) &&
252
+ (OPTION_NOT_GIVEN == from || attribute_was(attr_name) == from) &&
253
+ (OPTION_NOT_GIVEN == to || fetch_value(attr_name) == to)
254
+ end
255
+
256
+ def attribute_previously_changed?(attr_name)
257
+ previous_changes.include?(attr_name)
258
+ end
259
+
260
+ def attribute_was(attr_name)
261
+ if attribute_changed?(attr_name)
262
+ current_changes[attr_name]
263
+ else
264
+ fetch_value(attr_name)
265
+ end
266
+ end
267
+
268
+ def attribute_will_change!(attr_name)
269
+ current_changes[attr_name] = fetch_value(attr_name) unless current_changes.include?(attr_name)
270
+ end
271
+
272
+ def restore_attribute!(attr_name)
273
+ current_changes.delete(attr_name)
274
+ end
275
+
276
+ # These are for ActiveRecord, but we'll define them here.
277
+ alias_method :saved_change_to_attribute?, :attribute_previously_changed?
278
+ alias_method :saved_change_to_attribute, :attribute_previous_change
279
+ alias_method :attribute_before_last_save, :attribute_previously_was
280
+ alias_method :will_save_change_to_attribute?, :attribute_changed?
281
+ alias_method :attribute_change_to_be_saved, :attribute_change
282
+ alias_method :attribute_in_database, :attribute_was
283
+
284
+ private
285
+ attr_reader :model, :current_changes
286
+
287
+ def attr_names
288
+ current_changes.keys
289
+ end
290
+
291
+ def fetch_value(attr_name)
292
+ model.__send__(attr_name)
293
+ end
294
+ end
295
+
296
+ module BackendMethods
297
+ # @!group Backend Accessors
298
+ # @!macro backend_writer
299
+ # @param [Hash] options
300
+ def write(locale, value, options = {})
301
+ locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
302
+ if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
303
+ mutations_from_mobility.restore_attribute!(locale_accessor)
304
+ elsif read(locale, options.merge(locale: true)) != value
305
+ mutations_from_mobility.attribute_will_change!(locale_accessor)
306
+ end
307
+ super
308
+ end
309
+ # @!endgroup
310
+
311
+ private
312
+
313
+ def mutations_from_mobility
314
+ model.send(:mutations_from_mobility)
315
+ end
95
316
  end
96
317
  end
97
318
  end
@@ -12,7 +12,6 @@ details on usage.
12
12
  In addition to methods added by {Mobility::Plugins::ActiveModel::Dirty}, the
13
13
  AR::Dirty plugin adds support for the following persistence-specific methods
14
14
  (for a model with a translated attribute +title+):
15
- - +saved_changes+
16
15
  - +saved_change_to_title?+
17
16
  - +saved_change_to_title+
18
17
  - +title_before_last_save+
@@ -20,128 +19,83 @@ AR::Dirty plugin adds support for the following persistence-specific methods
20
19
  - +title_change_to_be_saved+
21
20
  - +title_in_database+
22
21
 
22
+ The following methods are also patched to include translated attribute changes:
23
+ - +saved_changes+
24
+ - +has_changes_to_save?+
25
+ - +changes_to_save+
26
+ - +changed_attribute_names_to_save+
27
+ - +attributes_in_database+
28
+
29
+ In addition, the following ActiveModel attribute handler methods are also
30
+ patched to work with translated attributes:
31
+ - +saved_change_to_attribute?+
32
+ - +saved_change_to_attribute+
33
+ - +attribute_before_last_save+
34
+ - +will_save_change_to_attribute?+
35
+ - +attribute_change_to_be_saved+
36
+ - +attribute_in_database+
37
+
38
+ (When using these methods, you must pass the attribute name along with its
39
+ locale suffix, so +title_en+, +title_pt_br+, etc.)
40
+
23
41
  =end
24
42
  module Dirty
25
- include ActiveModel::Dirty
26
-
27
- # Builds module which patches a few AR methods to handle changes to
28
- # translated attributes just like normal attributes.
29
43
  class MethodsBuilder < ActiveModel::Dirty::MethodsBuilder
30
- def initialize(*attribute_names)
31
- super
32
- @attribute_names = attribute_names
33
- define_method_overrides if ::ActiveRecord::VERSION::STRING < '5.2'
34
- define_attribute_methods if ::ActiveRecord::VERSION::STRING >= '5.1'
35
- end
36
-
37
- # Overrides +ActiveRecord::AttributeMethods::ClassMethods#has_attribute+ (in AR 5.1) and
38
- # +ActiveModel::AttributeMethods#_read_attribute+ (in AR >= 5.2) to
39
- # ensure that fallthrough attribute methods are treated like "real"
40
- # attribute methods.
41
- #
42
- # @note Patching +has_attribute?+ is necessary in AR 5.1 due to this commit[https://github.com/rails/rails/commit/4fed08fa787a316fa51f14baca9eae11913f5050].
43
44
  # @param [Attributes] attributes
44
45
  def included(model_class)
45
46
  super
46
47
 
47
- if ::ActiveRecord::VERSION::MAJOR == 5 && ::ActiveRecord::VERSION::MINOR == 1
48
- names = @attribute_names
49
- method_name_regex = /\A(#{names.join('|')})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
50
- has_attribute = Module.new do
51
- define_method :has_attribute? do |attr_name|
52
- super(attr_name) || (String === attr_name && !!method_name_regex.match(attr_name))
53
- end
54
- end
55
- model_class.extend has_attribute
56
- elsif ::ActiveRecord::VERSION::STRING >= '5.2'
57
- model_class.include ReadAttribute
58
- end
48
+ model_class.include InstanceMethods
59
49
  end
60
50
 
61
- private
62
-
63
- # @note These method overrides are needed for AR versions < 5.2,
64
- # since AR::Dirty overrides AM::Dirty, disabling previous_changes
65
- # from being set. Here we "undo" that.
66
- def define_method_overrides
67
- changes_applied_method = ::ActiveRecord::VERSION::STRING < '5.1' ? :changes_applied : :changes_internally_applied
68
- define_method changes_applied_method do
69
- @previously_changed = changes
70
- super()
51
+ class << self
52
+ def dirty_class
53
+ @dirty_class ||= (Class.new do
54
+ # In earlier versions of Rails, these are needed to avoid an
55
+ # exception when including the AR Dirty module outside of an
56
+ # AR::Base class. Eventually we should be able to drop them.
57
+ def self.after_create; end
58
+ def self.after_update; end
59
+
60
+ include ::ActiveRecord::AttributeMethods::Dirty
61
+ end)
71
62
  end
63
+ end
64
+ end
72
65
 
73
- define_method :clear_changes_information do
74
- @previously_changed = ActiveSupport::HashWithIndifferentAccess.new
75
- super()
66
+ module InstanceMethods
67
+ if ::ActiveRecord::VERSION::STRING >= '5.1' # define patterns added in 5.1
68
+ def saved_changes
69
+ super.merge(mutations_from_mobility.previous_changes)
76
70
  end
77
71
 
78
- define_method :previous_changes do
79
- (@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super())
72
+ def changes_to_save
73
+ super.merge(mutations_from_mobility.changes)
80
74
  end
81
- end
82
75
 
83
- # For AR >= 5.1 only
84
- def define_attribute_methods
85
- define_method :saved_changes do
86
- (@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super())
76
+ def changed_attribute_names_to_save
77
+ super + mutations_from_mobility.changed
87
78
  end
88
79
 
89
- @attribute_names.each do |name|
90
- define_method :"saved_change_to_#{name}?" do
91
- previous_changes.include?(Mobility.normalize_locale_accessor(name))
92
- end
93
-
94
- define_method :"saved_change_to_#{name}" do
95
- previous_changes[Mobility.normalize_locale_accessor(name)]
96
- end
97
-
98
- define_method :"#{name}_before_last_save" do
99
- previous_changes[Mobility.normalize_locale_accessor(name)].first
100
- end
101
-
102
- alias_method :"will_save_change_to_#{name}?", :"#{name}_changed?"
103
- alias_method :"#{name}_change_to_be_saved", :"#{name}_change"
104
- alias_method :"#{name}_in_database", :"#{name}_was"
80
+ def attributes_in_database
81
+ super.merge(mutations_from_mobility.changed_attributes)
105
82
  end
106
- end
107
83
 
108
- # Overrides _read_attribute to correctly dispatch reads on translated
109
- # attributes to their respective setters, rather than to
110
- # +@attributes+, which would otherwise return +nil+.
111
- #
112
- # For background on why this is necessary, see:
113
- # https://github.com/shioyama/mobility/issues/115
114
- module ReadAttribute
115
- # @note We first check if attributes has the key +attr+ to avoid
116
- # doing any extra work in case this is a "normal"
117
- # (non-translated) attribute.
118
- def _read_attribute(attr, *args)
119
- if @attributes.key?(attr)
120
- super
121
- else
122
- mobility_changed_attributes.include?(attr) ? __send__(attr) : super
84
+ if ::ActiveRecord::VERSION::STRING >= '6.0'
85
+ def has_changes_to_save?
86
+ super || mutations_from_mobility.changed?
123
87
  end
124
88
  end
89
+ end
125
90
 
126
- # @note This is necessary due to a performance fix in e12607
127
- # which skips setting @previously_changed if @attributes is
128
- # defined. For Mobility models using the Dirty plugin, there will
129
- # be cases where @attributes has been set, but there are *other*
130
- # changes on virtual translated attributes which need to also be
131
- # assigned. In this case, we use the presence of such changed
132
- # virtual attributes as an alternative trigger to set this variable.
133
- #
134
- # See:
135
- # - https://github.com/rails/rails/commit/e126078a0e013acfe0a397a8dad33b2c9de78732
136
- # - https://github.com/shioyama/mobility/pull/166
137
- def changes_applied
138
- if defined?(@attributes) && mobility_changed_attributes.any?
139
- @previously_changed = changes
140
- end
141
- super
91
+ def reload(*)
92
+ super.tap do
93
+ @mutations_from_mobility = nil
142
94
  end
143
95
  end
144
96
  end
97
+
98
+ BackendMethods = ActiveModel::Dirty::BackendMethods
145
99
  end
146
100
  end
147
101
  end
@@ -50,7 +50,7 @@ details.
50
50
  else
51
51
  raise ArgumentError, "#{model_class} does not support Dirty module."
52
52
  end
53
- backend_class.include dirty_module
53
+ backend_class.include dirty_module.const_get(:BackendMethods)
54
54
  model_class.include dirty_module.const_get(:MethodsBuilder).new(*attribute_names)
55
55
  end
56
56
  end
@@ -13,21 +13,6 @@ Automatically includes dirty plugin in model class when enabled.
13
13
  =end
14
14
  module Sequel
15
15
  module Dirty
16
- # @!group Backend Accessors
17
- # @!macro backend_writer
18
- # @param [Hash] options
19
- def write(locale, value, options = {})
20
- locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym
21
- if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value
22
- super
23
- [model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) }
24
- elsif read(locale, options.merge(fallback: false)) != value
25
- model.will_change_column(locale_accessor)
26
- super
27
- end
28
- end
29
- # @!endgroup
30
-
31
16
  # Builds module which overrides dirty methods to handle translated as
32
17
  # well as normal (untranslated) attributes.
33
18
  class MethodsBuilder < Module
@@ -53,6 +38,23 @@ Automatically includes dirty plugin in model class when enabled.
53
38
  model_class.plugin :dirty
54
39
  end
55
40
  end
41
+
42
+ module BackendMethods
43
+ # @!group Backend Accessors
44
+ # @!macro backend_writer
45
+ # @param [Hash] options
46
+ def write(locale, value, options = {})
47
+ locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym
48
+ if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value
49
+ super
50
+ [model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) }
51
+ elsif read(locale, options.merge(fallback: false)) != value
52
+ model.will_change_column(locale_accessor)
53
+ super
54
+ end
55
+ end
56
+ # @!endgroup
57
+ end
56
58
  end
57
59
  end
58
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mobility
4
- VERSION = "0.8.8"
4
+ VERSION = "0.8.9"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobility
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.8
4
+ version: 0.8.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Salzberg
@@ -35,7 +35,7 @@ cert_chain:
35
35
  cbyauX5dx2EyKhuidQ7l3jDOcpFUDWeaqqZllz/0i2LFBILAlYRy82zaspW5k6g3
36
36
  YL4OF4e7t6EeQyBoILL36f8LpD9odUTRdNruhmuEtoQ+kchZ
37
37
  -----END CERTIFICATE-----
38
- date: 2019-09-17 00:00:00.000000000 Z
38
+ date: 2019-10-25 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: request_store
metadata.gz.sig CHANGED
Binary file