diff options
author | Sean Griffin <sean@seantheprogrammer.com> | 2015-09-24 11:50:11 -0600 |
---|---|---|
committer | Sean Griffin <sean@seantheprogrammer.com> | 2015-09-24 14:06:59 -0600 |
commit | 8e633e505880755e7e366ccec2210bbe2b5436e7 (patch) | |
tree | 3df446051d47c42cd6081a1449a27d57f9179f88 /activerecord/test/cases | |
parent | adfb823af52d368fa4d88731a9809a314ad884ad (diff) | |
download | rails-8e633e505880755e7e366ccec2210bbe2b5436e7.tar.gz rails-8e633e505880755e7e366ccec2210bbe2b5436e7.tar.bz2 rails-8e633e505880755e7e366ccec2210bbe2b5436e7.zip |
Clean up the implementation of AR::Dirty
This moves a bit more of the logic required for dirty checking into the
attribute objects. I had hoped to remove the `with_value_from_database`
stuff, but unfortunately just calling `dup` on the attribute objects
isn't enough, since the values might contain deeply nested data
structures. I think this can be cleaned up further.
This makes most dirty checking become lazy, and reduces the number of
object allocations and amount of CPU time when assigning a value. This
opens the door (but doesn't quite finish) to improving the performance
of writes to a place comparable to 4.1
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/attribute_set_test.rb | 14 | ||||
-rw-r--r-- | activerecord/test/cases/attribute_test.rb | 19 |
2 files changed, 33 insertions, 0 deletions
diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb index 9d927481ec..7524243270 100644 --- a/activerecord/test/cases/attribute_set_test.rb +++ b/activerecord/test/cases/attribute_set_test.rb @@ -160,6 +160,9 @@ module ActiveRecord return if value.nil? value + " from database" end + + def assert_valid_value(*) + end end test "write_from_database sets the attribute with database typecasting" do @@ -207,5 +210,16 @@ module ActiveRecord assert_equal [:foo], attributes.accessed end + + test "#map returns a new attribute set with the changes applied" do + builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new) + attributes = builder.build_from_database(foo: "1", bar: "2") + new_attributes = attributes.map do |attr| + attr.with_cast_value(attr.value + 1) + end + + assert_equal 2, new_attributes.fetch_value(:foo) + assert_equal 3, new_attributes.fetch_value(:bar) + end end end diff --git a/activerecord/test/cases/attribute_test.rb b/activerecord/test/cases/attribute_test.rb index c69782d93f..0f216b7a13 100644 --- a/activerecord/test/cases/attribute_test.rb +++ b/activerecord/test/cases/attribute_test.rb @@ -107,6 +107,9 @@ module ActiveRecord def deserialize(value) value + " from database" end + + def assert_valid_value(*) + end end test "with_value_from_user returns a new attribute with the value from the user" do @@ -186,5 +189,21 @@ module ActiveRecord assert_not attribute.changed_in_place_from?("bar") end + + test "with_value_from_user validates the value" do + type = Type::Value.new + type.define_singleton_method(:assert_valid_value) do |value| + if value == 1 + raise ArgumentError + end + end + + attribute = Attribute.from_database(:foo, 1, type) + assert_equal 1, attribute.value + assert_equal 2, attribute.with_value_from_user(2).value + assert_raises ArgumentError do + attribute.with_value_from_user(1) + end + end end end |