representable 1.0.1 → 1.1.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.
@@ -9,8 +9,9 @@ module Representable
9
9
  # things might work as expected.
10
10
  module JSON
11
11
  def self.binding_for_definition(definition)
12
- return ObjectBinding.new(definition) if definition.typed?
13
- TextBinding.new(definition)
12
+ return CollectionBinding.new(definition) if definition.array?
13
+ return HashBinding.new(definition) if definition.hash?
14
+ PropertyBinding.new(definition)
14
15
  end
15
16
 
16
17
  def self.included(base)
@@ -0,0 +1,38 @@
1
+ module Representable::JSON
2
+ module Collection
3
+ include Representable::JSON
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include Representable
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+
13
+ module ClassMethods
14
+ def items(options)
15
+ collection :_self, options
16
+ end
17
+ end
18
+
19
+
20
+ def create_representation_with(doc, options, format)
21
+ bin = representable_bindings_for(format).first
22
+ bin.serialize_for(self)
23
+ end
24
+
25
+ def update_properties_from(doc, options, format)
26
+ bin = representable_bindings_for(format).first
27
+ value = bin.deserialize_from(doc)
28
+ replace(value)
29
+ end
30
+
31
+ # FIXME: refactor Definition so we can simply add options in #items to existing definition.
32
+ def representable_attrs
33
+ attrs = super
34
+ attrs << Definition.new(:_self, :collection => true) if attrs.size == 0
35
+ attrs
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module Representable::JSON
2
+ module Hash
3
+ include Representable::JSON
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include Representable
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+
13
+ module ClassMethods
14
+ def values(options)
15
+ hash :_self, options
16
+ end
17
+ end
18
+
19
+
20
+ def create_representation_with(doc, options, format)
21
+ bin = representable_bindings_for(format).first
22
+ bin.serialize_for(self)
23
+ end
24
+
25
+ def update_properties_from(doc, options, format)
26
+ bin = representable_bindings_for(format).first
27
+ value = bin.deserialize_from(doc)
28
+ replace(value)
29
+ end
30
+
31
+ # FIXME: refactor Definition so we can simply add options in #items to existing definition.
32
+ def representable_attrs
33
+ attrs = super
34
+ attrs << Definition.new(:_self, :hash => true) if attrs.size == 0
35
+ attrs
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -5,9 +5,10 @@ require 'nokogiri'
5
5
  module Representable
6
6
  module XML
7
7
  def self.binding_for_definition(definition)
8
- return ObjectBinding.new(definition) if definition.typed?
9
- return AttributeBinding.new(definition) if definition.attribute
10
- TextBinding.new(definition)
8
+ return CollectionBinding.new(definition) if definition.array?
9
+ return HashBinding.new(definition) if definition.hash?
10
+ return AttributeBinding.new(definition) if definition.attribute
11
+ PropertyBinding.new(definition)
11
12
  end
12
13
 
13
14
  def self.included(base)
@@ -0,0 +1,38 @@
1
+ module Representable::XML
2
+ module Collection
3
+ include Representable::XML
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include Representable
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+
13
+ module ClassMethods
14
+ def items(options)
15
+ collection :_self, options
16
+ end
17
+ end
18
+
19
+
20
+ def create_representation_with(doc, options, format)
21
+ bin = representable_bindings_for(format).first
22
+ bin.serialize_for(self)
23
+ end
24
+
25
+ def update_properties_from(doc, options, format)
26
+ bin = representable_bindings_for(format).first
27
+ value = bin.deserialize_from(doc)
28
+ replace(value)
29
+ end
30
+
31
+ # FIXME: refactor Definition so we can simply add options in #items to existing definition.
32
+ def representable_attrs
33
+ attrs = super
34
+ attrs << Definition.new(:_self, :collection => true) if attrs.size == 0
35
+ attrs
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module Representable::XML
2
+ module Hash
3
+ include Representable::XML
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include Representable
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+
13
+ module ClassMethods
14
+ def values(options)
15
+ hash :_self, options
16
+ end
17
+ end
18
+
19
+
20
+ def create_representation_with(doc, options, format)
21
+ bin = representable_bindings_for(format).first
22
+ bin.serialize_for(self)
23
+ end
24
+
25
+ def update_properties_from(doc, options, format)
26
+ bin = representable_bindings_for(format).first
27
+ value = bin.deserialize_from(doc)
28
+ replace(value)
29
+ end
30
+
31
+ # FIXME: refactor Definition so we can simply add options in #items to existing definition.
32
+ def representable_attrs
33
+ attrs = super
34
+ attrs << Definition.new(:_self, :hash => true) if attrs.size == 0
35
+ attrs
36
+ end
37
+ end
38
+ end
@@ -13,9 +13,18 @@ class DefinitionTest < MiniTest::Spec
13
13
  end
14
14
  end
15
15
 
16
- it "responds to #typed?" do
17
- assert ! @def.typed?
18
- assert Representable::Definition.new(:songs, :class => Hash).typed?
16
+ describe "#typed?" do
17
+ it "is false per default" do
18
+ assert ! @def.typed?
19
+ end
20
+
21
+ it "is true when :class is present" do
22
+ assert Representable::Definition.new(:songs, :class => Hash).typed?
23
+ end
24
+
25
+ it "is true when :extend is present, only" do
26
+ assert Representable::Definition.new(:songs, :extend => Hash).typed?
27
+ end
19
28
  end
20
29
 
21
30
  it "responds to #getter and returns string" do
@@ -26,10 +35,6 @@ class DefinitionTest < MiniTest::Spec
26
35
  assert_equal "songs", @def.name
27
36
  end
28
37
 
29
- it "responds to #instance_variable_name" do
30
- assert_equal :"@songs", @def.instance_variable_name
31
- end
32
-
33
38
  it "responds to #setter" do
34
39
  assert_equal :"songs=", @def.setter
35
40
  end
@@ -39,23 +44,6 @@ class DefinitionTest < MiniTest::Spec
39
44
  end
40
45
  end
41
46
 
42
-
43
- describe "#apply" do
44
- it "works with a single item" do
45
- @d = Representable::Definition.new(:song)
46
- assert_equal 2, @d.apply(1) { |v| v+1 }
47
- end
48
-
49
- it "works with collection" do
50
- @d = Representable::Definition.new(:song, :collection => true)
51
- assert_equal [2,3,4], @d.apply([1,2,3]) { |v| v+1 }
52
- end
53
-
54
- it "skips with collection and nil" do
55
- @d = Representable::Definition.new(:song, :collection => true)
56
- assert_equal nil, @d.apply(nil) { |v| v+1 }
57
- end
58
- end
59
47
 
60
48
  describe ":collection => true" do
61
49
  before do
@@ -96,4 +84,15 @@ class DefinitionTest < MiniTest::Spec
96
84
  assert_equal "Atheist Peace", @def.default
97
85
  end
98
86
  end
87
+
88
+ describe ":hash => true" do
89
+ before do
90
+ @def = Representable::Definition.new(:songs, :hash => true)
91
+ end
92
+
93
+ it "responds to #hash?" do
94
+ assert @def.hash?
95
+ assert ! Representable::Definition.new(:songs).hash?
96
+ end
97
+ end
99
98
  end
@@ -0,0 +1,119 @@
1
+ require 'test_helper'
2
+ require 'representable/json'
3
+
4
+ class JSONBindingTest < MiniTest::Spec
5
+ module SongRepresenter
6
+ include Representable::JSON
7
+ property :name
8
+ end
9
+
10
+ class SongWithRepresenter < ::Song
11
+ include Representable
12
+ include SongRepresenter
13
+ end
14
+
15
+
16
+ describe "PropertyBinding" do
17
+ describe "with plain text" do
18
+ before do
19
+ @property = Representable::JSON::PropertyBinding.new(Representable::Definition.new(:song))
20
+ end
21
+
22
+ it "extracts with #read" do
23
+ assert_equal "Thinning the Herd", @property.read("song" => "Thinning the Herd")
24
+ end
25
+
26
+ it "inserts with #write" do
27
+ doc = {}
28
+ assert_equal("Thinning the Herd", @property.write(doc,"Thinning the Herd"))
29
+ assert_equal({"song"=>"Thinning the Herd"}, doc)
30
+ end
31
+ end
32
+
33
+ describe "with an object" do
34
+ before do
35
+ @property = Representable::JSON::PropertyBinding.new(Representable::Definition.new(:song, :class => SongWithRepresenter))
36
+ @doc = {}
37
+ end
38
+
39
+ it "extracts with #read" do
40
+ assert_equal SongWithRepresenter.new("Thinning the Herd"), @property.read("song" => {"name" => "Thinning the Herd"})
41
+ end
42
+
43
+ it "inserts with #write" do
44
+ assert_equal({"name"=>"Thinning the Herd"}, @property.write(@doc, SongWithRepresenter.new("Thinning the Herd")))
45
+ assert_equal({"song" => {"name"=>"Thinning the Herd"}}, @doc)
46
+ end
47
+ end
48
+
49
+ describe "with an object and :extend" do
50
+ before do
51
+ @property = Representable::JSON::PropertyBinding.new(Representable::Definition.new(:song, :class => Song, :extend => SongRepresenter))
52
+ @doc = {}
53
+ end
54
+
55
+ it "extracts with #read" do
56
+ assert_equal Song.new("Thinning the Herd"), @property.read("song" => {"name" => "Thinning the Herd"})
57
+ end
58
+
59
+ it "inserts with #write" do
60
+ assert_equal({"name"=>"Thinning the Herd"}, @property.write(@doc, Song.new("Thinning the Herd")))
61
+ assert_equal({"song" => {"name"=>"Thinning the Herd"}}, @doc)
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ describe "CollectionBinding" do
68
+ describe "with plain text items" do
69
+ before do
70
+ @property = Representable::JSON::CollectionBinding.new(Representable::Definition.new(:songs, :collection => true))
71
+ end
72
+
73
+ it "extracts with #read" do
74
+ assert_equal ["The Gargoyle", "Bronx"], @property.read("songs" => ["The Gargoyle", "Bronx"])
75
+ end
76
+
77
+ it "inserts with #write" do
78
+ doc = {}
79
+ assert_equal(["The Gargoyle", "Bronx"], @property.write(doc, ["The Gargoyle", "Bronx"]))
80
+ assert_equal({"songs"=>["The Gargoyle", "Bronx"]}, doc)
81
+ end
82
+ end
83
+ end
84
+
85
+
86
+
87
+
88
+ describe "HashBinding" do
89
+ describe "with plain text items" do
90
+ before do
91
+ @property = Representable::JSON::HashBinding.new(Representable::Definition.new(:songs, :hash => true))
92
+ end
93
+
94
+ it "extracts with #read" do
95
+ assert_equal({"first" => "The Gargoyle", "second" => "Bronx"} , @property.read("songs" => {"first" => "The Gargoyle", "second" => "Bronx"}))
96
+ end
97
+
98
+ it "inserts with #write" do
99
+ doc = {}
100
+ assert_equal({"first" => "The Gargoyle", "second" => "Bronx"}, @property.write(doc, {"first" => "The Gargoyle", "second" => "Bronx"}))
101
+ assert_equal({"songs"=>{"first" => "The Gargoyle", "second" => "Bronx"}}, doc)
102
+ end
103
+ end
104
+
105
+ describe "with objects" do
106
+ before do
107
+ @property = Representable::JSON::HashBinding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter))
108
+ end
109
+
110
+ it "doesn't change the represented hash in #write" do
111
+ song = Song.new("Better Than That")
112
+ hash = {"first" => song}
113
+ @property.write({}, hash)
114
+ assert_equal({"first" => song}, hash)
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -133,7 +133,15 @@ module JsonTest
133
133
  end
134
134
 
135
135
  it "returns TextBinding" do
136
- assert_kind_of Json::TextBinding, Json.binding_for_definition(Def.new(:band))
136
+ assert_kind_of Json::PropertyBinding, Json.binding_for_definition(Def.new(:band))
137
+ end
138
+
139
+ it "returns HashBinding" do
140
+ assert_kind_of Json::HashBinding, Json.binding_for_definition(Def.new(:band, :hash => true))
141
+ end
142
+
143
+ it "returns CollectionBinding" do
144
+ assert_kind_of Json::CollectionBinding, Json.binding_for_definition(Def.new(:band, :collection => true))
137
145
  end
138
146
  end
139
147
 
@@ -155,7 +163,7 @@ module JsonTest
155
163
  module AlbumRepresenter
156
164
  include Representable::JSON
157
165
  property :best_song, :class => Song, :extend => SongRepresenter
158
- collection :songs, :class => Song, :extend => SongRepresenter
166
+ collection :songs, :class => Song, :extend => [SongRepresenter]
159
167
  end
160
168
 
161
169
 
@@ -194,7 +202,8 @@ module JsonTest
194
202
  end
195
203
  end
196
204
  end
197
-
205
+
206
+
198
207
  class PropertyTest < MiniTest::Spec
199
208
  describe "property :name" do
200
209
  class Band
@@ -405,4 +414,119 @@ end
405
414
  end
406
415
  end
407
416
  end
417
+
418
+ class HashTest < MiniTest::Spec
419
+ describe "hash :songs" do
420
+ before do
421
+ representer = Module.new do
422
+ include Representable::JSON
423
+ hash :songs
424
+ end
425
+
426
+ class SongList
427
+ attr_accessor :songs
428
+ end
429
+
430
+ @list = SongList.new.extend(representer)
431
+ end
432
+
433
+ it "renders with #to_json" do
434
+ @list.songs = {:one => "65", :two => "Emo Boy"}
435
+ assert_equal "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", @list.to_json
436
+ end
437
+
438
+ it "parses with #from_json" do
439
+ assert_equal({"one" => "65", "two" => ["Emo Boy"]}, @list.from_json("{\"songs\":{\"one\":\"65\",\"two\":[\"Emo Boy\"]}}").songs)
440
+ end
441
+ end
442
+
443
+ end
444
+
445
+
446
+ require 'representable/json/collection'
447
+ class CollectionRepresenterTest < MiniTest::Spec
448
+ module SongRepresenter
449
+ include Representable::JSON
450
+ property :name
451
+ end
452
+
453
+ describe "JSON::Collection" do
454
+ describe "with contained objects" do
455
+ before do
456
+ @songs_representer = Module.new do
457
+ include Representable::JSON::Collection
458
+ items :class => Song, :extend => SongRepresenter
459
+ end
460
+ end
461
+
462
+ it "renders objects with #to_json" do
463
+ assert_equal "[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]", [Song.new("Days Go By"), Song.new("Can't Take Them All")].extend(@songs_representer).to_json
464
+ end
465
+
466
+ it "returns objects array from #from_json" do
467
+ assert_equal [Song.new("Days Go By"), Song.new("Can't Take Them All")], [].extend(@songs_representer).from_json("[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]")
468
+ end
469
+ end
470
+
471
+ describe "with contained text" do
472
+ before do
473
+ @songs_representer = Module.new do
474
+ include Representable::JSON::Collection
475
+ end
476
+ end
477
+
478
+ it "renders contained items #to_json" do
479
+ assert_equal "[\"Days Go By\",\"Can't Take Them All\"]", ["Days Go By", "Can't Take Them All"].extend(@songs_representer).to_json
480
+ end
481
+
482
+ it "returns objects array from #from_json" do
483
+ assert_equal ["Days Go By", "Can't Take Them All"], [].extend(@songs_representer).from_json("[\"Days Go By\",\"Can't Take Them All\"]")
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+
490
+ require 'representable/json/hash'
491
+ class HashRepresenterTest < MiniTest::Spec
492
+ module SongRepresenter
493
+ include Representable::JSON
494
+ property :name
495
+ end
496
+
497
+ describe "JSON::Hash" do
498
+ describe "with contained objects" do
499
+ before do
500
+ @songs_representer = Module.new do
501
+ include Representable::JSON::Hash
502
+ values :class => Song, :extend => SongRepresenter
503
+ end
504
+ end
505
+
506
+ it "renders objects with #to_json" do
507
+ assert_equal "{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(@songs_representer).to_json
508
+ end
509
+
510
+ it "returns objects array from #from_json" do
511
+ assert_equal({"one" => Song.new("Days Go By"), "two" => Song.new("Can't Take Them All")}, {}.extend(@songs_representer).from_json("{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}"))
512
+ end
513
+ end
514
+
515
+ describe "with contained text" do
516
+ before do
517
+ @songs_representer = Module.new do
518
+ include Representable::JSON::Collection
519
+ end
520
+ end
521
+
522
+ it "renders contained items #to_json" do
523
+ assert_equal "[\"Days Go By\",\"Can't Take Them All\"]", ["Days Go By", "Can't Take Them All"].extend(@songs_representer).to_json
524
+ end
525
+
526
+ it "returns objects array from #from_json" do
527
+ assert_equal ["Days Go By", "Can't Take Them All"], [].extend(@songs_representer).from_json("[\"Days Go By\",\"Can't Take Them All\"]")
528
+ end
529
+ end
530
+ end
531
+ end
408
532
  end