diff options
| -rw-r--r-- | activerecord/lib/active_record.rb | 4 | ||||
| -rw-r--r-- | activerecord/lib/active_record/coders/yaml_column.rb | 34 | ||||
| -rw-r--r-- | activerecord/test/cases/coders/yaml_column_test.rb | 45 | 
3 files changed, 83 insertions, 0 deletions
| diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index c80bce2849..5afb97803e 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -81,6 +81,10 @@ module ActiveRecord      autoload :Validations    end +  module Coders +    autoload :YAMLColumn, 'active_record/coders/yaml_column' +  end +    module AttributeMethods      extend ActiveSupport::Autoload diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb new file mode 100644 index 0000000000..9b0df119ef --- /dev/null +++ b/activerecord/lib/active_record/coders/yaml_column.rb @@ -0,0 +1,34 @@ +module ActiveRecord +  # :stopdoc: +  module Coders +    class YAMLColumn +      RESCUE_ERRORS = [ ArgumentError ] + +      if defined?(Psych) && defined?(Psych::SyntaxError) +        RESCUE_ERRORS << Psych::SyntaxError +      end + +      attr_accessor :object_class + +      def initialize(object_class = Object) +        @object_class = object_class +      end + +      def load(yaml) +        return yaml unless yaml.is_a?(String) && yaml =~ /^---/ +        begin +          obj = YAML::load(yaml) + +          unless obj.is_a?(object_class) || obj.nil? +            raise SerializationTypeMismatch, +              "Attribute was supposed to be a #{object_class}, but was a #{obj.class}" +          end + +        rescue *RESCUE_ERRORS +          yaml +        end +      end +    end +  end +  # :startdoc +end diff --git a/activerecord/test/cases/coders/yaml_column_test.rb b/activerecord/test/cases/coders/yaml_column_test.rb new file mode 100644 index 0000000000..f85f11b57f --- /dev/null +++ b/activerecord/test/cases/coders/yaml_column_test.rb @@ -0,0 +1,45 @@ +require "cases/helper" + +module ActiveRecord +  module Coders +    class YAMLColumnTest < ActiveRecord::TestCase +      def test_initialize_takes_class +        coder = YAMLColumn.new(Object) +        assert_equal Object, coder.object_class +      end + +      def test_type_mismatch_on_different_classes +        coder = YAMLColumn.new(Array) +        assert_raises(SerializationTypeMismatch) do +          coder.load "--- foo" +        end +      end + +      def test_nil_is_ok +        coder = YAMLColumn.new +        assert_nil coder.load "--- " +      end + +      def test_nil_is_ok_with_different_class +        coder = YAMLColumn.new SerializationTypeMismatch +        assert_nil coder.load "--- " +      end + +      def test_returns_string_unless_starts_with_dash +        coder = YAMLColumn.new +        assert_equal 'foo', coder.load("foo") +      end + +      def test_load_handles_other_classes +        coder = YAMLColumn.new +        assert_equal [], coder.load([]) +      end + +      def test_load_swallows_yaml_exceptions +        coder = YAMLColumn.new +        bad_yaml = '--- {' +        assert_equal bad_yaml, coder.load(bad_yaml) +      end +    end +  end +end | 
