mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fix backward compatibility with stored Hash values. Wrap coders to convert serialized values to indifferent access.
This commit is contained in:
parent
9a30d82d45
commit
d5354af114
3 changed files with 51 additions and 15 deletions
|
@ -38,7 +38,7 @@ module ActiveRecord
|
|||
|
||||
module ClassMethods
|
||||
def store(store_attribute, options = {})
|
||||
serialize store_attribute, options.fetch(:coder, ActiveSupport::HashWithIndifferentAccess)
|
||||
serialize store_attribute, IndifferentCoder.new(options[:coder])
|
||||
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
|
||||
end
|
||||
|
||||
|
@ -47,7 +47,7 @@ module ActiveRecord
|
|||
define_method("#{key}=") do |value|
|
||||
initialize_store_attribute(store_attribute)
|
||||
send(store_attribute)[key] = value
|
||||
send("#{store_attribute}_will_change!")
|
||||
send :"#{store_attribute}_will_change!"
|
||||
end
|
||||
|
||||
define_method(key) do
|
||||
|
@ -71,5 +71,35 @@ module ActiveRecord
|
|||
send :"#{store_attribute}=", ActiveSupport::HashWithIndifferentAccess.new
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentCoder
|
||||
def initialize(coder_or_class_name)
|
||||
@coder =
|
||||
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
|
||||
coder_or_class_name
|
||||
else
|
||||
ActiveRecord::Coders::YAMLColumn.new(coder_or_class_name || Object)
|
||||
end
|
||||
end
|
||||
|
||||
def dump(obj)
|
||||
@coder.dump self.class.as_indifferent_hash(obj)
|
||||
end
|
||||
|
||||
def load(yaml)
|
||||
self.class.as_indifferent_hash @coder.load(yaml)
|
||||
end
|
||||
|
||||
def self.as_indifferent_hash(obj)
|
||||
case obj
|
||||
when ActiveSupport::HashWithIndifferentAccess
|
||||
obj
|
||||
when Hash
|
||||
obj.with_indifferent_access
|
||||
else
|
||||
HashWithIndifferentAccess.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,10 @@ require 'models/admin'
|
|||
require 'models/admin/user'
|
||||
|
||||
class StoreTest < ActiveRecord::TestCase
|
||||
fixtures :'admin/users'
|
||||
|
||||
setup do
|
||||
@john = Admin::User.create(:name => 'John Doe', :color => 'black', :remember_login => true, :height => 'tall', :is_a_good_guy => true)
|
||||
@john = Admin::User.create!(:name => 'John Doe', :color => 'black', :remember_login => true, :height => 'tall', :is_a_good_guy => true)
|
||||
end
|
||||
|
||||
test "reading store attributes through accessors" do
|
||||
|
@ -52,18 +54,19 @@ class StoreTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
test "convert store attributes from Hash to HashWithIndifferentAccess saving the data and access attributes indifferently" do
|
||||
@john.json_data = { :height => 'tall', 'weight' => 'heavy' }
|
||||
assert_equal true, @john.json_data.instance_of?(Hash)
|
||||
assert_equal 'tall', @john.json_data[:height]
|
||||
assert_equal nil, @john.json_data['height']
|
||||
assert_equal nil, @john.json_data[:weight]
|
||||
assert_equal 'heavy', @john.json_data['weight']
|
||||
@john.height = 'low'
|
||||
assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess)
|
||||
assert_equal 'low', @john.json_data[:height]
|
||||
assert_equal 'low', @john.json_data['height']
|
||||
assert_equal 'heavy', @john.json_data[:weight]
|
||||
assert_equal 'heavy', @john.json_data['weight']
|
||||
user = Admin::User.find_by_name('Jamis')
|
||||
assert_equal 'symbol', user.settings[:symbol]
|
||||
assert_equal 'symbol', user.settings['symbol']
|
||||
assert_equal 'string', user.settings[:string]
|
||||
assert_equal 'string', user.settings['string']
|
||||
assert_equal true, user.settings.instance_of?(ActiveSupport::HashWithIndifferentAccess)
|
||||
|
||||
user.height = 'low'
|
||||
assert_equal 'symbol', user.settings[:symbol]
|
||||
assert_equal 'symbol', user.settings['symbol']
|
||||
assert_equal 'string', user.settings[:string]
|
||||
assert_equal 'string', user.settings['string']
|
||||
assert_equal true, user.settings.instance_of?(ActiveSupport::HashWithIndifferentAccess)
|
||||
end
|
||||
|
||||
test "convert store attributes from any format other than Hash or HashWithIndifferent access losing the data" do
|
||||
|
|
3
activerecord/test/fixtures/admin/users.yml
vendored
3
activerecord/test/fixtures/admin/users.yml
vendored
|
@ -5,3 +5,6 @@ david:
|
|||
jamis:
|
||||
name: Jamis
|
||||
account: signals37
|
||||
settings:
|
||||
:symbol: symbol
|
||||
string: string
|
||||
|
|
Loading…
Reference in a new issue