mobility 0.8.8 → 0.8.9

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 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