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.
- 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
|