提交 b5eb3215 编写于 作者: B bogdanvlviv

Fix inconsistency with changed attributes when overriding AR attribute reader

上级 2b4583f2
...@@ -179,13 +179,13 @@ def changed_attributes ...@@ -179,13 +179,13 @@ def changed_attributes
# Handles <tt>*_changed?</tt> for +method_missing+. # Handles <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN) # :nodoc: def attribute_changed?(attr, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN) # :nodoc:
!!changes_include?(attr) && !!changes_include?(attr) &&
(to == OPTION_NOT_GIVEN || to == __send__(attr)) && (to == OPTION_NOT_GIVEN || to == _attributes(attr)) &&
(from == OPTION_NOT_GIVEN || from == changed_attributes[attr]) (from == OPTION_NOT_GIVEN || from == changed_attributes[attr])
end end
# Handles <tt>*_was</tt> for +method_missing+. # Handles <tt>*_was</tt> for +method_missing+.
def attribute_was(attr) # :nodoc: def attribute_was(attr) # :nodoc:
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) attribute_changed?(attr) ? changed_attributes[attr] : _attributes(attr)
end end
# Handles <tt>*_previously_changed?</tt> for +method_missing+. # Handles <tt>*_previously_changed?</tt> for +method_missing+.
...@@ -226,7 +226,7 @@ def clear_changes_information # :doc: ...@@ -226,7 +226,7 @@ def clear_changes_information # :doc:
# Handles <tt>*_change</tt> for +method_missing+. # Handles <tt>*_change</tt> for +method_missing+.
def attribute_change(attr) def attribute_change(attr)
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr) [changed_attributes[attr], _attributes(attr)] if attribute_changed?(attr)
end end
# Handles <tt>*_previous_change</tt> for +method_missing+. # Handles <tt>*_previous_change</tt> for +method_missing+.
...@@ -239,7 +239,7 @@ def attribute_will_change!(attr) ...@@ -239,7 +239,7 @@ def attribute_will_change!(attr)
return if attribute_changed?(attr) return if attribute_changed?(attr)
begin begin
value = __send__(attr) value = _attributes(attr)
value = value.duplicable? ? value.clone : value value = value.duplicable? ? value.clone : value
rescue TypeError, NoMethodError rescue TypeError, NoMethodError
end end
...@@ -268,5 +268,9 @@ def set_attribute_was(attr, old_value) ...@@ -268,5 +268,9 @@ def set_attribute_was(attr, old_value)
def clear_attribute_changes(attributes) # :doc: def clear_attribute_changes(attributes) # :doc:
attributes_changed_by_setter.except!(*attributes) attributes_changed_by_setter.except!(*attributes)
end end
def _attributes(attr)
__send__(attr)
end
end end
end end
* Fix inconsistency with changed attributes when overriding AR attribute reader.
*bogdanvlviv*
* When calling the dynamic fixture accessor method with no arguments it now returns all fixtures of this type. * When calling the dynamic fixture accessor method with no arguments it now returns all fixtures of this type.
Previously this method always returned an empty array. Previously this method always returned an empty array.
......
...@@ -328,6 +328,10 @@ def cache_changed_attributes ...@@ -328,6 +328,10 @@ def cache_changed_attributes
def clear_changed_attributes_cache def clear_changed_attributes_cache
remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes) remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
end end
def _attributes(attr)
_read_attribute(attr)
end
end end
end end
end end
...@@ -671,6 +671,25 @@ def test_datetime_attribute_doesnt_change_if_zone_is_modified_in_string ...@@ -671,6 +671,25 @@ def test_datetime_attribute_doesnt_change_if_zone_is_modified_in_string
assert binary.changed? assert binary.changed?
end end
test "changes is correct if override attribute reader" do
pirate = Pirate.create!(catchphrase: "arrrr")
def pirate.catchphrase
super.upcase
end
new_catchphrase = "arrrr matey!"
pirate.catchphrase = new_catchphrase
assert pirate.catchphrase_changed?
expected_changes = {
"catchphrase" => ["arrrr", new_catchphrase]
}
assert_equal new_catchphrase.upcase, pirate.catchphrase
assert_equal expected_changes, pirate.changes
end
test "attribute_changed? doesn't compute in-place changes for unrelated attributes" do test "attribute_changed? doesn't compute in-place changes for unrelated attributes" do
test_type_class = Class.new(ActiveRecord::Type::Value) do test_type_class = Class.new(ActiveRecord::Type::Value) do
define_method(:changed_in_place?) do |*| define_method(:changed_in_place?) do |*|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册