representable 0.0.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ h2. 0.9.0
2
+
3
+ h3. Changes
4
+ * Removed the :tag option in favor of :from. The Definition#from method is now authorative for all name mappings.
5
+ * Removed the active_support and i18n dependency.
@@ -29,7 +29,7 @@ Now, parsing manually starts simple but gets complex soon. In the end, you have
29
29
  include Representable::XML
30
30
 
31
31
  representable_property :id
32
- representable_collection :items, :tag => :item, :as => Item
32
+ representable_collection :items, :from => :item, :as => Item
33
33
  end
34
34
 
35
35
  class Item
@@ -73,6 +73,12 @@ You can also render a representation from a newly created object.
73
73
 
74
74
  Representable makes working with representations extremely easy and testable.
75
75
 
76
+
77
+ == Serialization Backends
78
+
79
+ This gem ships with JSON and XML support, meaning you can parse and render both media formats.
80
+
81
+
76
82
  == More
77
83
 
78
84
  Representable was written with REST representations in mind. However, it is a generic module for working with documents. If you do consider using it for a REST project, check out the {Roar framework}[http://github.com/apotonick/roar], which comes with representers, built-in hypermedia support and more. It internally uses Representable and streamlines the process for building hypermedia-driven REST applications.
data/Rakefile CHANGED
@@ -3,6 +3,9 @@ Bundler::GemHelper.install_tasks
3
3
 
4
4
  require 'rake/testtask'
5
5
 
6
+ desc 'Test the representable gem.'
7
+ task :default => :test
8
+
6
9
  Rake::TestTask.new(:test) do |test|
7
10
  test.libs << 'test'
8
11
  test.test_files = FileList['test/*_test.rb']
@@ -1,15 +1,8 @@
1
- require 'active_support'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/string/inflections.rb'
4
- require 'active_support/core_ext/hash/reverse_merge.rb'
5
-
6
1
  require 'hooks/inheritable_attribute'
7
2
 
8
-
9
3
  require 'representable/definition'
10
4
  require 'representable/nokogiri_extensions'
11
5
 
12
- #require 'representable/xml' # TODO: do that dynamically.
13
6
 
14
7
  module Representable
15
8
  def self.included(base)
@@ -226,7 +219,10 @@ module Representable
226
219
  end
227
220
 
228
221
  def representation_name
229
- explicit_representation_name or name.split('::').last.underscore
222
+ explicit_representation_name or name.split('::').last.
223
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
224
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
225
+ downcase
230
226
  end
231
227
  end
232
228
  end
@@ -2,7 +2,7 @@ module Representable
2
2
  module JSON
3
3
  class Binding
4
4
  attr_reader :definition
5
- delegate :required?, :array?, :accessor, :wrapper, :name, :to => :definition
5
+ #delegate :required?, :array?, :accessor, :from, :to => :definition
6
6
 
7
7
  def initialize(definition)
8
8
  @definition = definition
@@ -18,19 +18,19 @@ module Representable
18
18
  end
19
19
 
20
20
  def collect_for(hash)
21
- nodes = hash[name.to_s] or return
21
+ nodes = hash[definition.from] or return
22
22
  nodes = [nodes] unless nodes.is_a?(Array)
23
23
 
24
24
  vals = nodes.collect { |node| yield node }
25
25
 
26
- array? ? vals : vals.first
26
+ definition.array? ? vals : vals.first
27
27
  end
28
28
  end
29
29
 
30
30
  # Represents plain key-value.
31
31
  class TextBinding < Binding
32
32
  def update_json(hash, value)
33
- hash[name] = value
33
+ hash[definition.from] = value
34
34
  end
35
35
 
36
36
  private
@@ -43,11 +43,11 @@ module Representable
43
43
 
44
44
  # Represents a tag with object binding.
45
45
  class ObjectBinding < Binding
46
- delegate :sought_type, :to => :definition
46
+ #delegate :sought_type, :to => :definition
47
47
 
48
48
  def update_json(hash, value)
49
- if array?
50
- hash.merge! ({accessor => value.collect {|v| v.to_hash(:wrap => false)}}) # hier name=> wech.
49
+ if definition.array?
50
+ hash.merge! ({definition.from => value.collect {|v| v.to_hash(:wrap => false)}}) # hier name=> wech.
51
51
  else
52
52
  hash.merge! value.to_hash
53
53
  end
@@ -60,7 +60,7 @@ module Representable
60
60
 
61
61
  def value_from_hash(xml)
62
62
  collect_for(xml) do |node|
63
- sought_type.from_json(node, :wrap => false) # hier name=> wech.
63
+ definition.sought_type.from_json(node, :wrap => false) # hier name=> wech.
64
64
  end
65
65
  end
66
66
 
@@ -2,7 +2,6 @@ module Representable
2
2
  module XML
3
3
  class Binding
4
4
  attr_reader :definition
5
- delegate :required?, :array?, :accessor, :wrapper, :name, :to => :definition
6
5
 
7
6
  def initialize(definition)
8
7
  @definition = definition
@@ -20,11 +19,11 @@ module Representable
20
19
  end
21
20
 
22
21
  def xpath
23
- name
22
+ definition.from
24
23
  end
25
24
 
26
25
  def wrap(xml, opts = {:always_create => false})
27
- wrap_with = @auto_vals ? auto_wrapper : wrapper
26
+ wrap_with = @auto_vals ? auto_wrapper : definition.wrapper
28
27
 
29
28
  return xml if !wrap_with || xml.name == wrap_with
30
29
  if !opts[:always_create] && (child = xml.children.find {|c| c.name == wrap_with })
@@ -37,7 +36,7 @@ module Representable
37
36
  nodes = xml.search("./#{xpath}")
38
37
  vals = nodes.collect { |node| yield node }
39
38
 
40
- array? ? vals : vals.first
39
+ definition.array? ? vals : vals.first
41
40
  end
42
41
  end
43
42
 
@@ -46,35 +45,33 @@ module Representable
46
45
  class AttributeBinding < Binding
47
46
  def update_xml(xml, values)
48
47
  wrap(xml).tap do |xml|
49
- xml[name] = values.to_s
48
+ xml[definition.from] = values.to_s
50
49
  end
51
50
  end
52
51
 
53
52
  private
54
53
  def value_from_node(xml)
55
- xml[name]
54
+ xml[definition.from]
56
55
  end
57
56
  end
58
57
 
59
58
 
60
59
  # Represents text content in a tag. # FIXME: is this tested???
61
60
  class TextBinding < Binding
62
- delegate :cdata?, :content?, :name?, :to => :definition
63
-
64
61
  # Updates the text in the given _xml_ block to
65
62
  # the _value_ provided.
66
63
  def update_xml(xml, value)
67
64
  wrap(xml).tap do |xml|
68
- if content?
65
+ if definition.content?
69
66
  add(xml, value)
70
- elsif name?
67
+ elsif definition.name?
71
68
  xml.name = value
72
- elsif array?
69
+ elsif definition.array?
73
70
  value.each do |v|
74
- add(xml.add_node(name), v)
71
+ add(xml.add_node(definition.from), v)
75
72
  end
76
73
  else
77
- add(xml.add_node(name), value)
74
+ add(xml.add_node(definition.from), value)
78
75
  end
79
76
  end
80
77
  end
@@ -87,30 +84,17 @@ module Representable
87
84
  end
88
85
 
89
86
  def add(dest, value)
90
- if cdata?
91
- dest.add_child(Nokogiri::XML::CDATA.new(dest.document, content))
92
- else
93
- dest.content = value.to_s
94
- end
95
- end
96
- end
97
-
98
-
99
- class NamespaceBinding < Binding
100
- private
101
- def value_from_node(xml)
102
- xml.namespace.prefix
87
+ dest.content = value.to_s
103
88
  end
104
89
  end
90
+
105
91
 
106
92
  # Represents a tag with object binding.
107
93
  class ObjectBinding < Binding
108
- delegate :sought_type, :to => :definition
109
-
110
94
  # Adds the ref's markup to +xml+.
111
95
  def update_xml(xml, value)
112
96
  wrap(xml).tap do |xml|
113
- if array?
97
+ if definition.array?
114
98
  update_xml_for_collection(xml, value)
115
99
  else
116
100
  update_xml_for_entity(xml, value)
@@ -134,7 +118,7 @@ module Representable
134
118
  # Deserializes the ref's element from +xml+.
135
119
  def value_from_node(xml)
136
120
  collect_for(xml) do |node|
137
- deserialize(sought_type, node)
121
+ deserialize(definition.sought_type, node)
138
122
  end
139
123
  end
140
124
 
@@ -1,38 +1,16 @@
1
- class Module
2
- def bool_attr_reader(*attrs)
3
- attrs.each do |attr|
4
- define_method :"#{attr}?" do
5
- instance_variable_get(:"@#{attr}") || false
6
- end
7
- end
8
- end
9
- end
10
-
11
1
  module Representable
12
- class ContradictoryNamespaces < StandardError
13
- end
14
2
  class Definition # :nodoc:
15
- attr_reader :name, :sought_type, :wrapper, :accessor, :namespace
16
- bool_attr_reader :name_explicit, :array, :cdata
3
+ attr_reader :name, :sought_type, :wrapper, :accessor, :from
4
+
17
5
 
18
6
  def initialize(sym, opts={})
19
- @accessor = sym.to_s
20
- @namespace = opts.delete(:namespace)
7
+ @accessor = @name = sym.to_s
21
8
 
9
+ @array = true if opts[:as].is_a?(Array) # DISCUSS: move to ArrayDefinition.
10
+ @from = (opts[:from] || name).to_s
11
+ @sought_type = extract_type(opts[:as])
22
12
 
23
- if opts[:as].is_a?(Array) # DISCUSS: move to ArrayDefinition.
24
- @array = true
25
- @name = (opts[:tag] || @accessor).to_s
26
- else
27
- @name = accessor
28
- @name = (opts[:from] || @name).to_s
29
- end
30
-
31
- @sought_type = extract_type(opts[:as])
32
- if @sought_type.respond_to?(:roxml_tag_name)
33
- opts[:from] ||= @sought_type.roxml_tag_name
34
- end
35
-
13
+ # FIXME: move me to xml.
36
14
  if opts[:from] == :content
37
15
  opts[:from] = '.'
38
16
  elsif opts[:from] == :name
@@ -40,17 +18,10 @@ module Representable
40
18
  elsif opts[:from] == :attr
41
19
  @sought_type = :attr
42
20
  opts[:from] = nil
43
- elsif opts[:from] == :namespace
44
- opts[:from] = '*'
45
- @sought_type = :namespace
46
- elsif opts[:from].to_s =~ /^@/ # FIXME: move me to xml.
21
+ elsif opts[:from].to_s =~ /^@/
47
22
  @sought_type = :attr
48
23
  opts[:from].sub!('@', '')
49
24
  end
50
-
51
-
52
- #raise ContradictoryNamespaces if @name.include?(':') && (@namespace.present? || @namespace == false)
53
-
54
25
  end
55
26
 
56
27
  def instance_variable_name
@@ -73,6 +44,15 @@ module Representable
73
44
  @name == '.'
74
45
  end
75
46
 
47
+ def array?
48
+ @array
49
+ end
50
+
51
+ def cdata? # FIXME: move to XML!
52
+ @cdata
53
+ end
54
+
55
+
76
56
  # Applies the block to +value+ which might also be a collection.
77
57
  def apply(value)
78
58
  return value unless value # DISCUSS: is that ok here?
@@ -26,9 +26,10 @@ module Representable
26
26
  def from_json(data, options={})
27
27
  # DISCUSS: extract #from_json call in Bindings to this place.
28
28
  data = ::JSON[data] if data.is_a?(String) # DISCUSS: #from_json sometimes receives a string (in nestings).
29
- data ||= {}
30
-
29
+ data ||= {} # DISCUSS: is this needed?
31
30
  data = data[representation_name.to_s] unless options[:wrap] == false
31
+ data ||= {} # FIXME: should we fail here? generate a warning?
32
+
32
33
 
33
34
  create_from_json.tap do |inst|
34
35
  refs = representable_attrs.map {|attr| JSON.binding_for_definition(attr) }
@@ -53,7 +54,7 @@ module Representable
53
54
  refs = self.class.representable_attrs.map {|attr| JSON.binding_for_definition(attr) }
54
55
 
55
56
  refs.each do |ref|
56
- value = public_send(ref.accessor) # DISCUSS: eventually move back to Ref.
57
+ value = public_send(ref.definition.accessor) # DISCUSS: eventually move back to Ref.
57
58
  ref.update_json(attrs, value) if value
58
59
  end
59
60
  end
@@ -67,5 +68,5 @@ module Representable
67
68
  to_hash(options).to_json
68
69
  end
69
70
  end
70
- end # Xml
71
+ end
71
72
  end
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "0.0.2"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -6,7 +6,6 @@ module Representable
6
6
  BINDING_FOR_TYPE = {
7
7
  :attr => AttributeBinding,
8
8
  :text => TextBinding,
9
- :namespace=> NamespaceBinding,
10
9
  }
11
10
 
12
11
  def self.binding_for_definition(definition)
@@ -57,13 +56,13 @@ module Representable
57
56
  module InstanceMethods # :nodoc:
58
57
  # Returns a Nokogiri::XML object representing this object.
59
58
  def to_xml(params={})
60
- params.reverse_merge!(:name => self.class.representation_name)
59
+ params[:name] ||= self.class.representation_name
61
60
 
62
61
  Nokogiri::XML::Node.new(params[:name].to_s, Nokogiri::XML::Document.new).tap do |root|
63
62
  refs = self.class.representable_attrs.map {|attr| XML.binding_for_definition(attr) }
64
63
 
65
64
  refs.each do |ref|
66
- value = public_send(ref.accessor) # DISCUSS: eventually move back to Ref.
65
+ value = public_send(ref.definition.accessor) # DISCUSS: eventually move back to Ref.
67
66
  ref.update_xml(root, value) if value
68
67
  end
69
68
  end
@@ -19,12 +19,11 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
- s.add_dependency "activesupport"
23
22
  s.add_dependency "hooks"
24
23
  s.add_dependency "nokogiri"
25
- s.add_dependency "i18n"
26
24
  s.add_dependency "json"
27
25
 
26
+ s.add_development_dependency "rake"
28
27
  s.add_development_dependency "rspec"
29
28
  s.add_development_dependency "test_xml"
30
29
  end
@@ -36,6 +36,26 @@ class DefinitionTest < MiniTest::Spec
36
36
  assert Representable::Definition.new(:songs, :as => Hash).typed?
37
37
  assert Representable::Definition.new(:songs, :as => [Hash]).typed?
38
38
  end
39
+
40
+ it "responds to #accessor" do
41
+ assert_equal "songs", @def.accessor
42
+ end
43
+
44
+ it "responds to #name" do
45
+ assert_equal "songs", @def.name
46
+ end
47
+
48
+ it "responds to #instance_variable_name" do
49
+ assert_equal :"@songs", @def.instance_variable_name
50
+ end
51
+
52
+ it "responds to #setter" do
53
+ assert_equal :"songs=", @def.setter
54
+ end
55
+
56
+ it "responds to #sought_type" do
57
+ assert_equal :text, @def.sought_type
58
+ end
39
59
  end
40
60
 
41
61
 
@@ -61,26 +81,10 @@ class DefinitionTest < MiniTest::Spec
61
81
  @def = Representable::Definition.new(:songs, :as => [], :tag => :song)
62
82
  end
63
83
 
64
- it "responds to #accessor" do
65
- assert_equal "songs", @def.accessor
66
- end
67
-
68
84
  it "responds to #array?" do
69
85
  assert @def.array?
70
86
  end
71
87
 
72
- it "responds to #name" do
73
- assert_equal "songs", @def.accessor
74
- end
75
-
76
- it "responds to #instance_variable_name" do
77
- assert_equal :"@songs", @def.instance_variable_name
78
- end
79
-
80
- it "responds to #setter" do
81
- assert_equal :"songs=", @def.setter
82
- end
83
-
84
88
  it "responds to #sought_type" do
85
89
  assert_equal :text, @def.sought_type
86
90
  end
@@ -6,7 +6,7 @@ module JsonTest
6
6
  Json = Representable::JSON
7
7
  Def = Representable::Definition
8
8
 
9
- describe "Xml module" do
9
+ describe "JSON module" do
10
10
  describe "#binding_for_definition" do
11
11
  it "returns ObjectBinding" do
12
12
  assert_kind_of Json::ObjectBinding, Json.binding_for_definition(Def.new(:band, :as => Hash))
@@ -16,11 +16,32 @@ module JsonTest
16
16
  assert_kind_of Json::TextBinding, Json.binding_for_definition(Def.new(:band))
17
17
  end
18
18
  end
19
+
20
+ describe "#from_json" do
21
+ class Band
22
+ include Json
23
+ end
24
+
25
+ it "raises error with emtpy string" do
26
+ assert_raises JSON::ParserError do
27
+ Band.from_json("")
28
+ end
29
+ end
30
+
31
+ it "returns empty hash with inappropriate hash" do
32
+ assert Band.from_json({:song => "Message In A Bottle"}.to_json)
33
+ end
34
+
35
+ it "generates warning with inappropriate hash in debugging mode" do
36
+
37
+ end
38
+ end
39
+
19
40
  end
20
41
  end
21
42
 
22
43
  class PropertyTest < MiniTest::Spec
23
- describe "property :name" do
44
+ describe "representable_property :name" do
24
45
  class Band
25
46
  include Representable::JSON
26
47
  representable_property :name
@@ -36,7 +57,6 @@ module JsonTest
36
57
  assert_equal "Bombshell Rocks", band.name
37
58
  end
38
59
 
39
-
40
60
  it "#to_json serializes correctly" do
41
61
  band = Band.new
42
62
  band.name = "Cigar"
@@ -45,27 +65,6 @@ module JsonTest
45
65
  end
46
66
  end
47
67
 
48
- describe "property :name, :as => []" do
49
- class CD
50
- include Representable::JSON
51
- representable_property :songs, :as => []
52
- end
53
-
54
- it "#from_json creates correct accessors" do
55
- cd = CD.from_json({:cd => {:songs => ["Out in the cold", "Microphone"]}}.to_json)
56
- assert_equal ["Out in the cold", "Microphone"], cd.songs
57
- end
58
-
59
- it "#to_json serializes correctly" do
60
- cd = CD.new
61
- cd.songs = ["Out in the cold", "Microphone"]
62
-
63
- assert_equal '{"cd":{"songs":["Out in the cold","Microphone"]}}', cd.to_json
64
- end
65
- end
66
- end
67
-
68
- class TypedPropertyTest < MiniTest::Spec
69
68
  describe ":as => Item" do
70
69
  class Label
71
70
  include Representable::JSON
@@ -82,20 +81,54 @@ module JsonTest
82
81
  assert_equal "Bad Religion", album.label.name
83
82
  end
84
83
 
85
- describe "#to_json" do
86
- it "serializes" do
87
- label = Label.new; label.name = "Fat Wreck"
88
- album = Album.new; album.label = label
89
-
90
- assert_equal '{"album":{"label":{"name":"Fat Wreck"}}}', album.to_json
91
- end
84
+ it "#to_json serializes" do
85
+ label = Label.new; label.name = "Fat Wreck"
86
+ album = Album.new; album.label = label
87
+
88
+ assert_equal '{"album":{"label":{"name":"Fat Wreck"}}}', album.to_json
89
+ end
90
+ end
91
+
92
+ describe ":from => :songName" do
93
+ class Song
94
+ include Representable::JSON
95
+ representable_property :name, :from => :songName
96
+ end
97
+
98
+ it "respects :from in #from_json" do
99
+ song = Song.from_json({:song => {:songName => "Run To The Hills"}}.to_json)
100
+ assert_equal "Run To The Hills", song.name
101
+ end
102
+
103
+ it "respects :from in #to_json" do
104
+ song = Song.new; song.name = "Run To The Hills"
105
+ assert_equal '{"song":{"songName":"Run To The Hills"}}', song.to_json
92
106
  end
93
107
  end
94
108
  end
95
109
 
96
110
 
97
111
  class CollectionTest < MiniTest::Spec
98
- describe ":as => [Band]" do
112
+ describe "representable_collection :name" do
113
+ class CD
114
+ include Representable::JSON
115
+ representable_collection :songs
116
+ end
117
+
118
+ it "#from_json creates correct accessors" do
119
+ cd = CD.from_json({:cd => {:songs => ["Out in the cold", "Microphone"]}}.to_json)
120
+ assert_equal ["Out in the cold", "Microphone"], cd.songs
121
+ end
122
+
123
+ it "#to_json serializes correctly" do
124
+ cd = CD.new
125
+ cd.songs = ["Out in the cold", "Microphone"]
126
+
127
+ assert_equal '{"cd":{"songs":["Out in the cold","Microphone"]}}', cd.to_json
128
+ end
129
+ end
130
+
131
+ describe "representable_collection :name, :as => Band" do
99
132
  class Band
100
133
  include Representable::JSON
101
134
  representable_property :name
@@ -107,7 +140,7 @@ module JsonTest
107
140
 
108
141
  class Compilation
109
142
  include Representable::JSON
110
- representable_property :bands, :as => [Band]
143
+ representable_collection :bands, :as => Band
111
144
  end
112
145
 
113
146
  describe "#from_json" do
@@ -131,5 +164,25 @@ module JsonTest
131
164
  assert_equal '{"compilation":{"bands":[{"name":"Diesel Boy"},{"name":"Bad Religion"}]}}', cd.to_json
132
165
  end
133
166
  end
167
+
168
+
169
+ describe ":from => :songList" do
170
+ class Songs
171
+ include Representable::JSON
172
+ representable_collection :tracks, :from => :songList
173
+ end
174
+
175
+ it "respects :from in #from_json" do
176
+ songs = Songs.from_json({:songs => {:songList => ["Out in the cold", "Microphone"]}}.to_json)
177
+ assert_equal ["Out in the cold", "Microphone"], songs.tracks
178
+ end
179
+
180
+ it "respects option in #to_json" do
181
+ songs = Songs.new
182
+ songs.tracks = ["Out in the cold", "Microphone"]
183
+
184
+ assert_equal '{"songs":{"songList":["Out in the cold","Microphone"]}}', songs.to_json
185
+ end
186
+ end
134
187
  end
135
188
  end
@@ -24,12 +24,27 @@ class RepresentableTest < MiniTest::Spec
24
24
  end
25
25
  end
26
26
 
27
+
28
+
27
29
  describe "#representable_property" do
28
30
  it "creates accessors for the attribute" do
29
31
  @band = PunkBand.new
30
32
  assert @band.name = "Bad Religion"
31
33
  assert_equal "Bad Religion", @band.name
32
34
  end
35
+
36
+ describe ":from" do
37
+ # TODO: do this with all options.
38
+ it "can be set explicitly" do
39
+ band = Class.new(Band) { representable_property :friends, :from => :friend }
40
+ assert_equal "friend", band.representable_attrs.last.from
41
+ end
42
+
43
+ it "is infered from the name implicitly" do
44
+ band = Class.new(Band) { representable_property :friends }
45
+ assert_equal "friends", band.representable_attrs.last.from
46
+ end
47
+ end
33
48
  end
34
49
 
35
50
  describe "#representable_collection" do
@@ -125,18 +125,13 @@ class CollectionTest < MiniTest::Spec
125
125
  describe ":as => [Band], :tag => :band" do
126
126
  class Compilation
127
127
  include Representable::XML
128
- representable_collection :bands, :as => Band, :tag => :band
128
+ representable_collection :bands, :as => Band, :from => :band
129
129
  end
130
130
 
131
131
  describe "#representable_collection" do
132
132
  it "declares a collection" do
133
133
  assert Compilation.representable_attrs.first.array?
134
134
  end
135
-
136
- it "accepts :tag" do
137
- assert_equal "band", Compilation.representable_attrs.first.name
138
- end
139
-
140
135
  end
141
136
 
142
137
 
@@ -175,7 +170,7 @@ class CollectionTest < MiniTest::Spec
175
170
  describe ":as => []" do
176
171
  class Album
177
172
  include Representable::XML
178
- representable_collection :songs, :tag => :song
173
+ representable_collection :songs, :from => :song
179
174
  end
180
175
 
181
176
  it "collects untyped items" do
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 9
7
8
  - 0
8
- - 2
9
- version: 0.0.2
9
+ version: 0.9.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,11 +14,11 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-06-03 00:00:00 +02:00
17
+ date: 2011-10-05 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: activesupport
21
+ name: hooks
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
@@ -31,7 +31,7 @@ dependencies:
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
33
  - !ruby/object:Gem::Dependency
34
- name: hooks
34
+ name: nokogiri
35
35
  prerelease: false
36
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
37
  none: false
@@ -44,7 +44,7 @@ dependencies:
44
44
  type: :runtime
45
45
  version_requirements: *id002
46
46
  - !ruby/object:Gem::Dependency
47
- name: nokogiri
47
+ name: json
48
48
  prerelease: false
49
49
  requirement: &id003 !ruby/object:Gem::Requirement
50
50
  none: false
@@ -57,7 +57,7 @@ dependencies:
57
57
  type: :runtime
58
58
  version_requirements: *id003
59
59
  - !ruby/object:Gem::Dependency
60
- name: i18n
60
+ name: rake
61
61
  prerelease: false
62
62
  requirement: &id004 !ruby/object:Gem::Requirement
63
63
  none: false
@@ -67,10 +67,10 @@ dependencies:
67
67
  segments:
68
68
  - 0
69
69
  version: "0"
70
- type: :runtime
70
+ type: :development
71
71
  version_requirements: *id004
72
72
  - !ruby/object:Gem::Dependency
73
- name: json
73
+ name: rspec
74
74
  prerelease: false
75
75
  requirement: &id005 !ruby/object:Gem::Requirement
76
76
  none: false
@@ -80,10 +80,10 @@ dependencies:
80
80
  segments:
81
81
  - 0
82
82
  version: "0"
83
- type: :runtime
83
+ type: :development
84
84
  version_requirements: *id005
85
85
  - !ruby/object:Gem::Dependency
86
- name: rspec
86
+ name: test_xml
87
87
  prerelease: false
88
88
  requirement: &id006 !ruby/object:Gem::Requirement
89
89
  none: false
@@ -95,19 +95,6 @@ dependencies:
95
95
  version: "0"
96
96
  type: :development
97
97
  version_requirements: *id006
98
- - !ruby/object:Gem::Dependency
99
- name: test_xml
100
- prerelease: false
101
- requirement: &id007 !ruby/object:Gem::Requirement
102
- none: false
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- segments:
107
- - 0
108
- version: "0"
109
- type: :development
110
- version_requirements: *id007
111
98
  description: Maps representation documents from and to Ruby objects. Includes XML and JSON support, plain properties and compositions.
112
99
  email:
113
100
  - apotonick@gmail.com
@@ -121,6 +108,7 @@ files:
121
108
  - .gitignore
122
109
  - .gitmodules
123
110
  - .rspec
111
+ - CHANGES.textile
124
112
  - Gemfile
125
113
  - LICENSE
126
114
  - README.rdoc