1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Detect in-place modifications on Strings

This commit is contained in:
Sean Griffin 2014-06-17 18:51:38 -06:00
parent bdc39899eb
commit c7802dccba
4 changed files with 55 additions and 13 deletions

View file

@ -9,13 +9,28 @@ module ActiveRecord
true
end
def changed_in_place?(raw_old_value, new_value)
if new_value.is_a?(::String)
raw_old_value != new_value
end
end
def type_cast_for_database(value)
if value.is_a?(::String)
::String.new(value)
else
super
end
end
private
def cast_value(value)
case value
when true then "1"
when false then "0"
else value.to_s
# String.new is slightly faster than dup
else ::String.new(value.to_s)
end
end
end

View file

@ -309,16 +309,14 @@ class DirtyTest < ActiveRecord::TestCase
def test_attribute_will_change!
pirate = Pirate.create!(:catchphrase => 'arr')
pirate.catchphrase << ' matey'
assert !pirate.catchphrase_changed?
assert pirate.catchphrase_will_change!
assert pirate.catchphrase_changed?
assert_equal ['arr matey', 'arr matey'], pirate.catchphrase_change
assert_equal ['arr', 'arr'], pirate.catchphrase_change
pirate.catchphrase << '!'
pirate.catchphrase << ' matey!'
assert pirate.catchphrase_changed?
assert_equal ['arr matey', 'arr matey!'], pirate.catchphrase_change
assert_equal ['arr', 'arr matey!'], pirate.catchphrase_change
end
def test_association_assignment_changes_foreign_key

View file

@ -0,0 +1,36 @@
require 'cases/helper'
module ActiveRecord
class StringTypeTest < ActiveRecord::TestCase
test "type casting" do
type = Type::String.new
assert_equal "1", type.type_cast_from_user(true)
assert_equal "0", type.type_cast_from_user(false)
assert_equal "123", type.type_cast_from_user(123)
end
test "values are duped coming out" do
s = "foo"
type = Type::String.new
assert_not_same s, type.type_cast_from_user(s)
assert_not_same s, type.type_cast_from_database(s)
end
test "string mutations are detected" do
klass = Class.new(Base)
klass.table_name = 'authors'
author = klass.create!(name: 'Sean')
assert_not author.changed?
author.name << ' Griffin'
assert author.name_changed?
author.save!
author.reload
assert_equal 'Sean Griffin', author.name
assert_not author.changed?
end
end
end

View file

@ -35,13 +35,6 @@ module ActiveRecord
assert_equal false, type.type_cast_from_user('SOMETHING RANDOM')
end
def test_type_cast_string
type = Type::String.new
assert_equal "1", type.type_cast_from_user(true)
assert_equal "0", type.type_cast_from_user(false)
assert_equal "123", type.type_cast_from_user(123)
end
def test_type_cast_integer
type = Type::Integer.new
assert_equal 1, type.type_cast_from_user(1)