representable 1.8.5 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGES.md +36 -0
  4. data/Gemfile +3 -3
  5. data/README.md +62 -2
  6. data/Rakefile +1 -1
  7. data/lib/representable.rb +32 -109
  8. data/lib/representable/TODO.getting_serious +7 -1
  9. data/lib/representable/autoload.rb +10 -0
  10. data/lib/representable/binding.rb +20 -16
  11. data/lib/representable/bindings/xml_bindings.rb +0 -1
  12. data/lib/representable/coercion.rb +23 -31
  13. data/lib/representable/config.rb +45 -46
  14. data/lib/representable/declarative.rb +78 -0
  15. data/lib/representable/decorator.rb +39 -10
  16. data/lib/representable/definition.rb +40 -33
  17. data/lib/representable/deserializer.rb +2 -0
  18. data/lib/representable/for_collection.rb +25 -0
  19. data/lib/representable/hash.rb +4 -8
  20. data/lib/representable/hash/collection.rb +2 -9
  21. data/lib/representable/hash_methods.rb +0 -7
  22. data/lib/representable/inheritable.rb +50 -0
  23. data/lib/representable/json.rb +3 -9
  24. data/lib/representable/json/collection.rb +1 -3
  25. data/lib/representable/json/hash.rb +4 -9
  26. data/lib/representable/mapper.rb +8 -5
  27. data/lib/representable/parse_strategies.rb +1 -0
  28. data/lib/representable/pipeline.rb +14 -0
  29. data/lib/representable/represent.rb +6 -0
  30. data/lib/representable/version.rb +1 -1
  31. data/lib/representable/xml.rb +3 -18
  32. data/lib/representable/xml/collection.rb +2 -4
  33. data/lib/representable/xml/hash.rb +2 -10
  34. data/lib/representable/yaml.rb +1 -20
  35. data/representable.gemspec +2 -2
  36. data/test/class_test.rb +5 -10
  37. data/test/coercion_test.rb +31 -92
  38. data/test/config/inherit_test.rb +128 -0
  39. data/test/config_test.rb +114 -80
  40. data/test/definition_test.rb +107 -64
  41. data/test/features_test.rb +41 -0
  42. data/test/filter_test.rb +59 -0
  43. data/test/for_collection_test.rb +74 -0
  44. data/test/inherit_test.rb +44 -3
  45. data/test/inheritable_test.rb +97 -0
  46. data/test/inline_test.rb +0 -18
  47. data/test/instance_test.rb +0 -19
  48. data/test/json_test.rb +9 -44
  49. data/test/lonely_test.rb +1 -0
  50. data/test/parse_strategy_test.rb +30 -0
  51. data/test/represent_test.rb +88 -0
  52. data/test/representable_test.rb +3 -50
  53. data/test/schema_test.rb +123 -0
  54. data/test/test_helper.rb +1 -1
  55. data/test/xml_test.rb +34 -38
  56. metadata +25 -15
  57. data/lib/representable/decorator/coercion.rb +0 -4
  58. data/lib/representable/readable_writeable.rb +0 -29
  59. data/test/inheritance_test.rb +0 -22
@@ -0,0 +1,123 @@
1
+ require 'test_helper'
2
+
3
+ # Include Inherit Module And Decorator Test
4
+ class SchemaTest < MiniTest::Spec
5
+ module Genre
6
+ include Representable
7
+ property :genre
8
+ end
9
+
10
+ module LinkFeature
11
+ def self.included(base)
12
+ base.extend(Link)
13
+ end
14
+
15
+ module Link
16
+ def link
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ module Module
23
+ include Representable::Hash
24
+ feature LinkFeature
25
+
26
+ property :title
27
+ property :label do # extend: LabelModule
28
+ property :name
29
+ link # feature
30
+
31
+ property :location do
32
+ property :city
33
+ link # feature.
34
+ end
35
+ end
36
+
37
+ property :album, :extend => lambda { raise "don't manifest me!" } # this is not an inline decorator, don't manifest it.
38
+
39
+
40
+ include Genre # Schema::Included::included is called!
41
+ end
42
+
43
+
44
+ class WithLocationStreetRepresenter < Representable::Decorator
45
+ include Representable::Hash
46
+ feature LinkFeature
47
+
48
+ property :title
49
+ property :label do # extend: LabelModule
50
+ property :name
51
+ link # feature
52
+
53
+ property :location do
54
+ property :city
55
+ link # feature.
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "3-level deep with features" do
61
+ let (:label) { OpenStruct.new(:name => "Epitaph", :location => OpenStruct.new(:city => "Sanfran", :name => "DON'T SHOW ME!")) }
62
+
63
+ # Module does correctly include features in inlines.
64
+ it { band.extend(Module).to_hash.must_equal({"label"=>{"name"=>"Epitaph", "location"=>{"city"=>"Sanfran"}}, "genre"=>"Punkrock"}) }
65
+
66
+ # Decorator does correctly include features in inlines.
67
+ it { Decorator.new(band).to_hash.must_equal({"label"=>{"name"=>"Epitaph", "location"=>{"city"=>"Sanfran"}}, "genre"=>"Punkrock"}) }
68
+ end
69
+
70
+
71
+
72
+ class Decorator < Representable::Decorator
73
+ feature Representable::Hash
74
+
75
+ include Module
76
+ end
77
+
78
+ # puts Decorator.representable_attrs[:definitions].inspect
79
+
80
+ let (:label) { OpenStruct.new(:name => "Fat Wreck", :city => "San Francisco", :employees => [OpenStruct.new(:name => "Mike")], :location => OpenStruct.new(:city => "Sanfran")) }
81
+ let (:band) { OpenStruct.new(:genre => "Punkrock", :label => label) }
82
+
83
+
84
+ # it { FlatlinersDecorator.new( OpenStruct.new(label: OpenStruct.new) ).
85
+ # to_hash.must_equal({}) }
86
+ it do
87
+ Decorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "location"=>{"city"=>"Sanfran"}}})
88
+ end
89
+
90
+
91
+ class InheritDecorator < Representable::Decorator
92
+ include Representable::Hash
93
+
94
+ include Module
95
+
96
+ property :label, inherit: true do # decorator.rb:27:in `initialize': superclass must be a Class (Module given)
97
+ property :city
98
+
99
+ property :location, :inherit => true do
100
+ property :city
101
+ end
102
+ end
103
+ end
104
+
105
+ it do
106
+ InheritDecorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "city"=>"San Francisco", "location"=>{"city"=>"Sanfran"}}})
107
+ end
108
+
109
+
110
+
111
+ class InheritFromDecorator < InheritDecorator
112
+
113
+ property :label, inherit: true do
114
+ collection :employees do
115
+ property :name
116
+ end
117
+ end
118
+ end
119
+
120
+ it do
121
+ InheritFromDecorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "city"=>"San Francisco", "employees"=>[{"name"=>"Mike"}], "location"=>{"city"=>"Sanfran"}}})
122
+ end
123
+ end
@@ -19,7 +19,7 @@ class Album
19
19
  end
20
20
 
21
21
  class Song
22
- attr_accessor :name, :track
22
+ attr_accessor :name, :track # never change this, track rendered with Rails#to_json.
23
23
  def initialize(name=nil, track=nil)
24
24
  @name = name
25
25
  @track = track
@@ -34,40 +34,6 @@ class XmlTest < MiniTest::Spec
34
34
  end
35
35
 
36
36
 
37
- describe ".from_xml" do
38
- it "is delegated to #from_xml" do
39
- block = lambda {|*args|}
40
- @Band.any_instance.expects(:from_xml).with("<document>", "options") # FIXME: how to NOT expect block?
41
- @Band.from_xml("<document>", "options", &block)
42
- end
43
-
44
- it "yields new object and options to block" do
45
- @Band.class_eval { attr_accessor :new_name }
46
- @band = @Band.from_xml("<band/>", :new_name => "Diesel Boy") do |band, options|
47
- band.new_name= options[:new_name]
48
- end
49
- assert_equal "Diesel Boy", @band.new_name
50
- end
51
- end
52
-
53
-
54
- describe ".from_node" do
55
- it "is delegated to #from_node" do
56
- block = lambda {|*args|}
57
- @Band.any_instance.expects(:from_node).with("<document>", "options") # FIXME: how to expect block?
58
- @Band.from_node("<document>", "options", &block)
59
- end
60
-
61
- it "yields new object and options to block" do
62
- @Band.class_eval { attr_accessor :new_name }
63
- @band = @Band.from_node(Nokogiri::XML("<band/>"), :new_name => "Diesel Boy") do |band, options|
64
- band.new_name= options[:new_name]
65
- end
66
- assert_equal "Diesel Boy", @band.new_name
67
- end
68
- end
69
-
70
-
71
37
  describe "#from_xml" do
72
38
  before do
73
39
  @band = @Band.new
@@ -222,7 +188,7 @@ class AttributesTest < MiniTest::Spec
222
188
  end
223
189
 
224
190
  it "#from_xml creates correct accessors" do
225
- link = Link.from_xml(%{
191
+ link = Link.new.from_xml(%{
226
192
  <a href="http://apotomo.de" title="Home, sweet home" />
227
193
  })
228
194
  assert_equal "http://apotomo.de", link.href
@@ -238,13 +204,29 @@ class AttributesTest < MiniTest::Spec
238
204
  end
239
205
  end
240
206
 
207
+
208
+ class CDataBand
209
+ class CData < Representable::XML::PropertyBinding
210
+ def serialize_node(parent, value)
211
+ parent << Nokogiri::XML::CDATA.new(parent, represented.name)
212
+ end
213
+ end
214
+
215
+ include Representable::XML
216
+ property :name, :binding => lambda { |*args| CData.new(*args) }#getter: lambda { |opt| Nokogiri::XML::CDATA.new(opt[:doc], name) }
217
+ attr_accessor :name
218
+
219
+ def initialize(name=nil)
220
+ name and self.name = name
221
+ end
222
+ end
223
+
241
224
  class TypedPropertyTest < MiniTest::Spec
242
225
  module AlbumRepresenter
243
226
  include Representable::XML
244
227
  property :band, :class => Band
245
228
  end
246
229
 
247
-
248
230
  class Album
249
231
  attr_accessor :band
250
232
  def initialize(band=nil)
@@ -288,6 +270,19 @@ class TypedPropertyTest < MiniTest::Spec
288
270
  assert_xml_equal %{<album><band>Baaaad Religion</band></album>}, Album.new(band).extend(AlbumRepresenter).to_xml
289
271
  end
290
272
  end
273
+
274
+ describe "#to_xml with CDATA" do
275
+ it "wraps Band name in CDATA#to_xml" do
276
+ band = CDataBand.new("Bad Religion")
277
+ album = Album.new(band).extend(AlbumRepresenter)
278
+
279
+ assert_xml_equal %{<album>
280
+ <c_data_band>
281
+ <name><![CDATA[Bad Religion]]></name>
282
+ </c_data_band>
283
+ </album>}, album.to_xml
284
+ end
285
+ end
291
286
  end
292
287
  end
293
288
 
@@ -302,7 +297,7 @@ class CollectionTest < MiniTest::Spec
302
297
 
303
298
  describe "#from_xml" do
304
299
  it "pushes collection items to array" do
305
- cd = Compilation.from_xml(%{
300
+ cd = Compilation.new.from_xml(%{
306
301
  <compilation>
307
302
  <band><name>Diesel Boy</name></band>
308
303
  <band><name>Cobra Skulls</name></band>
@@ -390,9 +385,10 @@ class CollectionTest < MiniTest::Spec
390
385
  module SongRepresenter
391
386
  include Representable::XML
392
387
  property :name
388
+ self.representation_wrap = :song
393
389
  end
394
390
 
395
- let (:decorator) { rpr = representer; Class.new(Representable::Decorator) { include rpr; self.representation_wrap= :songs } } # FIXME: why isn't representation wrap inherited properly?
391
+ let (:decorator) { rpr = representer; Class.new(Representable::Decorator) { include rpr } }
396
392
 
397
393
  describe "XML::Collection" do
398
394
  describe "with contained objects" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: representable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.5
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-11 00:00:00.000000000 Z
11
+ date: 2014-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: uber
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.0.7
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.0.7
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -126,16 +126,16 @@ dependencies:
126
126
  name: virtus
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ~>
129
+ - - '>='
130
130
  - !ruby/object:Gem::Version
131
- version: 0.5.0
131
+ version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ~>
136
+ - - '>='
137
137
  - !ruby/object:Gem::Version
138
- version: 0.5.0
138
+ version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: json
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -168,26 +168,30 @@ files:
168
168
  - TODO
169
169
  - lib/representable.rb
170
170
  - lib/representable/TODO.getting_serious
171
+ - lib/representable/autoload.rb
171
172
  - lib/representable/binding.rb
172
173
  - lib/representable/bindings/hash_bindings.rb
173
174
  - lib/representable/bindings/xml_bindings.rb
174
175
  - lib/representable/bindings/yaml_bindings.rb
175
176
  - lib/representable/coercion.rb
176
177
  - lib/representable/config.rb
178
+ - lib/representable/declarative.rb
177
179
  - lib/representable/decorator.rb
178
- - lib/representable/decorator/coercion.rb
179
180
  - lib/representable/definition.rb
180
181
  - lib/representable/deserializer.rb
182
+ - lib/representable/for_collection.rb
181
183
  - lib/representable/hash.rb
182
184
  - lib/representable/hash/allow_symbols.rb
183
185
  - lib/representable/hash/collection.rb
184
186
  - lib/representable/hash_methods.rb
187
+ - lib/representable/inheritable.rb
185
188
  - lib/representable/json.rb
186
189
  - lib/representable/json/collection.rb
187
190
  - lib/representable/json/hash.rb
188
191
  - lib/representable/mapper.rb
189
192
  - lib/representable/parse_strategies.rb
190
- - lib/representable/readable_writeable.rb
193
+ - lib/representable/pipeline.rb
194
+ - lib/representable/represent.rb
191
195
  - lib/representable/serializer.rb
192
196
  - lib/representable/version.rb
193
197
  - lib/representable/xml.rb
@@ -198,19 +202,23 @@ files:
198
202
  - test/as_test.rb
199
203
  - test/class_test.rb
200
204
  - test/coercion_test.rb
205
+ - test/config/inherit_test.rb
201
206
  - test/config_test.rb
202
207
  - test/decorator_scope_test.rb
203
208
  - test/decorator_test.rb
204
209
  - test/definition_test.rb
205
210
  - test/example.rb
206
211
  - test/exec_context_test.rb
212
+ - test/features_test.rb
213
+ - test/filter_test.rb
214
+ - test/for_collection_test.rb
207
215
  - test/generic_test.rb
208
216
  - test/getter_setter_test.rb
209
217
  - test/hash_bindings_test.rb
210
218
  - test/hash_test.rb
211
219
  - test/if_test.rb
212
220
  - test/inherit_test.rb
213
- - test/inheritance_test.rb
221
+ - test/inheritable_test.rb
214
222
  - test/inline_test.rb
215
223
  - test/instance_test.rb
216
224
  - test/is_representable_test.rb
@@ -222,7 +230,9 @@ files:
222
230
  - test/pass_options_test.rb
223
231
  - test/prepare_test.rb
224
232
  - test/reader_writer_test.rb
233
+ - test/represent_test.rb
225
234
  - test/representable_test.rb
235
+ - test/schema_test.rb
226
236
  - test/serialize_deserialize_test.rb
227
237
  - test/stringify_hash_test.rb
228
238
  - test/test_helper.rb
@@ -245,9 +255,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
245
255
  version: '0'
246
256
  required_rubygems_version: !ruby/object:Gem::Requirement
247
257
  requirements:
248
- - - '>='
258
+ - - '>'
249
259
  - !ruby/object:Gem::Version
250
- version: '0'
260
+ version: 1.3.1
251
261
  requirements: []
252
262
  rubyforge_project:
253
263
  rubygems_version: 2.2.2
@@ -1,4 +0,0 @@
1
- require 'representable/coercion'
2
-
3
- # TODO: deprecate for 1.7.
4
- Representable::Decorator::Coercion = Representable::Coercion
@@ -1,29 +0,0 @@
1
- module Representable
2
- module ReadableWriteable
3
- def deserialize_property(binding, doc, options)
4
- return unless binding.writeable?
5
- super
6
- end
7
-
8
- def serialize_property(binding, doc, options)
9
- return unless binding.readable?
10
- super
11
- end
12
- end
13
-
14
-
15
- # TODO: i hate monkey-patching Definition here since it globally adds this options. However, for now this should be ok :-)
16
- Definition.class_eval do
17
- # Checks and returns if the property is writeable
18
- def writeable?
19
- return self[:writeable] if self.has_key?(:writeable)
20
- true
21
- end
22
-
23
- # Checks and returns if the property is readable
24
- def readable?
25
- return self[:readable] if self.has_key?(:readable)
26
- true
27
- end
28
- end
29
- end
@@ -1,22 +0,0 @@
1
- require 'test_helper'
2
-
3
- class InheritanceTest < MiniTest::Spec
4
- let (:decorator) do
5
- Class.new(Representable::Decorator) do
6
- property :title
7
- end
8
- end
9
-
10
- # Decorator.new.representable_attrs != Decorator.representable_attrs
11
- it "doesn't clone for instantiated decorator" do
12
- instance = decorator.new(Object.new)
13
- instance.send(:representable_attrs).first.merge!(:instance => true)
14
-
15
- # we didn't clone and thereby change the original config:
16
- instance.send(:representable_attrs).to_s.must_equal decorator.representable_attrs.to_s
17
- end
18
-
19
- # TODO: ? (performance?)
20
- # more tests on cloning
21
- #
22
- end