representable 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.textile +5 -0
- data/README.rdoc +164 -48
- data/lib/representable.rb +17 -10
- data/lib/representable/json.rb +6 -5
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml.rb +1 -0
- data/test/json_test.rb +84 -80
- data/test/representable_test.rb +3 -3
- data/test/test_helper.rb +2 -0
- data/test/xml_test.rb +6 -6
- metadata +80 -111
data/CHANGES.textile
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
h2. 0.10.1
|
2
|
+
|
3
|
+
* The block in @to_*@ and @from_*@ now yields the symbolized property name. If you need the binding/definition you gotta get it yourself.
|
4
|
+
* Runs with Ruby 1.8 and 1.9.
|
5
|
+
|
1
6
|
h2. 0.10.0
|
2
7
|
|
3
8
|
* Wrapping can now be set through @Representable.representation_wrap=@. Possible values are:
|
data/README.rdoc
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
|
6
6
|
== Introduction
|
7
7
|
|
8
|
-
_Representable_ maps fragments in documents to attributes in Ruby objects and back. It allows parsing representations
|
8
|
+
_Representable_ maps fragments in documents to attributes in Ruby objects and back. It allows parsing representations giving an object-oriented interface to the document. But that's only half of it! Representable can also render documents from an object instance.
|
9
9
|
|
10
|
-
This
|
10
|
+
This keeps your representation knowledge in one place when implementing REST services and clients.
|
11
11
|
|
12
12
|
|
13
13
|
== Features
|
@@ -19,86 +19,202 @@ This is especially helpful when implementing REST services and clients and keeps
|
|
19
19
|
|
20
20
|
== Example
|
21
21
|
|
22
|
+
Since you keep forgetting the heroes of your childhood you decide to implement a REST service for storing and querying those. You choose representable for handling representations.
|
22
23
|
|
24
|
+
gem 'representable'
|
23
25
|
|
24
|
-
When writing a REST service you'd have to parse and extract data from an incoming representation document manually. Given the following XML document which represents an order.
|
25
26
|
|
26
|
-
|
27
|
-
<id>1</id>
|
28
|
-
<item>
|
29
|
-
<name>Chocolate Cookie</name>
|
30
|
-
</item>
|
31
|
-
<item>
|
32
|
-
<name>Vanilla Muffin</name>
|
33
|
-
</item>
|
34
|
-
</order>
|
27
|
+
== Defining Representations
|
35
28
|
|
36
|
-
|
29
|
+
require 'representable/json'
|
37
30
|
|
38
|
-
class
|
39
|
-
include Representable::
|
31
|
+
class Hero
|
32
|
+
include Representable::JSON
|
40
33
|
|
41
|
-
representable_property :
|
42
|
-
|
34
|
+
representable_property :forename
|
35
|
+
representable_property :surename
|
43
36
|
end
|
37
|
+
|
38
|
+
This declares two simple properties. Representable will automatically add accessors to the class.
|
39
|
+
|
40
|
+
== Rendering
|
41
|
+
|
42
|
+
Now let's create and render our first hero.
|
43
|
+
|
44
|
+
peter = Hero.new
|
45
|
+
peter.forename = "Peter"
|
46
|
+
peter.surename = "Pan"
|
47
|
+
|
48
|
+
peter.to_json
|
49
|
+
#=> {"forename":"Peter","surename":"Pan"}
|
50
|
+
|
51
|
+
Those two properties are considered when rendering in #to_json.
|
52
|
+
|
53
|
+
== Parsing
|
54
|
+
|
55
|
+
The cool thing about Representable is: it works bidirectional. By declaring properties you can not only render but also parse!
|
56
|
+
|
57
|
+
hook = Hero.from_json('{"forename":"Captain","surename":"Hook"}')
|
58
|
+
hook.forename #=> "Captain"
|
44
59
|
|
45
|
-
|
46
|
-
|
60
|
+
See how easy this is? You can use an object-oriented method to read from the document.
|
61
|
+
|
62
|
+
== Nesting
|
63
|
+
|
64
|
+
You need a second domain object. Every hero has a place he comes from.
|
65
|
+
|
66
|
+
class Location
|
67
|
+
include Representable::JSON
|
47
68
|
|
48
|
-
representable_property :
|
69
|
+
representable_property :title
|
49
70
|
end
|
50
|
-
|
51
|
-
== Consuming Representations
|
52
71
|
|
53
|
-
|
72
|
+
Peter, where ya' from?
|
73
|
+
|
74
|
+
neverland = Location.new
|
75
|
+
neverland.title = "Neverland"
|
76
|
+
|
77
|
+
It makes sense to embed the location in the hero's document.
|
54
78
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@order.items.first.name # => "Chocolate Cookie"
|
79
|
+
class Hero
|
80
|
+
representable_property :origin, :as => Location
|
81
|
+
end
|
59
82
|
|
83
|
+
Using the +:as+ option allows you to include other representable objects.
|
60
84
|
|
61
|
-
|
85
|
+
peter.origin = neverland
|
86
|
+
peter.to_json
|
87
|
+
#=> {"forename":"Peter","surename":"Pan","origin":{"title":"Neverland"}}
|
62
88
|
|
63
|
-
The cool thing with object-oriented representations is: you can treat them just like any other object in Ruby and extend them dynamically - which is impossible with plain hashes.
|
64
89
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
90
|
+
== Parsing Nested Documents
|
91
|
+
|
92
|
+
Don't forget how easy it is to parse nested representations.
|
93
|
+
|
94
|
+
hook = Hero.from_json('{"name":"Captain","surename":"Hook","origin":{"title":"Dark Ocean"}}')
|
95
|
+
hook.origin.inspect #=> #<Location:0x910d7c8 @title="Dark Ocean">
|
96
|
+
hook.origin.title #=> "Dark Ocean"
|
97
|
+
|
98
|
+
Representable just creates objects from the parsed document - nothing more and nothing less.
|
99
|
+
|
100
|
+
== Simple Collections
|
101
|
+
|
102
|
+
Heroes have features, special abilities that make 'em a superhero.
|
103
|
+
|
104
|
+
class Hero
|
105
|
+
representable_collection :features
|
106
|
+
end
|
107
|
+
|
108
|
+
The second API method is +representable_collection+ and, well, declares a collection.
|
109
|
+
|
110
|
+
peter.features = ["stays young", "can fly"]
|
111
|
+
peter.to_json
|
112
|
+
#=> {"forename":"Peter","surename":"Pan","origin":{"title":"Neverland"},"features":["stays young","can fly"]}
|
113
|
+
|
114
|
+
|
115
|
+
== Typed Collections
|
71
116
|
|
117
|
+
Ok, things start working out. Your hero has a name, an origin and a list of features so far. Why not allows adding friends to Peter - nobody wants to be alone!
|
72
118
|
|
73
|
-
|
119
|
+
class Hero
|
120
|
+
representable_collection :friends, :as => Hero
|
121
|
+
end
|
122
|
+
|
123
|
+
Again, we type the collection by using the +:as+ option.
|
124
|
+
|
125
|
+
nick = Hero.new
|
126
|
+
nick.forename = "Nick"
|
127
|
+
|
128
|
+
el = Hero.new
|
129
|
+
el.forename = "El"
|
130
|
+
|
131
|
+
peter.friends = [nick, el]
|
132
|
+
|
133
|
+
I always wanted to be Peter's bro... in this example it is possible!
|
134
|
+
|
135
|
+
peter.to_json
|
136
|
+
#=> {"forename":"Peter","surename":"Pan","origin":{"title":"Neverland"},"features":["stays young","can fly"],"friends":[{"name":"Nick"},{"name":"El"}]}
|
137
|
+
|
138
|
+
|
139
|
+
== Customizing
|
140
|
+
|
141
|
+
=== Wrapping
|
142
|
+
|
143
|
+
Representable is designed to be very simple. However, a few tweaks are available. What if you want to wrap your document?
|
144
|
+
|
145
|
+
class Hero
|
146
|
+
self.representation_wrap = true
|
147
|
+
end
|
148
|
+
|
149
|
+
peter.to_json #=> {"hero":{"name":"Peter","surename":"Pan"}}
|
150
|
+
|
151
|
+
You can also provide a custom wrapper.
|
74
152
|
|
75
|
-
|
153
|
+
class Hero
|
154
|
+
self.representation_wrap = :boy
|
155
|
+
end
|
156
|
+
|
157
|
+
peter.to_json #=> {"boy":{"name":"Peter","surename":"Pan"}}
|
158
|
+
|
159
|
+
|
160
|
+
=== Mapping
|
76
161
|
|
77
|
-
|
162
|
+
If your accessor name doesn't match the attribute name in the document, use the +:from+ matcher.
|
163
|
+
|
164
|
+
class Hero
|
165
|
+
representable_property :forename, :from => :name
|
166
|
+
end
|
78
167
|
|
79
|
-
|
168
|
+
peter.to_json #=> {"name":"Peter","surename":"Pan"}
|
80
169
|
|
81
|
-
Order.new(:id => 2, :items => [candy]).to_xml
|
82
170
|
|
171
|
+
=== Filtering
|
83
172
|
|
84
|
-
Representable
|
173
|
+
Representable allows you to skip properties when rendering or parsing.
|
85
174
|
|
175
|
+
peter.to_json do |name|
|
176
|
+
name == :forename
|
177
|
+
end
|
86
178
|
|
87
|
-
|
179
|
+
#=> {"forename":"Peter"}
|
88
180
|
|
89
|
-
|
181
|
+
|
182
|
+
== XML support
|
183
|
+
|
184
|
+
Representable allows declaring a document's syntax and structure while having different formats. Currently, it ships with JSON and XML bindings.
|
185
|
+
|
186
|
+
class Hero
|
187
|
+
include Representable::XML
|
188
|
+
end
|
189
|
+
|
190
|
+
peter.to_xml
|
191
|
+
#=> <hero>
|
192
|
+
<name>Peter</name>
|
193
|
+
<surename>Pan</surename>
|
194
|
+
<location>
|
195
|
+
<title>Neverland</title>
|
196
|
+
</location>
|
197
|
+
<hero>
|
198
|
+
<name>Nick</name>
|
199
|
+
</hero>
|
200
|
+
<hero>
|
201
|
+
<name>El</name>
|
202
|
+
</hero>
|
203
|
+
</hero>
|
204
|
+
|
205
|
+
The #to_xml method gives us an XML representation of Peter - great!
|
90
206
|
|
91
207
|
|
92
208
|
== More
|
93
209
|
|
94
|
-
|
210
|
+
Instead of spreading knowledge about your representations about the entire framework, Representable keeps rendering and parsing representations in one single, testable asset. It is a new abstraction layer missing in many "RESTful" frameworks.
|
95
211
|
|
96
|
-
Representable
|
212
|
+
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.
|
97
213
|
|
98
214
|
|
99
215
|
== Copyright
|
100
216
|
|
101
|
-
Representable is a simplified fork of the ROXML gem. Big thanks to Ben Woosley for his work.
|
217
|
+
Representable is a heavily simplified fork of the ROXML gem. Big thanks to Ben Woosley for his work.
|
102
218
|
|
103
|
-
Copyright (c) 2011 Nick Sutterer <apotonick@gmail.com>
|
104
|
-
Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom.
|
219
|
+
* Copyright (c) 2011 Nick Sutterer <apotonick@gmail.com>
|
220
|
+
* Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom.
|
data/lib/representable.rb
CHANGED
@@ -16,28 +16,35 @@ module Representable
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Reads values from +doc+ and sets properties accordingly.
|
19
|
-
def update_properties_from(doc)
|
20
|
-
self.class.representable_bindings.each do |
|
21
|
-
next if
|
19
|
+
def update_properties_from(doc, &block)
|
20
|
+
self.class.representable_bindings.each do |bin|
|
21
|
+
next if eval_property_block(bin, &block) # skip if block is false.
|
22
22
|
|
23
|
-
value =
|
24
|
-
send(
|
23
|
+
value = bin.read(doc)
|
24
|
+
send(bin.definition.setter, value)
|
25
25
|
end
|
26
26
|
self
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
30
30
|
# Compiles the document going through all properties.
|
31
|
-
def create_representation_with(doc)
|
32
|
-
self.class.representable_bindings.each do |
|
33
|
-
next if
|
31
|
+
def create_representation_with(doc, &block)
|
32
|
+
self.class.representable_bindings.each do |bin|
|
33
|
+
next if eval_property_block(bin, &block) # skip if block is false.
|
34
34
|
|
35
|
-
value =
|
36
|
-
|
35
|
+
value = send(bin.definition.getter) # DISCUSS: eventually move back to Ref.
|
36
|
+
bin.write(doc, value) if value
|
37
37
|
end
|
38
38
|
doc
|
39
39
|
end
|
40
40
|
|
41
|
+
# Returns true unless a eventually given block returns false. Yields the symbolized
|
42
|
+
# property name.
|
43
|
+
def eval_property_block(binding)
|
44
|
+
# TODO: no magic symbol conversion!
|
45
|
+
block_given? and not yield binding.definition.name.to_sym
|
46
|
+
end
|
47
|
+
|
41
48
|
|
42
49
|
module ClassMethods # :nodoc:
|
43
50
|
module Declarations
|
data/lib/representable/json.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'representable'
|
2
2
|
require 'representable/bindings/json_bindings'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module Representable
|
5
6
|
# Brings #to_xml, #to_hash, #from_xml and #from_hash to your object.
|
@@ -48,8 +49,8 @@ module Representable
|
|
48
49
|
update_properties_from(data, &block)
|
49
50
|
end
|
50
51
|
|
51
|
-
def to_hash(options={})
|
52
|
-
hash = create_representation_with({})
|
52
|
+
def to_hash(options={}, &block)
|
53
|
+
hash = create_representation_with({}, &block)
|
53
54
|
|
54
55
|
return hash unless wrap = options[:wrap] || self.class.representation_wrap
|
55
56
|
|
@@ -57,8 +58,8 @@ module Representable
|
|
57
58
|
end
|
58
59
|
|
59
60
|
# Returns a JSON string representing this object.
|
60
|
-
def to_json(
|
61
|
-
to_hash(
|
61
|
+
def to_json(*args, &block)
|
62
|
+
to_hash(*args, &block).to_json
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
data/lib/representable/xml.rb
CHANGED
data/test/json_test.rb
CHANGED
@@ -8,142 +8,146 @@ module JsonTest
|
|
8
8
|
|
9
9
|
describe "JSON module" do
|
10
10
|
before do
|
11
|
-
@Band = Class.new
|
11
|
+
@Band = Class.new do
|
12
|
+
include Representable::JSON
|
13
|
+
representable_property :name
|
12
14
|
representable_property :label
|
15
|
+
|
16
|
+
def initialize(name=nil)
|
17
|
+
self.name = name if name
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
it "returns ObjectBinding" do
|
23
|
-
assert_kind_of Json::ObjectBinding, Band.binding_for_definition(Def.new(:band, :as => Hash))
|
24
|
-
end
|
25
|
-
|
26
|
-
it "returns TextBinding" do
|
27
|
-
assert_kind_of Json::TextBinding, Band.binding_for_definition(Def.new(:band))
|
21
|
+
|
22
|
+
|
23
|
+
describe ".from_json" do
|
24
|
+
it "is delegated to #from_json" do
|
25
|
+
block = lambda {|bind|}
|
26
|
+
@Band.any_instance.expects(:from_json).with("{}", "yo") # FIXME: how to expect block?
|
27
|
+
@Band.from_json("{}", "yo", &block)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
|
32
|
+
describe ".from_hash" do
|
33
|
+
it "is delegated to #from_hash" do
|
34
|
+
block = lambda {|bind|}
|
35
|
+
@Band.any_instance.expects(:from_hash).with("{}", "yo") # FIXME: how to expect block?
|
36
|
+
@Band.from_hash("{}", "yo", &block)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
40
|
+
|
38
41
|
describe "#from_json" do
|
39
42
|
before do
|
40
43
|
@band = @Band.new
|
44
|
+
@json = {:name => "Nofx", :label => "NOFX"}.to_json
|
41
45
|
end
|
42
46
|
|
43
|
-
it "
|
44
|
-
@band.from_json(
|
47
|
+
it "parses JSON and assigns properties" do
|
48
|
+
@band.from_json(@json)
|
45
49
|
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
46
50
|
end
|
47
51
|
|
48
|
-
it "forwards block to #
|
49
|
-
@band.from_json(
|
50
|
-
|
52
|
+
it "forwards block to #from_hash" do
|
53
|
+
@band.from_json(@json) do |name|
|
54
|
+
name == :name
|
51
55
|
end
|
52
56
|
|
53
57
|
assert_equal ["Nofx", nil], [@band.name, @band.label]
|
54
58
|
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe "#from_hash" do
|
63
|
+
before do
|
64
|
+
@band = @Band.new
|
65
|
+
@hash = {"name" => "Nofx", "label" => "NOFX"}
|
66
|
+
end
|
55
67
|
|
68
|
+
it "receives hash and assigns properties" do
|
69
|
+
@band.from_hash(@hash)
|
70
|
+
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
71
|
+
end
|
56
72
|
|
57
|
-
it "
|
58
|
-
@band.
|
59
|
-
|
73
|
+
it "forwards block to #update_properties_from" do
|
74
|
+
@band.from_hash(@hash) do |name|
|
75
|
+
name == :name
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal ["Nofx", nil], [@band.name, @band.label]
|
60
79
|
end
|
61
80
|
|
62
81
|
it "respects :wrap option" do
|
63
|
-
@band.
|
82
|
+
@band.from_hash({"band" => {"name" => "This Is A Standoff"}}, :wrap => :band)
|
64
83
|
assert_equal "This Is A Standoff", @band.name
|
65
84
|
end
|
66
|
-
|
85
|
+
|
67
86
|
it "respects :wrap option over representation_wrap" do
|
68
87
|
@Band.class_eval do
|
69
88
|
self.representation_wrap = :group
|
70
89
|
end
|
71
|
-
@band.
|
72
|
-
assert_equal "This Is A Standoff", @band.name
|
73
|
-
end
|
74
|
-
|
75
|
-
it "respects representation_wrap" do
|
76
|
-
@Band.class_eval do
|
77
|
-
self.representation_wrap = :group
|
78
|
-
end
|
79
|
-
@band.from_json({:group => {:name => "This Is A Standoff"}}.to_json)
|
90
|
+
@band.from_hash({"band" => {"name" => "This Is A Standoff"}}, :wrap => :band)
|
80
91
|
assert_equal "This Is A Standoff", @band.name
|
81
92
|
end
|
82
93
|
end
|
83
94
|
|
84
95
|
|
85
|
-
describe "
|
86
|
-
it "delegates to #
|
87
|
-
|
88
|
-
assert_equal ["Nofx", nil], [band.name, band.label]
|
89
|
-
end
|
90
|
-
|
91
|
-
it "passes all args to #from_json" do
|
92
|
-
block = lambda {|a,b|}
|
93
|
-
@Band.any_instance.expects(:from_json).with("{}", "yo") # FIXME: how to expect block?
|
94
|
-
@Band.from_json("{}", "yo", &block)
|
96
|
+
describe "#to_json" do
|
97
|
+
it "delegates to #to_hash and returns string" do
|
98
|
+
assert_equal "{\"name\":\"Rise Against\"}", @Band.new("Rise Against").to_json
|
95
99
|
end
|
96
100
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
it "forwards block to #to_hash" do
|
102
|
+
band = @Band.new
|
103
|
+
band.name = "The Guinea Pigs"
|
104
|
+
band.label = "n/a"
|
105
|
+
json = band.to_json do |name|
|
106
|
+
name == :name
|
101
107
|
end
|
102
|
-
|
103
|
-
|
104
|
-
it "returns empty hash with inappropriate hash" do
|
105
|
-
assert Band.from_json({:song => "Message In A Bottle"}.to_json)
|
106
|
-
end
|
107
|
-
|
108
|
-
it "generates warning with inappropriate hash in debugging mode" do
|
108
|
+
|
109
|
+
assert_equal "{\"name\":\"The Guinea Pigs\"}", json
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
113
|
|
113
|
-
describe "
|
114
|
-
it "
|
115
|
-
|
116
|
-
assert_equal
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
|
121
|
-
describe "#to_json" do
|
122
|
-
before do
|
123
|
-
@band = @Band.new
|
124
|
-
@band.label = "Fat"
|
114
|
+
describe "#to_hash" do
|
115
|
+
it "returns unwrapped hash" do
|
116
|
+
hash = @Band.new("Rise Against").to_hash
|
117
|
+
assert_equal({"name"=>"Rise Against"}, hash)
|
125
118
|
end
|
126
119
|
|
127
|
-
it "
|
128
|
-
|
120
|
+
it "respects #representation_wrap=" do
|
121
|
+
@Band.representation_wrap = :group
|
122
|
+
assert_equal({:group=>{"name"=>"Rise Against"}}, @Band.new("Rise Against").to_hash)
|
129
123
|
end
|
130
124
|
|
131
125
|
it "respects :wrap option" do
|
132
|
-
assert_equal
|
126
|
+
assert_equal({:band=>{"name"=>"NOFX"}}, @Band.new("NOFX").to_hash(:wrap => :band))
|
133
127
|
end
|
134
|
-
|
128
|
+
|
135
129
|
it "respects :wrap option over representation_wrap" do
|
136
130
|
@Band.class_eval do
|
137
131
|
self.representation_wrap = :group
|
138
132
|
end
|
139
|
-
assert_equal
|
133
|
+
assert_equal({:band=>{"name"=>"Rise Against"}}, @Band.new("Rise Against").to_hash(:wrap => :band))
|
140
134
|
end
|
135
|
+
end
|
141
136
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
137
|
+
describe "#binding_for_definition" do
|
138
|
+
it "returns ObjectBinding" do
|
139
|
+
assert_kind_of Json::ObjectBinding, @Band.binding_for_definition(Def.new(:band, :as => Hash))
|
140
|
+
end
|
141
|
+
|
142
|
+
it "returns TextBinding" do
|
143
|
+
assert_kind_of Json::TextBinding, @Band.binding_for_definition(Def.new(:band))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#representable_bindings" do
|
148
|
+
it "returns bindings for each property" do
|
149
|
+
assert_equal 2, @Band.representable_bindings.size
|
150
|
+
assert_equal "name", @Band.representable_bindings.first.definition.name
|
147
151
|
end
|
148
152
|
end
|
149
153
|
end
|
data/test/representable_test.rb
CHANGED
@@ -116,8 +116,8 @@ class RepresentableTest < MiniTest::Spec
|
|
116
116
|
|
117
117
|
it "skips elements when block returns false" do
|
118
118
|
band = PopBand.new
|
119
|
-
band.update_properties_from({"name"=>"No One's Choice", "groupies"=>2}) do |
|
120
|
-
|
119
|
+
band.update_properties_from({"name"=>"No One's Choice", "groupies"=>2}) do |name|
|
120
|
+
name == :name
|
121
121
|
end
|
122
122
|
assert_equal "No One's Choice", band.name
|
123
123
|
assert_equal nil, band.groupies
|
@@ -141,7 +141,7 @@ class RepresentableTest < MiniTest::Spec
|
|
141
141
|
end
|
142
142
|
|
143
143
|
it "skips elements when block returns false" do
|
144
|
-
assert_equal({"name"=>"No One's Choice"}, @band.send(:create_representation_with, {}) do |
|
144
|
+
assert_equal({"name"=>"No One's Choice"}, @band.send(:create_representation_with, {}) do |name| name == :name end)
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
data/test/test_helper.rb
CHANGED
data/test/xml_test.rb
CHANGED
@@ -65,8 +65,8 @@ class XmlTest < MiniTest::Spec
|
|
65
65
|
end
|
66
66
|
|
67
67
|
it "forwards block to #from_node" do
|
68
|
-
@band.from_xml(@xml) do |
|
69
|
-
|
68
|
+
@band.from_xml(@xml) do |name|
|
69
|
+
name == :name
|
70
70
|
end
|
71
71
|
|
72
72
|
assert_equal ["Nofx", nil], [@band.name, @band.label]
|
@@ -86,8 +86,8 @@ class XmlTest < MiniTest::Spec
|
|
86
86
|
end
|
87
87
|
|
88
88
|
it "forwards block to #update_properties_from" do
|
89
|
-
@band.from_node(@xml) do |
|
90
|
-
|
89
|
+
@band.from_node(@xml) do |name|
|
90
|
+
name == :name
|
91
91
|
end
|
92
92
|
|
93
93
|
assert_equal ["Nofx", nil], [@band.name, @band.label]
|
@@ -104,8 +104,8 @@ class XmlTest < MiniTest::Spec
|
|
104
104
|
band = @Band.new
|
105
105
|
band.name = "The Guinea Pigs"
|
106
106
|
band.label = "n/a"
|
107
|
-
xml = band.to_xml do |
|
108
|
-
|
107
|
+
xml = band.to_xml do |name|
|
108
|
+
name == :name
|
109
109
|
end
|
110
110
|
|
111
111
|
assert_xml_equal "<band><name>The Guinea Pigs</name></band>", xml
|
metadata
CHANGED
@@ -1,124 +1,101 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: representable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 10
|
8
|
-
- 0
|
9
|
-
version: 0.10.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Nick Sutterer
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-12-01 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: hooks
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &72137670 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 0
|
30
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
31
22
|
type: :runtime
|
32
|
-
version_requirements: *id001
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: nokogiri
|
35
23
|
prerelease: false
|
36
|
-
|
24
|
+
version_requirements: *72137670
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: nokogiri
|
27
|
+
requirement: &72137450 !ruby/object:Gem::Requirement
|
37
28
|
none: false
|
38
|
-
requirements:
|
39
|
-
- -
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
|
42
|
-
- 0
|
43
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
44
33
|
type: :runtime
|
45
|
-
version_requirements: *id002
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: json
|
48
34
|
prerelease: false
|
49
|
-
|
35
|
+
version_requirements: *72137450
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: json
|
38
|
+
requirement: &72137230 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
- 0
|
56
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
57
44
|
type: :runtime
|
58
|
-
version_requirements: *id003
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: rake
|
61
45
|
prerelease: false
|
62
|
-
|
46
|
+
version_requirements: *72137230
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &72137010 !ruby/object:Gem::Requirement
|
63
50
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
|
68
|
-
- 0
|
69
|
-
version: "0"
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
70
55
|
type: :development
|
71
|
-
version_requirements: *id004
|
72
|
-
- !ruby/object:Gem::Dependency
|
73
|
-
name: test_xml
|
74
56
|
prerelease: false
|
75
|
-
|
57
|
+
version_requirements: *72137010
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: test_xml
|
60
|
+
requirement: &72136800 !ruby/object:Gem::Requirement
|
76
61
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
- 0
|
82
|
-
version: "0"
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
83
66
|
type: :development
|
84
|
-
version_requirements: *id005
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: minitest
|
87
67
|
prerelease: false
|
88
|
-
|
68
|
+
version_requirements: *72136800
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: &72136530 !ruby/object:Gem::Requirement
|
89
72
|
none: false
|
90
|
-
requirements:
|
73
|
+
requirements:
|
91
74
|
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
|
94
|
-
- 2
|
95
|
-
- 8
|
96
|
-
version: "2.8"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.8'
|
97
77
|
type: :development
|
98
|
-
version_requirements: *id006
|
99
|
-
- !ruby/object:Gem::Dependency
|
100
|
-
name: mocha
|
101
78
|
prerelease: false
|
102
|
-
|
79
|
+
version_requirements: *72136530
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: mocha
|
82
|
+
requirement: &72136320 !ruby/object:Gem::Requirement
|
103
83
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
- 0
|
109
|
-
version: "0"
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
110
88
|
type: :development
|
111
|
-
|
112
|
-
|
113
|
-
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *72136320
|
91
|
+
description: Maps representation documents from and to Ruby objects. Includes XML
|
92
|
+
and JSON support, plain properties and compositions.
|
93
|
+
email:
|
114
94
|
- apotonick@gmail.com
|
115
95
|
executables: []
|
116
|
-
|
117
96
|
extensions: []
|
118
|
-
|
119
97
|
extra_rdoc_files: []
|
120
|
-
|
121
|
-
files:
|
98
|
+
files:
|
122
99
|
- .gitignore
|
123
100
|
- .gitmodules
|
124
101
|
- .rspec
|
@@ -142,37 +119,29 @@ files:
|
|
142
119
|
- test/representable_test.rb
|
143
120
|
- test/test_helper.rb
|
144
121
|
- test/xml_test.rb
|
145
|
-
has_rdoc: true
|
146
122
|
homepage: http://representable.apotomo.de
|
147
123
|
licenses: []
|
148
|
-
|
149
124
|
post_install_message:
|
150
125
|
rdoc_options: []
|
151
|
-
|
152
|
-
require_paths:
|
126
|
+
require_paths:
|
153
127
|
- lib
|
154
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
129
|
none: false
|
156
|
-
requirements:
|
157
|
-
- -
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
|
160
|
-
|
161
|
-
version: "0"
|
162
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
135
|
none: false
|
164
|
-
requirements:
|
165
|
-
- -
|
166
|
-
- !ruby/object:Gem::Version
|
167
|
-
|
168
|
-
- 0
|
169
|
-
version: "0"
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
170
140
|
requirements: []
|
171
|
-
|
172
141
|
rubyforge_project:
|
173
|
-
rubygems_version: 1.
|
142
|
+
rubygems_version: 1.8.10
|
174
143
|
signing_key:
|
175
144
|
specification_version: 3
|
176
|
-
summary: Maps representation documents from and to Ruby objects. Includes XML and
|
145
|
+
summary: Maps representation documents from and to Ruby objects. Includes XML and
|
146
|
+
JSON support, plain properties and compositions.
|
177
147
|
test_files: []
|
178
|
-
|