diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2012-05-30 23:18:08 -0700 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2012-05-30 23:21:57 -0700 |
commit | d5354af1149496e1a6ebccc5434dbba3bde86265 (patch) | |
tree | 0bd3a964279fcfd2f4be4225637e76b1efc1907e /activerecord | |
parent | 9a30d82d455a5b8578f7dfe6f5f9479fca44c78f (diff) | |
download | rails-d5354af1149496e1a6ebccc5434dbba3bde86265.tar.gz rails-d5354af1149496e1a6ebccc5434dbba3bde86265.tar.bz2 rails-d5354af1149496e1a6ebccc5434dbba3bde86265.zip |
Fix backward compatibility with stored Hash values. Wrap coders to convert serialized values to indifferent access.
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/store.rb | 34 | ||||
-rw-r--r-- | activerecord/test/cases/store_test.rb | 29 | ||||
-rw-r--r-- | activerecord/test/fixtures/admin/users.yml | 3 |
3 files changed, 51 insertions, 15 deletions
diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index fdd82b489a..d70e02e379 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -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 diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index 3a5d84df9f..79476ed2a4 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -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 diff --git a/activerecord/test/fixtures/admin/users.yml b/activerecord/test/fixtures/admin/users.yml index 6f11f2509e..e2884beda5 100644 --- a/activerecord/test/fixtures/admin/users.yml +++ b/activerecord/test/fixtures/admin/users.yml @@ -5,3 +5,6 @@ david: jamis: name: Jamis account: signals37 + settings: + :symbol: symbol + string: string |