@@ -47,23 +47,56 @@ module ActiveResource
4747 #
4848 # coder = ActiveResource::Coder.new(Person) { |person| person.serializable_hash }
4949 # coder.dump(person) # => { "name" => "Matz" }
50+ #
51+ # === Collections
52+ #
53+ # To encode ActiveResource::Collection instances, construct an instance with +collection:
54+ # true+.
55+ #
56+ # class Team < ActiveRecord::Base
57+ # serialize :people, coder: ActiveResource::Coder.new(Person, collection: true)
58+ # end
59+ #
60+ # team = Team.new
61+ # team.people = Person.all
62+ # team.people.map(&:attributes) # => [{ "id" => 1, "name" => "Matz" }]
63+ #
64+ # By default, <tt>#dump</tt> serializes the instance to a string value by
65+ # calling Collection#encode:
66+ #
67+ # team.people_before_type_cast # => "[{\"id\":1,\"name\":\"Matz\"}]"
68+ #
69+ # To customize serialization, pass a block that accepts the collection as the second argument:
70+ #
71+ # people = Person.all
72+ #
73+ # coder = ActiveResource::Coder.new(Person) { |collection| collection.original_parsed }
74+ # coder.dump(people) # => [{ "id" => 1, "name" => "Matz" }]
5075 class Coder
51- attr_accessor :resource_class , :encoder
76+ attr_accessor :resource_class , :encoder , :collection
5277
5378 # ==== Arguments
5479 # * <tt>resource_class</tt> Active Resource class that to be coded
5580 # * <tt>encoder_method</tt> the method to invoke on the instance to encode
5681 # it. Defaults to ActiveResource::Base#encode.
57- def initialize ( resource_class , encoder_method = :encode , &block )
82+ #
83+ # ==== Options
84+ #
85+ # * <tt>:collection</tt> - Whether or not the values represent an
86+ # ActiveResource::Collection Defaults to false.
87+ def initialize ( resource_class , encoder_method = :encode , collection : false , &block )
5888 @resource_class = resource_class
5989 @encoder = block || encoder_method
90+ @collection = collection
6091 end
6192
6293 # Serializes a resource value to a value that will be stored in the database.
6394 # Returns nil when passed nil
6495 def dump ( value )
6596 return if value . nil?
66- raise ArgumentError . new ( "expected value to be #{ resource_class } , but was #{ value . class } " ) unless value . is_a? ( resource_class )
97+
98+ expected_class = collection ? resource_class . collection_parser : resource_class
99+ raise ArgumentError . new ( "expected value to be #{ expected_class } , but was #{ value . class } " ) unless value . is_a? ( expected_class )
67100
68101 value . yield_self ( &encoder )
69102 end
@@ -73,10 +106,15 @@ def dump(value)
73106 def load ( value )
74107 return if value . nil?
75108 value = resource_class . format . decode ( value ) if value . is_a? ( String )
76- raise ArgumentError . new ( "expected value to be Hash, but was #{ value . class } " ) unless value . is_a? ( Hash )
77- value = Formats . remove_root ( value ) if value . keys . first . to_s == resource_class . element_name
78109
79- resource_class . new ( value , value [ resource_class . primary_key ] )
110+ if collection
111+ raise ArgumentError . new ( "expected value to be Hash or Array, but was #{ value . class } " ) unless value . is_a? ( Hash ) || value . is_a? ( Array )
112+ resource_class . instantiate_collection ( value )
113+ else
114+ raise ArgumentError . new ( "expected value to be Hash, but was #{ value . class } " ) unless value . is_a? ( Hash )
115+ value = Formats . remove_root ( value ) if value . keys . first . to_s == resource_class . element_name
116+ resource_class . new ( value , value [ resource_class . primary_key ] )
117+ end
80118 end
81119 end
82120end
0 commit comments