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
|
module ClassMethods
|
||||||
def store(store_attribute, options = {})
|
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
|
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ module ActiveRecord
|
||||||
define_method("#{key}=") do |value|
|
define_method("#{key}=") do |value|
|
||||||
initialize_store_attribute(store_attribute)
|
initialize_store_attribute(store_attribute)
|
||||||
send(store_attribute)[key] = value
|
send(store_attribute)[key] = value
|
||||||
send("#{store_attribute}_will_change!")
|
send :"#{store_attribute}_will_change!"
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method(key) do
|
define_method(key) do
|
||||||
|
@ -71,5 +71,35 @@ module ActiveRecord
|
||||||
send :"#{store_attribute}=", ActiveSupport::HashWithIndifferentAccess.new
|
send :"#{store_attribute}=", ActiveSupport::HashWithIndifferentAccess.new
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,10 @@ require 'models/admin'
|
||||||
require 'models/admin/user'
|
require 'models/admin/user'
|
||||||
|
|
||||||
class StoreTest < ActiveRecord::TestCase
|
class StoreTest < ActiveRecord::TestCase
|
||||||
|
fixtures :'admin/users'
|
||||||
|
|
||||||
setup do
|
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
|
end
|
||||||
|
|
||||||
test "reading store attributes through accessors" do
|
test "reading store attributes through accessors" do
|
||||||
|
@ -52,18 +54,19 @@ class StoreTest < ActiveRecord::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
test "convert store attributes from Hash to HashWithIndifferentAccess saving the data and access attributes indifferently" do
|
test "convert store attributes from Hash to HashWithIndifferentAccess saving the data and access attributes indifferently" do
|
||||||
@john.json_data = { :height => 'tall', 'weight' => 'heavy' }
|
user = Admin::User.find_by_name('Jamis')
|
||||||
assert_equal true, @john.json_data.instance_of?(Hash)
|
assert_equal 'symbol', user.settings[:symbol]
|
||||||
assert_equal 'tall', @john.json_data[:height]
|
assert_equal 'symbol', user.settings['symbol']
|
||||||
assert_equal nil, @john.json_data['height']
|
assert_equal 'string', user.settings[:string]
|
||||||
assert_equal nil, @john.json_data[:weight]
|
assert_equal 'string', user.settings['string']
|
||||||
assert_equal 'heavy', @john.json_data['weight']
|
assert_equal true, user.settings.instance_of?(ActiveSupport::HashWithIndifferentAccess)
|
||||||
@john.height = 'low'
|
|
||||||
assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess)
|
user.height = 'low'
|
||||||
assert_equal 'low', @john.json_data[:height]
|
assert_equal 'symbol', user.settings[:symbol]
|
||||||
assert_equal 'low', @john.json_data['height']
|
assert_equal 'symbol', user.settings['symbol']
|
||||||
assert_equal 'heavy', @john.json_data[:weight]
|
assert_equal 'string', user.settings[:string]
|
||||||
assert_equal 'heavy', @john.json_data['weight']
|
assert_equal 'string', user.settings['string']
|
||||||
|
assert_equal true, user.settings.instance_of?(ActiveSupport::HashWithIndifferentAccess)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "convert store attributes from any format other than Hash or HashWithIndifferent access losing the data" do
|
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:
|
jamis:
|
||||||
name: Jamis
|
name: Jamis
|
||||||
account: signals37
|
account: signals37
|
||||||
|
settings:
|
||||||
|
:symbol: symbol
|
||||||
|
string: string
|
||||||
|
|
Loading…
Reference in a new issue