Class: Mobility::Plugins::ActiveModel::Dirty::MobilityMutationTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/mobility/plugins/active_model/dirty.rb

Overview

Note:

Seriously, I really don’t want to reproduce all of ActiveModel::Dirty here, but having fought with upstream changes many many times I finally decided it’s more future-proof to just re-implement the stuff we need here, to avoid weird breakage.

Although this is somewhat ugly, at least it’s explicit and since it’s self-defined (rather than hooking into fickle private methods in Rails), it won’t break all of a sudden. We just need to ensure that specs are up-to-date with the latest weird dirty method pattern Rails has decided to support.

Constant Summary collapse

OPTION_NOT_GIVEN =
Object.new

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ MobilityMutationTracker

Returns a new instance of MobilityMutationTracker.



250
251
252
253
254
# File 'lib/mobility/plugins/active_model/dirty.rb', line 250

def initialize(model)
  @model = model
  @current_changes = {}.with_indifferent_access
  @previous_changes = {}.with_indifferent_access
end

Instance Attribute Details

#previous_changesObject (readonly)

Returns the value of attribute previous_changes.



248
249
250
# File 'lib/mobility/plugins/active_model/dirty.rb', line 248

def previous_changes
  @previous_changes
end

Instance Method Details

#attribute_change(attr_name) ⇒ Object Also known as: attribute_change_to_be_saved



285
286
287
288
289
# File 'lib/mobility/plugins/active_model/dirty.rb', line 285

def attribute_change(attr_name)
  if attribute_changed?(attr_name)
    [attribute_was(attr_name), fetch_value(attr_name)]
  end
end

#attribute_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN) ⇒ Boolean Also known as: will_save_change_to_attribute?

Returns:

  • (Boolean)


303
304
305
306
307
# File 'lib/mobility/plugins/active_model/dirty.rb', line 303

def attribute_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN)
  current_changes.include?(attr_name) &&
    (OPTION_NOT_GIVEN == from || attribute_was(attr_name) == from) &&
    (OPTION_NOT_GIVEN == to || fetch_value(attr_name) == to)
end

#attribute_previous_change(attr_name) ⇒ Object Also known as: saved_change_to_attribute



291
292
293
# File 'lib/mobility/plugins/active_model/dirty.rb', line 291

def attribute_previous_change(attr_name)
  previous_changes[attr_name]
end

#attribute_previously_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN) ⇒ Boolean Also known as: saved_change_to_attribute?

Returns:

  • (Boolean)


309
310
311
312
313
# File 'lib/mobility/plugins/active_model/dirty.rb', line 309

def attribute_previously_changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN)
  previous_changes.include?(attr_name) &&
    (OPTION_NOT_GIVEN == from || attribute_previous_change(attr_name).first == from) &&
    (OPTION_NOT_GIVEN == to || attribute_previous_change(attr_name).second == to)
end

#attribute_previously_was(attr_name) ⇒ Object Also known as: attribute_before_last_save



295
296
297
298
299
300
301
# File 'lib/mobility/plugins/active_model/dirty.rb', line 295

def attribute_previously_was(attr_name)
  if attribute_previously_changed?(attr_name)
    # Calling +first+ here fetches the value before change from the
    # hash.
    previous_changes[attr_name].first
  end
end

#attribute_was(attr_name) ⇒ Object Also known as: attribute_in_database



315
316
317
318
319
320
321
# File 'lib/mobility/plugins/active_model/dirty.rb', line 315

def attribute_was(attr_name)
  if attribute_changed?(attr_name)
    current_changes[attr_name]
  else
    fetch_value(attr_name)
  end
end

#attribute_will_change!(attr_name) ⇒ Object



323
324
325
# File 'lib/mobility/plugins/active_model/dirty.rb', line 323

def attribute_will_change!(attr_name)
  current_changes[attr_name] = fetch_value(attr_name) unless current_changes.include?(attr_name)
end

#changedObject



261
262
263
# File 'lib/mobility/plugins/active_model/dirty.rb', line 261

def changed
  attr_names.select { |attr_name| attribute_changed?(attr_name) }
end

#changed?Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/mobility/plugins/active_model/dirty.rb', line 281

def changed?
  attr_names.any? { |attr| attribute_changed?(attr) }
end

#changed_attributesObject



265
266
267
268
269
270
271
# File 'lib/mobility/plugins/active_model/dirty.rb', line 265

def changed_attributes
  attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
    if attribute_changed?(attr_name)
      result[attr_name] = attribute_was(attr_name)
    end
  end
end

#changesObject



273
274
275
276
277
278
279
# File 'lib/mobility/plugins/active_model/dirty.rb', line 273

def changes
  attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
    if change = attribute_change(attr_name)
      result.merge!(attr_name => change)
    end
  end
end

#finalize_changesObject



256
257
258
259
# File 'lib/mobility/plugins/active_model/dirty.rb', line 256

def finalize_changes
  @previous_changes = changes
  @current_changes = {}.with_indifferent_access
end

#restore_attribute!(attr_name) ⇒ Object



327
328
329
# File 'lib/mobility/plugins/active_model/dirty.rb', line 327

def restore_attribute!(attr_name)
  current_changes.delete(attr_name)
end