representable 1.2.8 → 1.2.9
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.
- data/.travis.yml +1 -1
- data/CHANGES.textile +6 -0
- data/TODO +7 -0
- data/gemfiles/Gemfile.mongoid-2.4 +1 -2
- data/lib/representable.rb +1 -1
- data/lib/representable/binding.rb +38 -9
- data/lib/representable/bindings/hash_bindings.rb +5 -4
- data/lib/representable/bindings/xml_bindings.rb +6 -6
- data/lib/representable/bindings/yaml_bindings.rb +3 -3
- data/lib/representable/definition.rb +1 -1
- data/lib/representable/json/hash.rb +2 -1
- data/lib/representable/readable_writeable.rb +29 -0
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml/hash.rb +1 -0
- data/test/coercion_test.rb +2 -0
- data/test/definition_test.rb +4 -0
- data/test/example.rb +21 -1
- data/test/hash_bindings_test.rb +7 -7
- data/test/json_test.rb +4 -4
- data/test/representable_test.rb +125 -0
- data/test/xml_bindings_test.rb +8 -8
- data/test/xml_test.rb +5 -5
- metadata +4 -2
data/.travis.yml
CHANGED
data/CHANGES.textile
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
h2. 1.2.9
|
2
|
+
|
3
|
+
* When @:class@ returns @nil@ we no longer try to create a new instance but use the processed fragment itself.
|
4
|
+
* @:instance@ allows overriding the @ObjectBinding#create_object@ workflow by returning an instance from the lambda. This is particularly helpful when you need to inject additional data into the property object created in #deserialize.
|
5
|
+
* @:extend@ and @:class@ now also accept procs which allows having polymorphic properties and collections where representer and class can be chosen at runtime.
|
6
|
+
|
1
7
|
h2. 1.2.8
|
2
8
|
|
3
9
|
* Reverting all the bullshit from 1.2.7 making it even better. @Binding@s now wrap their @Definition@ instance adopting its API. Moved the binding_for_definition mechanics to the respecting @Binding@ subclass.
|
data/TODO
ADDED
data/lib/representable.rb
CHANGED
@@ -119,7 +119,7 @@ private
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def representable_bindings_for(format)
|
122
|
-
representable_attrs.map {|attr| format.build_for(attr) }
|
122
|
+
representable_attrs.map {|attr| format.build_for(attr, self) }
|
123
123
|
end
|
124
124
|
|
125
125
|
# Returns the wrapper for the representation. Mostly used in XML.
|
@@ -9,6 +9,11 @@ module Representable
|
|
9
9
|
def definition # TODO: remove in 1.4.
|
10
10
|
raise "Binding#definition is no longer supported as all Definition methods are now delegated automatically."
|
11
11
|
end
|
12
|
+
|
13
|
+
def initialize(definition, represented)
|
14
|
+
super(definition)
|
15
|
+
@represented = represented
|
16
|
+
end
|
12
17
|
|
13
18
|
# Main entry point for rendering/parsing a property object.
|
14
19
|
def serialize(value)
|
@@ -24,7 +29,7 @@ module Representable
|
|
24
29
|
# at runtime.
|
25
30
|
module Extend
|
26
31
|
# Extends the object with its representer before serialization.
|
27
|
-
def serialize(
|
32
|
+
def serialize(*)
|
28
33
|
extend_for(super)
|
29
34
|
end
|
30
35
|
|
@@ -33,12 +38,22 @@ module Representable
|
|
33
38
|
end
|
34
39
|
|
35
40
|
def extend_for(object)
|
36
|
-
if mod =
|
41
|
+
if mod = representer_module_for(object) # :extend.
|
37
42
|
object.extend(*mod)
|
38
43
|
end
|
39
|
-
|
44
|
+
|
40
45
|
object
|
41
46
|
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def representer_module_for(object, *args)
|
50
|
+
call_proc_for(representer_module, object) # TODO: how to pass additional data to the computing block?`
|
51
|
+
end
|
52
|
+
|
53
|
+
def call_proc_for(proc, *args)
|
54
|
+
return proc unless proc.is_a?(Proc)
|
55
|
+
@represented.instance_exec(*args, &proc)
|
56
|
+
end
|
42
57
|
end
|
43
58
|
|
44
59
|
module Object
|
@@ -47,18 +62,32 @@ module Representable
|
|
47
62
|
def serialize(object)
|
48
63
|
return object if object.nil?
|
49
64
|
|
50
|
-
super
|
65
|
+
super.send(serialize_method, :wrap => false) # TODO: pass :binding => self
|
51
66
|
end
|
52
67
|
|
53
|
-
def deserialize(data)
|
68
|
+
def deserialize(data)
|
54
69
|
# DISCUSS: does it make sense to skip deserialization of nil-values here?
|
55
|
-
super(create_object).send(deserialize_method, data)
|
70
|
+
super(create_object(data)).send(deserialize_method, data)
|
56
71
|
end
|
57
72
|
|
58
|
-
def create_object
|
59
|
-
|
73
|
+
def create_object(fragment)
|
74
|
+
instance_for(fragment) or class_for(fragment)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def class_for(fragment, *args)
|
79
|
+
item_class = class_from(fragment) or return fragment # DISCUSS: is it legal to return the very fragment here?
|
80
|
+
item_class.new
|
81
|
+
end
|
82
|
+
|
83
|
+
def class_from(fragment, *args)
|
84
|
+
call_proc_for(sought_type, fragment)
|
85
|
+
end
|
86
|
+
|
87
|
+
def instance_for(fragment, *args)
|
88
|
+
return unless options[:instance]
|
89
|
+
call_proc_for(options[:instance], fragment)
|
60
90
|
end
|
61
91
|
end
|
62
|
-
|
63
92
|
end
|
64
93
|
end
|
@@ -16,10 +16,10 @@ module Representable
|
|
16
16
|
|
17
17
|
|
18
18
|
class PropertyBinding < Representable::Binding
|
19
|
-
def self.build_for(definition)
|
20
|
-
return CollectionBinding.new(definition) if definition.array?
|
21
|
-
return HashBinding.new(definition) if definition.hash?
|
22
|
-
new(definition)
|
19
|
+
def self.build_for(definition, represented)
|
20
|
+
return CollectionBinding.new(definition, represented) if definition.array?
|
21
|
+
return HashBinding.new(definition, represented) if definition.hash?
|
22
|
+
new(definition, represented)
|
23
23
|
end
|
24
24
|
|
25
25
|
def initialize(*args) # FIXME. make generic.
|
@@ -50,6 +50,7 @@ module Representable
|
|
50
50
|
|
51
51
|
class CollectionBinding < PropertyBinding
|
52
52
|
def serialize_for(value)
|
53
|
+
# value.enum_for(:each_with_index).collect { |obj, i| serialize(obj, i) } # DISCUSS: provide ary index/hash key for representer_module_for?
|
53
54
|
value.collect { |obj| serialize(obj) }
|
54
55
|
end
|
55
56
|
|
@@ -24,12 +24,12 @@ module Representable
|
|
24
24
|
|
25
25
|
|
26
26
|
class PropertyBinding < Binding
|
27
|
-
def self.build_for(definition)
|
28
|
-
return CollectionBinding.new(definition) if definition.array?
|
29
|
-
return HashBinding.new(definition) if definition.hash? and not definition.options[:use_attributes] # FIXME: hate this.
|
30
|
-
return AttributeHashBinding.new(definition) if definition.hash? and definition.options[:use_attributes]
|
31
|
-
return AttributeBinding.new(definition) if definition.attribute
|
32
|
-
new(definition)
|
27
|
+
def self.build_for(definition, represented)
|
28
|
+
return CollectionBinding.new(definition, represented) if definition.array?
|
29
|
+
return HashBinding.new(definition, represented) if definition.hash? and not definition.options[:use_attributes] # FIXME: hate this.
|
30
|
+
return AttributeHashBinding.new(definition, represented) if definition.hash? and definition.options[:use_attributes]
|
31
|
+
return AttributeBinding.new(definition, represented) if definition.attribute
|
32
|
+
new(definition, represented)
|
33
33
|
end
|
34
34
|
|
35
35
|
def initialize(*args)
|
@@ -19,12 +19,12 @@ module Representable
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class PropertyBinding < Representable::Hash::PropertyBinding
|
22
|
-
def self.build_for(definition)
|
23
|
-
return CollectionBinding.new(definition) if definition.array?
|
22
|
+
def self.build_for(definition, represented)
|
23
|
+
return CollectionBinding.new(definition, represented) if definition.array?
|
24
24
|
#return HashBinding.new(definition) if definition.hash? and not definition.options[:use_attributes] # FIXME: hate this.
|
25
25
|
#return AttributeHashBinding.new(definition) if definition.hash? and definition.options[:use_attributes]
|
26
26
|
#return AttributeBinding.new(definition) if definition.attribute
|
27
|
-
new(definition)
|
27
|
+
new(definition, represented)
|
28
28
|
end
|
29
29
|
|
30
30
|
def initialize(*args) # FIXME. make generic.
|
@@ -20,7 +20,7 @@ module Representable
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def typed?
|
23
|
-
sought_type.is_a?(Class) or representer_module # also true if only :extend is set, for people who want solely rendering.
|
23
|
+
sought_type.is_a?(Class) or representer_module or options[:instance] # also true if only :extend is set, for people who want solely rendering.
|
24
24
|
end
|
25
25
|
|
26
26
|
def array?
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Representable
|
2
|
+
module Feature
|
3
|
+
module ReadableWriteable
|
4
|
+
def deserialize_property(binding, doc, options)
|
5
|
+
return unless binding.writeable?
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def serialize_property(binding, doc, options)
|
10
|
+
return unless binding.readable?
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: i hate monkey-patching Definition here since it globally adds this options. However, for now this should be ok :-)
|
17
|
+
class Definition
|
18
|
+
# TODO: make this generic like `option :writeable, :default => true`
|
19
|
+
def writeable?
|
20
|
+
return options[:writeable] if options.has_key?(:writeable)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def readable?
|
25
|
+
return options[:readable] if options.has_key?(:readable)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/test/coercion_test.rb
CHANGED
@@ -35,6 +35,8 @@ class VirtusCoercionTest < MiniTest::Spec
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it "coerces into the provided type" do
|
38
|
+
skip "Virtus is still not correctly treating coercion on class level?"
|
39
|
+
|
38
40
|
song = ImmigrantSong.new.from_json("{\"composed_at\":\"November 18th, 1983\",\"track\":\"18\"}")
|
39
41
|
assert_equal DateTime.parse("Fri, 18 Nov 1983 00:00:00 +0000"), song.composed_at
|
40
42
|
assert_equal 18, song.track
|
data/test/definition_test.rb
CHANGED
@@ -25,6 +25,10 @@ class DefinitionTest < MiniTest::Spec
|
|
25
25
|
it "is true when :extend is present, only" do
|
26
26
|
assert Representable::Definition.new(:songs, :extend => Hash).typed?
|
27
27
|
end
|
28
|
+
|
29
|
+
it "is true when :instance is present, only" do
|
30
|
+
assert Representable::Definition.new(:songs, :instance => Object.new).typed?
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
it "responds to #getter and returns string" do
|
data/test/example.rb
CHANGED
@@ -59,6 +59,11 @@ puts song.extend(SongRepresenter).to_json
|
|
59
59
|
######### nesting types
|
60
60
|
|
61
61
|
class Album < OpenStruct
|
62
|
+
def name
|
63
|
+
puts @table.inspect
|
64
|
+
#@attributes
|
65
|
+
@table[:name]
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
69
|
module AlbumRepresenter
|
@@ -88,6 +93,20 @@ SongRepresenter.module_eval do
|
|
88
93
|
end
|
89
94
|
|
90
95
|
|
96
|
+
######### using helpers (customizing the rendering/parsing)
|
97
|
+
module AlbumRepresenter
|
98
|
+
def name
|
99
|
+
super.upper
|
100
|
+
end
|
101
|
+
end
|
102
|
+
album = Album.new(:name => "The Police", :songs => [song, Song.new(:title => "Synchronicity")])
|
103
|
+
puts album.extend(AlbumRepresenter).to_json
|
104
|
+
|
105
|
+
SongRepresenter.module_eval do
|
106
|
+
@representable_attrs = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
|
91
110
|
######### inheritance
|
92
111
|
module SongRepresenter
|
93
112
|
include Representable::JSON
|
@@ -156,4 +175,5 @@ puts song.extend(SongRepresenter).to_yaml
|
|
156
175
|
|
157
176
|
######### custom methods in representer (using helpers)
|
158
177
|
######### r/w, conditions
|
159
|
-
#########
|
178
|
+
#########
|
179
|
+
######### polymorphic :extend and :class, instance context!, :instance
|
data/test/hash_bindings_test.rb
CHANGED
@@ -15,7 +15,7 @@ class HashBindingTest < MiniTest::Spec
|
|
15
15
|
describe "PropertyBinding" do
|
16
16
|
describe "#read" do
|
17
17
|
before do
|
18
|
-
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song))
|
18
|
+
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song), nil)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "returns fragment if present" do
|
@@ -32,7 +32,7 @@ class HashBindingTest < MiniTest::Spec
|
|
32
32
|
|
33
33
|
describe "with plain text" do
|
34
34
|
before do
|
35
|
-
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song))
|
35
|
+
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song), nil)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "extracts with #read" do
|
@@ -48,7 +48,7 @@ class HashBindingTest < MiniTest::Spec
|
|
48
48
|
|
49
49
|
describe "with an object" do
|
50
50
|
before do
|
51
|
-
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song, :class => SongWithRepresenter))
|
51
|
+
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song, :class => SongWithRepresenter), nil)
|
52
52
|
@doc = {}
|
53
53
|
end
|
54
54
|
|
@@ -64,7 +64,7 @@ class HashBindingTest < MiniTest::Spec
|
|
64
64
|
|
65
65
|
describe "with an object and :extend" do
|
66
66
|
before do
|
67
|
-
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song, :class => Song, :extend => SongRepresenter))
|
67
|
+
@property = Representable::Hash::PropertyBinding.new(Representable::Definition.new(:song, :class => Song, :extend => SongRepresenter), nil)
|
68
68
|
@doc = {}
|
69
69
|
end
|
70
70
|
|
@@ -83,7 +83,7 @@ class HashBindingTest < MiniTest::Spec
|
|
83
83
|
describe "CollectionBinding" do
|
84
84
|
describe "with plain text items" do
|
85
85
|
before do
|
86
|
-
@property = Representable::Hash::CollectionBinding.new(Representable::Definition.new(:songs, :collection => true))
|
86
|
+
@property = Representable::Hash::CollectionBinding.new(Representable::Definition.new(:songs, :collection => true), nil)
|
87
87
|
end
|
88
88
|
|
89
89
|
it "extracts with #read" do
|
@@ -104,7 +104,7 @@ class HashBindingTest < MiniTest::Spec
|
|
104
104
|
describe "HashBinding" do
|
105
105
|
describe "with plain text items" do
|
106
106
|
before do
|
107
|
-
@property = Representable::Hash::HashBinding.new(Representable::Definition.new(:songs, :hash => true))
|
107
|
+
@property = Representable::Hash::HashBinding.new(Representable::Definition.new(:songs, :hash => true), nil)
|
108
108
|
end
|
109
109
|
|
110
110
|
it "extracts with #read" do
|
@@ -120,7 +120,7 @@ class HashBindingTest < MiniTest::Spec
|
|
120
120
|
|
121
121
|
describe "with objects" do
|
122
122
|
before do
|
123
|
-
@property = Representable::Hash::HashBinding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter))
|
123
|
+
@property = Representable::Hash::HashBinding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter), nil)
|
124
124
|
end
|
125
125
|
|
126
126
|
it "doesn't change the represented hash in #write" do
|
data/test/json_test.rb
CHANGED
@@ -128,19 +128,19 @@ module JsonTest
|
|
128
128
|
|
129
129
|
describe "#build_for" do
|
130
130
|
it "returns ObjectBinding" do
|
131
|
-
assert_kind_of Representable::Hash::ObjectBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :class => Hash))
|
131
|
+
assert_kind_of Representable::Hash::ObjectBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :class => Hash), nil)
|
132
132
|
end
|
133
133
|
|
134
134
|
it "returns TextBinding" do
|
135
|
-
assert_kind_of Representable::Hash::PropertyBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band))
|
135
|
+
assert_kind_of Representable::Hash::PropertyBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band), nil)
|
136
136
|
end
|
137
137
|
|
138
138
|
it "returns HashBinding" do
|
139
|
-
assert_kind_of Representable::Hash::HashBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :hash => true))
|
139
|
+
assert_kind_of Representable::Hash::HashBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :hash => true), nil)
|
140
140
|
end
|
141
141
|
|
142
142
|
it "returns CollectionBinding" do
|
143
|
-
assert_kind_of Representable::Hash::CollectionBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :collection => true))
|
143
|
+
assert_kind_of Representable::Hash::CollectionBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :collection => true), nil)
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
data/test/representable_test.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class RepresentableTest < MiniTest::Spec
|
4
|
+
def self.representer!(name=:representer, &block)
|
5
|
+
let(name) do
|
6
|
+
Module.new do
|
7
|
+
include Representable::Hash
|
8
|
+
instance_exec(&block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
4
13
|
class Band
|
5
14
|
include Representable
|
6
15
|
property :name
|
@@ -403,6 +412,122 @@ class RepresentableTest < MiniTest::Spec
|
|
403
412
|
assert_equal "oh yes", band.fame
|
404
413
|
end
|
405
414
|
end
|
415
|
+
|
416
|
+
describe ":extend and :class" do
|
417
|
+
module UpcaseRepresenter
|
418
|
+
def to_hash(*); upcase; end
|
419
|
+
def from_hash(hsh); self.class.new hsh.upcase; end # DISCUSS: from_hash must return self.
|
420
|
+
end
|
421
|
+
module DowncaseRepresenter
|
422
|
+
def to_hash(*); downcase; end
|
423
|
+
def from_hash(hsh); hsh.downcase; end
|
424
|
+
end
|
425
|
+
class UpcaseString < String; end
|
426
|
+
|
427
|
+
|
428
|
+
describe "lambda blocks" do
|
429
|
+
representer! do
|
430
|
+
property :name, :extend => lambda { |name| compute_representer(name) }
|
431
|
+
end
|
432
|
+
|
433
|
+
it "executes lambda in represented instance context" do
|
434
|
+
Song.new("Carnage").instance_eval do
|
435
|
+
def compute_representer(name)
|
436
|
+
UpcaseRepresenter
|
437
|
+
end
|
438
|
+
self
|
439
|
+
end.extend(representer).to_hash.must_equal({"name" => "CARNAGE"})
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
describe ":instance" do
|
444
|
+
obj = String.new("Fate")
|
445
|
+
mod = Module.new { def from_hash(*); self; end }
|
446
|
+
representer! do
|
447
|
+
property :name, :extend => mod, :instance => lambda { |name| obj }
|
448
|
+
end
|
449
|
+
|
450
|
+
it "uses object from :instance but still extends it" do
|
451
|
+
song = Song.new.extend(representer).from_hash("name" => "Eric's Had A Bad Day")
|
452
|
+
song.name.must_equal obj
|
453
|
+
song.name.must_be_kind_of mod
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
describe "property with :extend" do
|
458
|
+
representer! do
|
459
|
+
property :name, :extend => lambda { |name| name.is_a?(UpcaseString) ? UpcaseRepresenter : DowncaseRepresenter }, :class => String
|
460
|
+
end
|
461
|
+
|
462
|
+
it "uses lambda when rendering" do
|
463
|
+
assert_equal({"name" => "you make me thick"}, Song.new("You Make Me Thick").extend(representer).to_hash )
|
464
|
+
assert_equal({"name" => "STEPSTRANGER"}, Song.new(UpcaseString.new "Stepstranger").extend(representer).to_hash )
|
465
|
+
end
|
466
|
+
|
467
|
+
it "uses lambda when parsing" do
|
468
|
+
Song.new.extend(representer).from_hash({"name" => "You Make Me Thick"}).name.must_equal "you make me thick"
|
469
|
+
Song.new.extend(representer).from_hash({"name" => "Stepstranger"}).name.must_equal "stepstranger" # DISCUSS: we compare "".is_a?(UpcaseString)
|
470
|
+
end
|
471
|
+
|
472
|
+
describe "with :class lambda" do
|
473
|
+
representer! do
|
474
|
+
property :name, :extend => lambda { |name| name.is_a?(UpcaseString) ? UpcaseRepresenter : DowncaseRepresenter },
|
475
|
+
:class => lambda { |fragment| fragment == "Still Failing?" ? String : UpcaseString }
|
476
|
+
end
|
477
|
+
|
478
|
+
it "creates instance from :class lambda when parsing" do
|
479
|
+
song = Song.new.extend(representer).from_hash({"name" => "Quitters Never Win"})
|
480
|
+
song.name.must_be_kind_of UpcaseString
|
481
|
+
song.name.must_equal "QUITTERS NEVER WIN"
|
482
|
+
|
483
|
+
song = Song.new.extend(representer).from_hash({"name" => "Still Failing?"})
|
484
|
+
song.name.must_be_kind_of String
|
485
|
+
song.name.must_equal "still failing?"
|
486
|
+
end
|
487
|
+
|
488
|
+
describe "when :class lambda returns nil" do
|
489
|
+
representer! do
|
490
|
+
property :name, :extend => lambda { |name| Module.new { def from_hash(data); data; end } },
|
491
|
+
:class => nil
|
492
|
+
end
|
493
|
+
|
494
|
+
it "skips creating new instance" do
|
495
|
+
song = Song.new.extend(representer).from_hash({"name" => string = "Satellite"})
|
496
|
+
song.name.object_id.must_equal string.object_id
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
|
503
|
+
describe "collection with :extend" do
|
504
|
+
representer! do
|
505
|
+
collection :songs, :extend => lambda { |name| name.is_a?(UpcaseString) ? UpcaseRepresenter : DowncaseRepresenter }, :class => String
|
506
|
+
end
|
507
|
+
|
508
|
+
it "uses lambda for each item when rendering" do
|
509
|
+
Album.new([UpcaseString.new("Dean Martin"), "Charlie Still Smirks"]).extend(representer).to_hash.must_equal("songs"=>["DEAN MARTIN", "charlie still smirks"])
|
510
|
+
end
|
511
|
+
|
512
|
+
it "uses lambda for each item when parsing" do
|
513
|
+
album = Album.new.extend(representer).from_hash("songs"=>["DEAN MARTIN", "charlie still smirks"])
|
514
|
+
album.songs.must_equal ["dean martin", "charlie still smirks"] # DISCUSS: we compare "".is_a?(UpcaseString)
|
515
|
+
end
|
516
|
+
|
517
|
+
describe "with :class lambda" do
|
518
|
+
representer! do
|
519
|
+
collection :songs, :extend => lambda { |name| name.is_a?(UpcaseString) ? UpcaseRepresenter : DowncaseRepresenter },
|
520
|
+
:class => lambda { |fragment| fragment == "Still Failing?" ? String : UpcaseString }
|
521
|
+
end
|
522
|
+
|
523
|
+
it "creates instance from :class lambda for each item when parsing" do
|
524
|
+
album = Album.new.extend(representer).from_hash("songs"=>["Still Failing?", "charlie still smirks"])
|
525
|
+
album.songs.must_equal ["still failing?", "CHARLIE STILL SMIRKS"]
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
end
|
406
531
|
|
407
532
|
describe "Config" do
|
408
533
|
before do
|
data/test/xml_bindings_test.rb
CHANGED
@@ -26,7 +26,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
26
26
|
describe "PropertyBinding" do
|
27
27
|
describe "with plain text" do
|
28
28
|
before do
|
29
|
-
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song))
|
29
|
+
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song), nil)
|
30
30
|
end
|
31
31
|
|
32
32
|
it "extracts with #read" do
|
@@ -41,7 +41,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
41
41
|
|
42
42
|
describe "with an object" do
|
43
43
|
before do
|
44
|
-
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :class => SongWithRepresenter))
|
44
|
+
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :class => SongWithRepresenter), nil)
|
45
45
|
end
|
46
46
|
|
47
47
|
it "extracts with #read" do
|
@@ -56,7 +56,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
56
56
|
|
57
57
|
describe "with an object and :extend" do
|
58
58
|
before do
|
59
|
-
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :class => Song, :extend => SongRepresenter))
|
59
|
+
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :class => Song, :extend => SongRepresenter), nil)
|
60
60
|
end
|
61
61
|
|
62
62
|
it "extracts with #read" do
|
@@ -74,7 +74,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
74
74
|
describe "CollectionBinding" do
|
75
75
|
describe "with plain text items" do
|
76
76
|
before do
|
77
|
-
@property = Representable::XML::CollectionBinding.new(Representable::Definition.new(:song, :collection => true))
|
77
|
+
@property = Representable::XML::CollectionBinding.new(Representable::Definition.new(:song, :collection => true), nil)
|
78
78
|
end
|
79
79
|
|
80
80
|
it "extracts with #read" do
|
@@ -90,7 +90,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
90
90
|
|
91
91
|
describe "with objects" do
|
92
92
|
before do
|
93
|
-
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :collection => true, :class => SongWithRepresenter))
|
93
|
+
@property = Representable::XML::PropertyBinding.new(Representable::Definition.new(:song, :collection => true, :class => SongWithRepresenter), nil)
|
94
94
|
end
|
95
95
|
|
96
96
|
it "extracts with #read" do
|
@@ -111,7 +111,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
111
111
|
describe "HashBinding" do
|
112
112
|
describe "with plain text items" do
|
113
113
|
before do
|
114
|
-
@property = Representable::XML::HashBinding.new(Representable::Definition.new(:songs, :hash => true))
|
114
|
+
@property = Representable::XML::HashBinding.new(Representable::Definition.new(:songs, :hash => true), nil)
|
115
115
|
end
|
116
116
|
|
117
117
|
it "extracts with #read" do
|
@@ -127,7 +127,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
127
127
|
|
128
128
|
describe "with objects" do
|
129
129
|
before do
|
130
|
-
@property = Representable::XML::HashBinding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter))
|
130
|
+
@property = Representable::XML::HashBinding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter), nil)
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
@@ -136,7 +136,7 @@ class XMLBindingTest < MiniTest::Spec
|
|
136
136
|
describe "AttributeBinding" do
|
137
137
|
describe "with plain text items" do
|
138
138
|
before do
|
139
|
-
@property = Representable::XML::AttributeBinding.new(Representable::Definition.new(:name, :attribute => true))
|
139
|
+
@property = Representable::XML::AttributeBinding.new(Representable::Definition.new(:name, :attribute => true), nil)
|
140
140
|
end
|
141
141
|
|
142
142
|
it "extracts with #read" do
|
data/test/xml_test.rb
CHANGED
@@ -126,20 +126,20 @@ class XmlTest < MiniTest::Spec
|
|
126
126
|
|
127
127
|
describe "XML::Binding#build_for" do
|
128
128
|
it "returns AttributeBinding" do
|
129
|
-
assert_kind_of XML::AttributeBinding, XML::PropertyBinding.build_for(Def.new(:band, :from => "band", :attribute => true))
|
129
|
+
assert_kind_of XML::AttributeBinding, XML::PropertyBinding.build_for(Def.new(:band, :from => "band", :attribute => true), nil)
|
130
130
|
end
|
131
131
|
|
132
132
|
it "returns PropertyBinding" do
|
133
|
-
assert_kind_of XML::PropertyBinding, XML::PropertyBinding.build_for(Def.new(:band, :class => Hash))
|
134
|
-
assert_kind_of XML::PropertyBinding, XML::PropertyBinding.build_for(Def.new(:band, :from => :content))
|
133
|
+
assert_kind_of XML::PropertyBinding, XML::PropertyBinding.build_for(Def.new(:band, :class => Hash), nil)
|
134
|
+
assert_kind_of XML::PropertyBinding, XML::PropertyBinding.build_for(Def.new(:band, :from => :content), nil)
|
135
135
|
end
|
136
136
|
|
137
137
|
it "returns CollectionBinding" do
|
138
|
-
assert_kind_of XML::CollectionBinding, XML::PropertyBinding.build_for(Def.new(:band, :collection => :true))
|
138
|
+
assert_kind_of XML::CollectionBinding, XML::PropertyBinding.build_for(Def.new(:band, :collection => :true), nil)
|
139
139
|
end
|
140
140
|
|
141
141
|
it "returns HashBinding" do
|
142
|
-
assert_kind_of XML::HashBinding, XML::PropertyBinding.build_for(Def.new(:band, :hash => :true))
|
142
|
+
assert_kind_of XML::HashBinding, XML::PropertyBinding.build_for(Def.new(:band, :hash => :true), nil)
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: representable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -155,6 +155,7 @@ files:
|
|
155
155
|
- LICENSE
|
156
156
|
- README.rdoc
|
157
157
|
- Rakefile
|
158
|
+
- TODO
|
158
159
|
- gemfiles/Gemfile.mongoid-2.4
|
159
160
|
- lib/representable.rb
|
160
161
|
- lib/representable/binding.rb
|
@@ -170,6 +171,7 @@ files:
|
|
170
171
|
- lib/representable/json.rb
|
171
172
|
- lib/representable/json/collection.rb
|
172
173
|
- lib/representable/json/hash.rb
|
174
|
+
- lib/representable/readable_writeable.rb
|
173
175
|
- lib/representable/version.rb
|
174
176
|
- lib/representable/xml.rb
|
175
177
|
- lib/representable/xml/collection.rb
|