representable 2.4.0.rc3 → 2.4.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
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