representable 2.4.0.rc3 → 2.4.0.rc4

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +7 -2
  3. data/Rakefile +6 -0
  4. data/lib/representable.rb +21 -17
  5. data/lib/representable/binding.rb +3 -2
  6. data/lib/representable/definition.rb +1 -1
  7. data/lib/representable/deprecations.rb +31 -5
  8. data/lib/representable/deserializer.rb +24 -34
  9. data/lib/representable/hash/collection.rb +9 -2
  10. data/lib/representable/hash_methods.rb +2 -2
  11. data/lib/representable/parse_strategies.rb +6 -7
  12. data/lib/representable/pipeline.rb +12 -1
  13. data/lib/representable/pipeline_factories.rb +9 -2
  14. data/lib/representable/serializer.rb +3 -3
  15. data/lib/representable/version.rb +1 -1
  16. data/test-with-deprecations/as_test.rb +65 -0
  17. data/test-with-deprecations/benchmarking.rb +83 -0
  18. data/test-with-deprecations/binding_test.rb +46 -0
  19. data/test-with-deprecations/blaaaaaaaa_test.rb +69 -0
  20. data/test-with-deprecations/cached_test.rb +147 -0
  21. data/test-with-deprecations/class_test.rb +119 -0
  22. data/test-with-deprecations/coercion_test.rb +52 -0
  23. data/test-with-deprecations/config/inherit_test.rb +135 -0
  24. data/test-with-deprecations/config_test.rb +122 -0
  25. data/test-with-deprecations/decorator_scope_test.rb +28 -0
  26. data/test-with-deprecations/decorator_test.rb +96 -0
  27. data/test-with-deprecations/default_test.rb +34 -0
  28. data/test-with-deprecations/defaults_options_test.rb +93 -0
  29. data/test-with-deprecations/definition_test.rb +264 -0
  30. data/test-with-deprecations/example.rb +310 -0
  31. data/test-with-deprecations/examples/object.rb +31 -0
  32. data/test-with-deprecations/exec_context_test.rb +93 -0
  33. data/test-with-deprecations/features_test.rb +70 -0
  34. data/test-with-deprecations/filter_test.rb +57 -0
  35. data/test-with-deprecations/for_collection_test.rb +74 -0
  36. data/test-with-deprecations/generic_test.rb +116 -0
  37. data/test-with-deprecations/getter_setter_test.rb +21 -0
  38. data/test-with-deprecations/hash_bindings_test.rb +87 -0
  39. data/test-with-deprecations/hash_test.rb +160 -0
  40. data/test-with-deprecations/heritage_test.rb +62 -0
  41. data/test-with-deprecations/if_test.rb +79 -0
  42. data/test-with-deprecations/include_exclude_test.rb +88 -0
  43. data/test-with-deprecations/inherit_test.rb +159 -0
  44. data/test-with-deprecations/inline_test.rb +272 -0
  45. data/test-with-deprecations/instance_test.rb +266 -0
  46. data/test-with-deprecations/is_representable_test.rb +77 -0
  47. data/test-with-deprecations/json_test.rb +355 -0
  48. data/test-with-deprecations/lonely_test.rb +239 -0
  49. data/test-with-deprecations/mongoid_test.rb +31 -0
  50. data/test-with-deprecations/nested_test.rb +115 -0
  51. data/test-with-deprecations/object_test.rb +60 -0
  52. data/{test/---deserialize-pipeline_test.rb → test-with-deprecations/parse_pipeline_test.rb} +29 -2
  53. data/test-with-deprecations/parse_strategy_test.rb +279 -0
  54. data/{test → test-with-deprecations}/pass_options_test.rb +0 -0
  55. data/test-with-deprecations/pipeline_test.rb +277 -0
  56. data/test-with-deprecations/populator_test.rb +105 -0
  57. data/test-with-deprecations/prepare_test.rb +67 -0
  58. data/test-with-deprecations/private_options_test.rb +18 -0
  59. data/test-with-deprecations/reader_writer_test.rb +19 -0
  60. data/test-with-deprecations/realistic_benchmark.rb +115 -0
  61. data/test-with-deprecations/render_nil_test.rb +21 -0
  62. data/test-with-deprecations/represent_test.rb +88 -0
  63. data/test-with-deprecations/representable_test.rb +511 -0
  64. data/test-with-deprecations/schema_test.rb +148 -0
  65. data/test-with-deprecations/serialize_deserialize_test.rb +33 -0
  66. data/test-with-deprecations/skip_test.rb +81 -0
  67. data/test-with-deprecations/stringify_hash_test.rb +41 -0
  68. data/test-with-deprecations/test_helper.rb +135 -0
  69. data/test-with-deprecations/test_helper_test.rb +25 -0
  70. data/test-with-deprecations/uncategorized_test.rb +67 -0
  71. data/test-with-deprecations/user_options_test.rb +15 -0
  72. data/test-with-deprecations/wrap_test.rb +152 -0
  73. data/test-with-deprecations/xml_bindings_test.rb +62 -0
  74. data/test-with-deprecations/xml_test.rb +503 -0
  75. data/test-with-deprecations/yaml_test.rb +162 -0
  76. data/test/as_test.rb +3 -3
  77. data/test/cached_test.rb +2 -2
  78. data/test/class_test.rb +5 -5
  79. data/test/exec_context_test.rb +2 -2
  80. data/test/filter_test.rb +1 -1
  81. data/test/getter_setter_test.rb +4 -4
  82. data/test/if_test.rb +2 -2
  83. data/test/include_exclude_test.rb +88 -0
  84. data/test/instance_test.rb +15 -15
  85. data/test/lonely_test.rb +18 -2
  86. data/test/object_test.rb +4 -4
  87. data/test/parse_pipeline_test.rb +64 -0
  88. data/test/parse_strategy_test.rb +3 -3
  89. data/test/pipeline_test.rb +8 -12
  90. data/test/prepare_test.rb +2 -3
  91. data/test/reader_writer_test.rb +3 -3
  92. data/test/representable_test.rb +12 -48
  93. data/test/serialize_deserialize_test.rb +9 -9
  94. data/test/skip_test.rb +11 -11
  95. data/test/test_helper.rb +2 -0
  96. data/test/uncategorized_test.rb +10 -10
  97. data/test/user_options_test.rb +15 -0
  98. data/test/wrap_test.rb +1 -1
  99. metadata +65 -4
@@ -0,0 +1,93 @@
1
+ require 'test_helper'
2
+
3
+ class DefaultsOptionsTest < BaseTest
4
+ let (:format) { :hash }
5
+ let (:song) { Struct.new(:title, :author_name, :song_volume, :description).new("Revolution", "Some author", 20, nil) }
6
+ let (:prepared) { representer.prepare song }
7
+
8
+ describe "hash options combined with dynamic options" do
9
+ representer! do
10
+ defaults render_nil: true do |name|
11
+ { as: name.to_s.upcase }
12
+ end
13
+
14
+ property :title
15
+ property :author_name
16
+ property :description
17
+ property :song_volume
18
+ end
19
+
20
+ it { render(prepared).must_equal_document({"TITLE" => "Revolution", "AUTHOR_NAME" => "Some author", "DESCRIPTION" => nil, "SONG_VOLUME" => 20}) }
21
+ end
22
+
23
+ describe "with only dynamic property options" do
24
+ representer! do
25
+ defaults do |name|
26
+ { as: name.to_s.upcase }
27
+ end
28
+
29
+ property :title
30
+ property :author_name
31
+ property :description
32
+ property :song_volume
33
+ end
34
+
35
+ it { render(prepared).must_equal_document({"TITLE" => "Revolution", "AUTHOR_NAME" => "Some author", "SONG_VOLUME" => 20}) }
36
+ end
37
+
38
+ describe "with only hashes" do
39
+ representer! do
40
+ defaults render_nil: true
41
+
42
+ property :title
43
+ property :author_name
44
+ property :description
45
+ property :song_volume
46
+ end
47
+
48
+ it { render(prepared).must_equal_document({"title" => "Revolution", "author_name" => "Some author", "description" => nil, "song_volume" => 20}) }
49
+ end
50
+
51
+ describe "direct defaults hash" do
52
+ representer! do
53
+ defaults render_nil: true
54
+
55
+ property :title
56
+ property :author_name
57
+ property :description
58
+ property :song_volume
59
+ end
60
+
61
+ it { render(prepared).must_equal_document({"title" => "Revolution", "author_name" => "Some author", "description" => nil, "song_volume" => 20}) }
62
+ end
63
+
64
+ describe "direct defaults hash with dynamic options" do
65
+ representer! do
66
+ defaults render_nil: true do |name|
67
+ { as: name.to_s.upcase }
68
+ end
69
+
70
+ property :title
71
+ property :author_name
72
+ property :description
73
+ property :song_volume
74
+ end
75
+
76
+ it { render(prepared).must_equal_document({"TITLE" => "Revolution", "AUTHOR_NAME" => "Some author", "DESCRIPTION" => nil, "SONG_VOLUME" => 20}) }
77
+ end
78
+
79
+ describe "prioritizes specific options" do
80
+ representer! do
81
+ defaults render_nil: true do |name|
82
+ { as: name.to_s.upcase }
83
+ end
84
+
85
+ property :title
86
+ property :author_name
87
+ property :description, render_nil: false
88
+ property :song_volume, as: :volume
89
+ end
90
+
91
+ it { render(prepared).must_equal_document({"TITLE" => "Revolution", "AUTHOR_NAME" => "Some author", "volume" => 20}) }
92
+ end
93
+ end
@@ -0,0 +1,264 @@
1
+ require 'test_helper'
2
+
3
+ class DefinitionTest < MiniTest::Spec
4
+ Definition = Representable::Definition
5
+
6
+ # TODO: test that we DON'T clone options, that must happen in
7
+ describe "#initialize" do
8
+ it do
9
+ opts = nil
10
+
11
+ # new yields the defaultized options HASH.
12
+ definition = Definition.new(:song, :extend => Module) do |options|
13
+ options[:awesome] = true
14
+ options[:parse_filter] << 1
15
+
16
+ # default variables
17
+ options[:as].must_equal nil
18
+ options[:extend].must_equal Module
19
+ end
20
+ definition.name.must_equal "song"
21
+
22
+ #
23
+ definition[:awesome].must_equal true
24
+ definition[:parse_filter].must_equal Representable::Pipeline[1]
25
+ definition[:render_filter].must_equal Representable::Pipeline[]
26
+ end
27
+ end
28
+
29
+ describe "#[]" do
30
+ let (:definition) { Definition.new(:song) }
31
+ # default is nil.
32
+ it { definition[:bla].must_equal nil }
33
+ end
34
+
35
+ # merge!
36
+ describe "#merge!" do
37
+ let (:definition) { Definition.new(:song, :whatever => true) }
38
+
39
+ # merges new options.
40
+ it { definition.merge!(:something => true)[:something].must_equal true }
41
+ # doesn't override original options.
42
+ it { definition.merge!({:something => true})[:whatever].must_equal true }
43
+ # override original when passed in #merge!.
44
+ it { definition.merge!({:whatever => false})[:whatever].must_equal false }
45
+
46
+
47
+ it "runs macros" do
48
+ definition[:setter].must_equal nil
49
+ definition.merge!(:parse_strategy => :sync)
50
+ definition[:setter].must_respond_to :evaluate
51
+ end
52
+
53
+ # with block
54
+ it do
55
+ definition = Definition.new(:song, :extend => Module).merge!({:something => true}) do |options|
56
+ options[:awesome] = true
57
+ options[:render_filter] << 1
58
+
59
+ # default variables
60
+ # options[:as].must_equal "song"
61
+ # options[:extend].must_equal Module
62
+ end
63
+
64
+ definition[:awesome].must_equal true
65
+ definition[:something].must_equal true
66
+ definition[:render_filter].must_equal Representable::Pipeline[1]
67
+ definition[:parse_filter].must_equal Representable::Pipeline[]
68
+ end
69
+
70
+ describe "with :parse_filter" do
71
+ let (:definition) { Definition.new(:title, :parse_filter => 1) }
72
+
73
+ # merges :parse_filter and :render_filter.
74
+ it do
75
+ merged = definition.merge!(:parse_filter => 2)[:parse_filter]
76
+
77
+ merged.must_be_kind_of Representable::Pipeline
78
+ merged.size.must_equal 2
79
+ end
80
+
81
+ # :parse_filter can also be array.
82
+ it { definition.merge!(:parse_filter => [2, 3])[:parse_filter].size.must_equal 3 }
83
+ end
84
+
85
+ # does not change arguments
86
+ it do
87
+ Definition.new(:title).merge!(options = {:whatever => 1})
88
+ options.must_equal(:whatever => 1)
89
+ end
90
+ end
91
+
92
+
93
+ # delete!
94
+ describe "#delete!" do
95
+ let (:definition) { Definition.new(:song, serialize: "remove me!") }
96
+
97
+ before { definition[:serialize].evaluate(nil).must_equal "remove me!" }
98
+
99
+ it { definition.delete!(:serialize)[:serialize].must_equal nil }
100
+ end
101
+
102
+ # #inspect
103
+ describe "#inspect" do
104
+ it { Definition.new(:songs).inspect.must_equal "#<Representable::Definition ==>songs @options={:name=>\"songs\", :parse_filter=>[], :render_filter=>[]}>" }
105
+ end
106
+
107
+
108
+ describe "generic API" do
109
+ before do
110
+ @def = Representable::Definition.new(:songs)
111
+ end
112
+
113
+ it "responds to #representer_module" do
114
+ assert_equal nil, Representable::Definition.new(:song).representer_module
115
+ assert_equal Hash, Representable::Definition.new(:song, :extend => Hash).representer_module
116
+ end
117
+
118
+ describe "#typed?" do
119
+ it "is false per default" do
120
+ assert ! @def.typed?
121
+ end
122
+
123
+ it "is true when :class is present" do
124
+ assert Representable::Definition.new(:songs, :class => Hash).typed?
125
+ end
126
+
127
+ it "is true when :extend is present, only" do
128
+ assert Representable::Definition.new(:songs, :extend => Hash).typed?
129
+ end
130
+
131
+ it "is true when :instance is present, only" do
132
+ assert Representable::Definition.new(:songs, :instance => Object.new).typed?
133
+ end
134
+ end
135
+
136
+
137
+ describe "#representable?" do
138
+ it { assert Definition.new(:song, :representable => true).representable? }
139
+ it { Definition.new(:song, :representable => true, :extend => Object).representable?.must_equal true }
140
+ it { refute Definition.new(:song, :representable => false, :extend => Object).representable? }
141
+ it { assert Definition.new(:song, :extend => Object).representable? }
142
+ it { refute Definition.new(:song).representable? }
143
+ end
144
+
145
+
146
+ it "responds to #getter and returns string" do
147
+ assert_equal "songs", @def.getter
148
+ end
149
+
150
+ it "responds to #name" do
151
+ assert_equal "songs", @def.name
152
+ end
153
+
154
+ it "responds to #setter" do
155
+ assert_equal :"songs=", @def.setter
156
+ end
157
+
158
+ describe "nested: FIXME" do
159
+ it do
160
+ dfn = Representable::Definition.new(:songs, nested: Module)
161
+ assert dfn.typed?
162
+ dfn[:extend].(nil).must_equal Module
163
+ end
164
+ end
165
+
166
+
167
+ describe "#clone" do
168
+ subject { Representable::Definition.new(:title, :volume => 9, :clonable => Uber::Options::Value.new(1)) }
169
+
170
+ it { subject.clone.must_be_kind_of Representable::Definition }
171
+ it { subject.clone[:clonable].evaluate(nil).must_equal 1 }
172
+
173
+ it "clones @options" do
174
+ @def.merge!(:volume => 9)
175
+
176
+ cloned = @def.clone
177
+ cloned.merge!(:volume => 8)
178
+
179
+ assert_equal @def[:volume], 9
180
+ assert_equal cloned[:volume], 8
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "#has_default?" do
186
+ it "returns false if no :default set" do
187
+ assert_equal false, Representable::Definition.new(:song).has_default?
188
+ end
189
+
190
+ it "returns true if :default set" do
191
+ assert_equal true, Representable::Definition.new(:song, :default => nil).has_default?
192
+ end
193
+ end
194
+
195
+
196
+ describe "#binding" do
197
+ it "returns true when :binding is set" do
198
+ assert Representable::Definition.new(:songs, :binding => Object)[:binding]
199
+ end
200
+
201
+ it "returns false when :binding is not set" do
202
+ assert !Representable::Definition.new(:songs)[:binding]
203
+ end
204
+ end
205
+
206
+ describe "#create_binding" do
207
+ it "executes the block (without special context)" do
208
+ definition = Representable::Definition.new(:title, :binding => lambda { |*args| @binding = Representable::Binding.new(*args) })
209
+ definition.create_binding.must_equal @binding
210
+ end
211
+ end
212
+
213
+ describe ":collection => true" do
214
+ before do
215
+ @def = Representable::Definition.new(:songs, :collection => true, :tag => :song)
216
+ end
217
+
218
+ it "responds to #array?" do
219
+ assert @def.array?
220
+ end
221
+ end
222
+
223
+
224
+ describe ":default => value" do
225
+ it "responds to #default" do
226
+ @def = Representable::Definition.new(:song)
227
+ assert_equal nil, @def[:default]
228
+ end
229
+
230
+ it "accepts a default value" do
231
+ @def = Representable::Definition.new(:song, :default => "Atheist Peace")
232
+ assert_equal "Atheist Peace", @def[:default]
233
+ end
234
+ end
235
+
236
+ describe ":hash => true" do
237
+ before do
238
+ @def = Representable::Definition.new(:songs, :hash => true)
239
+ end
240
+
241
+ it "responds to #hash?" do
242
+ assert @def.hash?
243
+ assert ! Representable::Definition.new(:songs).hash?
244
+ end
245
+ end
246
+
247
+ describe ":binding => Object" do
248
+ subject do
249
+ Representable::Definition.new(:songs, :binding => Object)
250
+ end
251
+
252
+ it "responds to #binding" do
253
+ assert_equal subject[:binding], Object
254
+ end
255
+ end
256
+
257
+ describe "#[]=" do
258
+ it "raises exception since it's deprecated" do
259
+ assert_raises NoMethodError do
260
+ Definition.new(:title)[:extend] = Module.new # use merge! after initialize.
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,310 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'representable/yaml'
5
+ require 'ostruct'
6
+
7
+ def reset_representer(*module_name)
8
+ module_name.each do |mod|
9
+ mod.module_eval do
10
+ @representable_attrs = nil
11
+ end
12
+ end
13
+ end
14
+
15
+ class Song < OpenStruct
16
+ end
17
+
18
+ song = Song.new(:title => "Fallout", :track => 1)
19
+
20
+ require 'representable/json'
21
+ module SongRepresenter
22
+ include Representable::JSON
23
+
24
+ property :title
25
+ property :track
26
+ end
27
+
28
+ puts song.extend(SongRepresenter).to_json
29
+
30
+ rox = Song.new.extend(SongRepresenter).from_json(%{ {"title":"Roxanne"} })
31
+ puts rox.inspect
32
+
33
+ module SongRepresenter
34
+ include Representable::JSON
35
+
36
+ self.representation_wrap= :hit
37
+
38
+ property :title
39
+ property :track
40
+ end
41
+
42
+ puts song.extend(SongRepresenter).to_json
43
+
44
+
45
+
46
+ ######### collections
47
+
48
+ reset_representer(SongRepresenter)
49
+
50
+ module SongRepresenter
51
+ include Representable::JSON
52
+
53
+ property :title
54
+ property :track
55
+ collection :composers
56
+ end
57
+
58
+
59
+ song = Song.new(:title => "Fallout", :composers => ["Stewart Copeland", "Sting"])
60
+ puts song.extend(SongRepresenter).to_json
61
+
62
+
63
+ ######### nesting types
64
+
65
+ class Album < OpenStruct
66
+ def name
67
+ puts @table.inspect
68
+ #@attributes
69
+ @table[:name]
70
+ end
71
+ end
72
+
73
+ module AlbumRepresenter
74
+ include Representable::JSON
75
+
76
+ property :name
77
+ property :song, :extend => SongRepresenter, :class => Song
78
+ end
79
+
80
+ album = Album.new(:name => "The Police", :song => song)
81
+ puts album.extend(AlbumRepresenter).to_json
82
+
83
+ reset_representer(AlbumRepresenter)
84
+
85
+ module AlbumRepresenter
86
+ include Representable::JSON
87
+
88
+ property :name
89
+ collection :songs, :extend => SongRepresenter, :class => Song
90
+ end
91
+
92
+ album = Album.new(:name => "The Police", :songs => [song, Song.new(:title => "Synchronicity")])
93
+ puts album.extend(AlbumRepresenter).to_json
94
+
95
+
96
+ album = Album.new.extend(AlbumRepresenter).from_json(%{{"name":"Offspring","songs":[{"title":"Genocide"},{"title":"Nitro","composers":["Offspring"]}]}
97
+ })
98
+ puts album.inspect
99
+
100
+ reset_representer(SongRepresenter)
101
+
102
+ ######### using helpers (customizing the rendering/parsing)
103
+ module AlbumRepresenter
104
+ include Representable::JSON
105
+
106
+ def name
107
+ super.upcase
108
+ end
109
+ end
110
+
111
+ puts Album.new(:name => "The Police").
112
+ extend(AlbumRepresenter).to_json
113
+
114
+ reset_representer(SongRepresenter)
115
+
116
+
117
+ ######### inheritance
118
+ module SongRepresenter
119
+ include Representable::JSON
120
+
121
+ property :title
122
+ property :track
123
+ end
124
+
125
+ module CoverSongRepresenter
126
+ include Representable::JSON
127
+ include SongRepresenter
128
+
129
+ property :covered_by
130
+ end
131
+
132
+
133
+ song = Song.new(:title => "Truth Hits Everybody", :covered_by => "No Use For A Name")
134
+ puts song.extend(CoverSongRepresenter).to_json
135
+
136
+
137
+ ### XML
138
+ require 'representable/xml'
139
+ module SongRepresenter
140
+ include Representable::XML
141
+
142
+ property :title
143
+ property :track
144
+ collection :composers
145
+ end
146
+ song = Song.new(:title => "Fallout", :composers => ["Stewart Copeland", "Sting"])
147
+ puts song.extend(SongRepresenter).to_xml
148
+
149
+ reset_representer(SongRepresenter)
150
+
151
+
152
+ ### YAML
153
+ require 'representable/yaml'
154
+ module SongRepresenter
155
+ include Representable::YAML
156
+
157
+ property :title
158
+ property :track
159
+ collection :composers
160
+ end
161
+ puts song.extend(SongRepresenter).to_yaml
162
+
163
+
164
+ SongRepresenter.module_eval do
165
+ @representable_attrs = nil
166
+ end
167
+
168
+
169
+ ### YAML
170
+ module SongRepresenter
171
+ include Representable::YAML
172
+
173
+ property :title
174
+ property :track
175
+ collection :composers, :style => :flow
176
+ end
177
+ puts song.extend(SongRepresenter).to_yaml
178
+
179
+ SongRepresenter.module_eval do
180
+ @representable_attrs = nil
181
+ end
182
+
183
+ # R/W support
184
+ song = Song.new(:title => "You're Wrong", :track => 4)
185
+ module SongRepresenter
186
+ include Representable::Hash
187
+
188
+ property :title, :readable => false
189
+ property :track
190
+ end
191
+ puts song.extend(SongRepresenter).to_hash
192
+
193
+ SongRepresenter.module_eval do
194
+ @representable_attrs = nil
195
+ end
196
+
197
+ module SongRepresenter
198
+ include Representable::Hash
199
+
200
+ property :title, :writeable => false
201
+ property :track
202
+ end
203
+ song = Song.new.extend(SongRepresenter)
204
+ song.from_hash({:title => "Fallout", :track => 1})
205
+ puts song
206
+
207
+ ######### custom methods in representer (using helpers)
208
+ ######### conditions
209
+ ######### :as
210
+ ######### XML::Collection
211
+ ######### polymorphic :extend and :class, instance context!, :instance
212
+ class CoverSong < Song
213
+ end
214
+
215
+ songs = [Song.new(title: "Weirdo", track: 5), CoverSong.new(title: "Truth Hits Everybody", track: 6, copyright: "The Police")]
216
+ album = Album.new(name: "Incognito", songs: songs)
217
+
218
+
219
+ reset_representer(SongRepresenter, AlbumRepresenter)
220
+
221
+ module SongRepresenter
222
+ include Representable::Hash
223
+
224
+ property :title
225
+ property :track
226
+ end
227
+
228
+ module CoverSongRepresenter
229
+ include Representable::Hash
230
+ include SongRepresenter
231
+
232
+ property :copyright
233
+ end
234
+
235
+ module AlbumRepresenter
236
+ include Representable::Hash
237
+
238
+ property :name
239
+ collection :songs, :extend => lambda { |song| song.is_a?(CoverSong) ? CoverSongRepresenter : SongRepresenter }
240
+ end
241
+
242
+ puts album.extend(AlbumRepresenter).to_hash
243
+
244
+ reset_representer(AlbumRepresenter)
245
+
246
+ module AlbumRepresenter
247
+ include Representable::Hash
248
+
249
+ property :name
250
+ collection :songs,
251
+ :extend => lambda { |song| song.is_a?(CoverSong) ? CoverSongRepresenter : SongRepresenter },
252
+ :class => lambda { |hsh| hsh.has_key?("copyright") ? CoverSong : Song } #=> {"title"=>"Weirdo", "track"=>5}
253
+ end
254
+
255
+ album = Album.new.extend(AlbumRepresenter).from_hash({"name"=>"Incognito", "songs"=>[{"title"=>"Weirdo", "track"=>5}, {"title"=>"Truth Hits Everybody", "track"=>6, "copyright"=>"The Police"}]})
256
+ puts album.inspect
257
+
258
+ reset_representer(AlbumRepresenter)
259
+
260
+ module AlbumRepresenter
261
+ include Representable::Hash
262
+
263
+ property :name
264
+ collection :songs,
265
+ :extend => lambda { |song| song.is_a?(CoverSong) ? CoverSongRepresenter : SongRepresenter },
266
+ :instance => lambda { |hsh| hsh.has_key?("copyright") ? CoverSong.new : Song.new(original: true) }
267
+ end
268
+
269
+ album = Album.new.extend(AlbumRepresenter).from_hash({"name"=>"Incognito", "songs"=>[{"title"=>"Weirdo", "track"=>5}, {"title"=>"Truth Hits Everybody", "track"=>6, "copyright"=>"The Police"}]})
270
+ puts album.inspect
271
+
272
+ ######### #hash
273
+
274
+ reset_representer(SongRepresenter)
275
+
276
+ module SongRepresenter
277
+ include Representable::JSON
278
+
279
+ property :title
280
+ hash :ratings
281
+ end
282
+
283
+ puts Song.new(title: "Bliss", ratings: {"Rolling Stone" => 4.9, "FryZine" => 4.5}).extend(SongRepresenter).to_json
284
+
285
+ ######### JSON::Hash
286
+
287
+ module FavoriteSongsRepresenter
288
+ include Representable::JSON::Hash
289
+ end
290
+
291
+ puts( {"Nick" => "Hyper Music", "El" => "Blown In The Wind"}.extend(FavoriteSongsRepresenter).to_json)
292
+
293
+ require 'representable/json/hash'
294
+ module FavoriteSongsRepresenter
295
+ include Representable::JSON::Hash
296
+
297
+ values extend: SongRepresenter, class: Song
298
+ end
299
+
300
+ puts( {"Nick" => Song.new(title: "Hyper Music")}.extend(FavoriteSongsRepresenter).to_json)
301
+
302
+
303
+ require 'representable/json/collection'
304
+ module SongsRepresenter
305
+ include Representable::JSON::Collection
306
+
307
+ items extend: SongRepresenter, class: Song
308
+ end
309
+
310
+ puts [Song.new(title: "Hyper Music"), Song.new(title: "Screenager")].extend(SongsRepresenter).to_json