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.
- checksums.yaml +4 -4
- data/CHANGES.md +7 -2
- data/Rakefile +6 -0
- data/lib/representable.rb +21 -17
- data/lib/representable/binding.rb +3 -2
- data/lib/representable/definition.rb +1 -1
- data/lib/representable/deprecations.rb +31 -5
- data/lib/representable/deserializer.rb +24 -34
- data/lib/representable/hash/collection.rb +9 -2
- data/lib/representable/hash_methods.rb +2 -2
- data/lib/representable/parse_strategies.rb +6 -7
- data/lib/representable/pipeline.rb +12 -1
- data/lib/representable/pipeline_factories.rb +9 -2
- data/lib/representable/serializer.rb +3 -3
- data/lib/representable/version.rb +1 -1
- data/test-with-deprecations/as_test.rb +65 -0
- data/test-with-deprecations/benchmarking.rb +83 -0
- data/test-with-deprecations/binding_test.rb +46 -0
- data/test-with-deprecations/blaaaaaaaa_test.rb +69 -0
- data/test-with-deprecations/cached_test.rb +147 -0
- data/test-with-deprecations/class_test.rb +119 -0
- data/test-with-deprecations/coercion_test.rb +52 -0
- data/test-with-deprecations/config/inherit_test.rb +135 -0
- data/test-with-deprecations/config_test.rb +122 -0
- data/test-with-deprecations/decorator_scope_test.rb +28 -0
- data/test-with-deprecations/decorator_test.rb +96 -0
- data/test-with-deprecations/default_test.rb +34 -0
- data/test-with-deprecations/defaults_options_test.rb +93 -0
- data/test-with-deprecations/definition_test.rb +264 -0
- data/test-with-deprecations/example.rb +310 -0
- data/test-with-deprecations/examples/object.rb +31 -0
- data/test-with-deprecations/exec_context_test.rb +93 -0
- data/test-with-deprecations/features_test.rb +70 -0
- data/test-with-deprecations/filter_test.rb +57 -0
- data/test-with-deprecations/for_collection_test.rb +74 -0
- data/test-with-deprecations/generic_test.rb +116 -0
- data/test-with-deprecations/getter_setter_test.rb +21 -0
- data/test-with-deprecations/hash_bindings_test.rb +87 -0
- data/test-with-deprecations/hash_test.rb +160 -0
- data/test-with-deprecations/heritage_test.rb +62 -0
- data/test-with-deprecations/if_test.rb +79 -0
- data/test-with-deprecations/include_exclude_test.rb +88 -0
- data/test-with-deprecations/inherit_test.rb +159 -0
- data/test-with-deprecations/inline_test.rb +272 -0
- data/test-with-deprecations/instance_test.rb +266 -0
- data/test-with-deprecations/is_representable_test.rb +77 -0
- data/test-with-deprecations/json_test.rb +355 -0
- data/test-with-deprecations/lonely_test.rb +239 -0
- data/test-with-deprecations/mongoid_test.rb +31 -0
- data/test-with-deprecations/nested_test.rb +115 -0
- data/test-with-deprecations/object_test.rb +60 -0
- data/{test/---deserialize-pipeline_test.rb → test-with-deprecations/parse_pipeline_test.rb} +29 -2
- data/test-with-deprecations/parse_strategy_test.rb +279 -0
- data/{test → test-with-deprecations}/pass_options_test.rb +0 -0
- data/test-with-deprecations/pipeline_test.rb +277 -0
- data/test-with-deprecations/populator_test.rb +105 -0
- data/test-with-deprecations/prepare_test.rb +67 -0
- data/test-with-deprecations/private_options_test.rb +18 -0
- data/test-with-deprecations/reader_writer_test.rb +19 -0
- data/test-with-deprecations/realistic_benchmark.rb +115 -0
- data/test-with-deprecations/render_nil_test.rb +21 -0
- data/test-with-deprecations/represent_test.rb +88 -0
- data/test-with-deprecations/representable_test.rb +511 -0
- data/test-with-deprecations/schema_test.rb +148 -0
- data/test-with-deprecations/serialize_deserialize_test.rb +33 -0
- data/test-with-deprecations/skip_test.rb +81 -0
- data/test-with-deprecations/stringify_hash_test.rb +41 -0
- data/test-with-deprecations/test_helper.rb +135 -0
- data/test-with-deprecations/test_helper_test.rb +25 -0
- data/test-with-deprecations/uncategorized_test.rb +67 -0
- data/test-with-deprecations/user_options_test.rb +15 -0
- data/test-with-deprecations/wrap_test.rb +152 -0
- data/test-with-deprecations/xml_bindings_test.rb +62 -0
- data/test-with-deprecations/xml_test.rb +503 -0
- data/test-with-deprecations/yaml_test.rb +162 -0
- data/test/as_test.rb +3 -3
- data/test/cached_test.rb +2 -2
- data/test/class_test.rb +5 -5
- data/test/exec_context_test.rb +2 -2
- data/test/filter_test.rb +1 -1
- data/test/getter_setter_test.rb +4 -4
- data/test/if_test.rb +2 -2
- data/test/include_exclude_test.rb +88 -0
- data/test/instance_test.rb +15 -15
- data/test/lonely_test.rb +18 -2
- data/test/object_test.rb +4 -4
- data/test/parse_pipeline_test.rb +64 -0
- data/test/parse_strategy_test.rb +3 -3
- data/test/pipeline_test.rb +8 -12
- data/test/prepare_test.rb +2 -3
- data/test/reader_writer_test.rb +3 -3
- data/test/representable_test.rb +12 -48
- data/test/serialize_deserialize_test.rb +9 -9
- data/test/skip_test.rb +11 -11
- data/test/test_helper.rb +2 -0
- data/test/uncategorized_test.rb +10 -10
- data/test/user_options_test.rb +15 -0
- data/test/wrap_test.rb +1 -1
- 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
|