representable 1.8.0 → 1.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b00de985635f525b8a01171885aed414e6204034
4
- data.tar.gz: dc62dd3c718b5969a663da9587ef815ddb4eb6e8
3
+ metadata.gz: 4966e0bd638ff12a23976fed58fab076e5912e20
4
+ data.tar.gz: 4ca036c615f0e656d8268cdb1bf74918f1d9476a
5
5
  SHA512:
6
- metadata.gz: 9a7cc3fb19f4319e69cbf66e566ae70b9a8ede10bc5b9666756128ab7795eec2c35315f31603ff3ad3fa8b78ac170270389ba33e128b6848496d45fd1cec615f
7
- data.tar.gz: d2eb8e52c0485aebea0fe956fa98ef9d9c06f87a8d00a0d027dbea804b573982b364d1bcc06f3db65bbeb33e89e814a594300302675776be11024ce335569d69
6
+ metadata.gz: b2f875cda0fde3869bb592317de279ba4c92fb6e29b46685ed4908313bd43dab6a9614e9af6413368940ccad9e61dd7339fc0d325e1fdba9211906eb4ab40850
7
+ data.tar.gz: fb9e3c1d669e7219ee57451e5d5302ef41b770a6dea11f73c7699528de4a01ad3a0df6da4f8abb8cf9f691de1da94a9f92fa9014f74d4a3ec4f51366dbfead51
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 1.8.1
2
+
3
+ * Add `:serialize` and `:deserialize` options for overriding those steps.
4
+
1
5
  # 1.8.0
2
6
 
3
7
  ## Major Breakage
@@ -17,6 +21,7 @@
17
21
 
18
22
  * When unsure about the number of arguments passed into an option lambda, use `:pass_options`. This passes all general options in a dedicated `Options` object that responds to `binding`, `decorator`, `represented` and `user_options`. It's always the last argument for the block.
19
23
  * Added `parse_strategy: :find_or_instantiate`. More to come.
24
+ * Added `parse_strategy: lambda { |fragment, i, options| }` to implement your own deserialization.
20
25
  * Use `representable: false` to prevent calling `to_*/from_*` on a represented object even if the property is `typed?` (`:extend`, `:class` or `:instance` set).
21
26
  * Introduced `:use_decorator` option to force an inline representer to be implemented with a Decorator even in a module. This fixes a bug since we used the `:decorate` option in earlier versions, which was already used for something else.
22
27
  * Autoload `Representable::Hash*` and `Representable::Decorator`.
data/README.md CHANGED
@@ -125,10 +125,10 @@ end
125
125
  Surprisingly, `#collection` lets us define lists of objects to represent.
126
126
 
127
127
  ```ruby
128
- Song.new(title: "Fallout", composers: ["Steward Copeland", "Sting"]).
128
+ Song.new(title: "Fallout", composers: ["Stewart Copeland", "Sting"]).
129
129
  extend(SongRepresenter).to_json
130
130
 
131
- #=> {"title":"Fallout","composers":["Steward Copeland","Sting"]}
131
+ #=> {"title":"Fallout","composers":["Stewart Copeland","Sting"]}
132
132
  ```
133
133
 
134
134
  And again, this works both ways - in addition to the title it extracts the composers from the document, too.
@@ -162,7 +162,7 @@ When rendering, the `:extend` module is used to extend the attribute(s) with the
162
162
 
163
163
  ```ruby
164
164
  album.extend(AlbumRepresenter).to_json
165
- #=> {"name":"The Police","songs":[{"title":"Fallout","composers":["Steward Copeland","Sting"]},{"title":"Synchronicity","composers":[]}]}
165
+ #=> {"name":"The Police","songs":[{"title":"Fallout","composers":["Stewart Copeland","Sting"]},{"title":"Synchronicity","composers":[]}]}
166
166
  ```
167
167
 
168
168
  Parsing a documents needs both `:extend` and the `:class` option as the parser requires knowledge what kind of object to create from the nested composition.
@@ -453,6 +453,8 @@ Here's a list of all dynamic options and their argument signature.
453
453
  * `writer: lambda { |document, args| }` ([see Read And Write](#overriding-read-and-write))
454
454
  * `if: lambda { |args| }` ([see Conditions](#conditions))
455
455
  * `prepare: lambda { |object, args| }` ([see docs](#rendering-and-parsing-without-extend))
456
+ * `serialize: lambda { |object, args| }` ([see docs](#overriding-serialize-and-deserialize))
457
+ * `deserialize: lambda { |object, fragment, args| }` ([see docs](#overriding-serialize-and-deserialize))
456
458
  * `representation_wrap` is a dynamic option, too: `self.representation_wrap = lambda do { |args| }` ([see Wrapping](#wrapping))
457
459
 
458
460
 
@@ -491,11 +493,11 @@ end
491
493
  For XML we just include the `Representable::XML` module.
492
494
 
493
495
  ```xml
494
- Song.new(title: "Fallout", composers: ["Steward Copeland", "Sting"]).
496
+ Song.new(title: "Fallout", composers: ["Stewart Copeland", "Sting"]).
495
497
  extend(SongRepresenter).to_xml #=>
496
498
  <song>
497
499
  <title>Fallout</title>
498
- <composers>Steward Copeland</composers>
500
+ <composers>Stewart Copeland</composers>
499
501
  <composers>Sting</composers>
500
502
  </song>
501
503
  ```
@@ -823,7 +825,7 @@ song.extend(SongRepresenter).to_yaml
823
825
  #=>
824
826
  ---
825
827
  title: Fallout
826
- composers: [Steward Copeland, Sting]
828
+ composers: [Stewart Copeland, Sting]
827
829
  ```
828
830
 
829
831
  ## More on XML
@@ -992,6 +994,26 @@ If you want `nil` values to be included when rendering, use the `:render_nil` op
992
994
  property :track, render_nil: true
993
995
  ```
994
996
 
997
+
998
+ ### Overriding Serialize And Deserialize
999
+
1000
+ When serializing, the default mechanics after preparing the object are to call `object.to_hash`.
1001
+
1002
+ Override this step with `:serialize`.
1003
+
1004
+ ```ruby
1005
+ property :song, extend: SongRepresenter,
1006
+ serialize: lambda { |object, *args| Marshal.dump(object) }
1007
+ ```
1008
+
1009
+ Vice-versa, parsing allows the same.
1010
+
1011
+ ```ruby
1012
+ property :song, extend: SongRepresenter,
1013
+ deserialize: lambda { |object, fragment, *args| Marshal.load(fragment) }
1014
+ ```
1015
+
1016
+
995
1017
  ## Coercion
996
1018
 
997
1019
  If you fancy coercion when parsing a document you can use the Coercion module which uses [virtus](https://github.com/solnic/virtus) for type conversion.
@@ -135,6 +135,7 @@ module Representable
135
135
  end
136
136
 
137
137
  private
138
+ # DISCUSS: deprecate :class in favour of :instance and simplicity?
138
139
  def class_for(fragment, *args)
139
140
  item_class = class_from(fragment, *args) or return handle_deprecated_class(fragment)
140
141
  item_class.new
@@ -90,7 +90,7 @@ module Representable
90
90
  end
91
91
 
92
92
  def dynamic_options
93
- [:as, :getter, :setter, :class, :instance, :reader, :writer, :extend, :prepare, :if]
93
+ [:as, :getter, :setter, :class, :instance, :reader, :writer, :extend, :prepare, :if, :deserialize, :serialize]
94
94
  end
95
95
 
96
96
  def handle_extend!(options)
@@ -37,7 +37,9 @@ module Representable
37
37
  def deserialize(object, fragment, options) # TODO: merge with #serialize.
38
38
  return object unless @binding.representable?
39
39
 
40
- object.send(@binding.deserialize_method, fragment, options)
40
+ @binding.send(:evaluate_option, :deserialize, object, fragment) do
41
+ object.send(@binding.deserialize_method, fragment, options)
42
+ end
41
43
  end
42
44
 
43
45
  def prepare(object)
@@ -20,7 +20,9 @@ module Representable
20
20
  def serialize(object, user_options)
21
21
  return object unless @binding.representable?
22
22
 
23
- object.send(@binding.serialize_method, user_options.merge!({:wrap => false}))
23
+ @binding.send(:evaluate_option, :serialize, object) do
24
+ object.send(@binding.serialize_method, user_options.merge!({:wrap => false}))
25
+ end
24
26
  end
25
27
  end
26
28
  end
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "1.8.0"
2
+ VERSION = "1.8.1"
3
3
  end
@@ -56,7 +56,7 @@ module SongRepresenter
56
56
  end
57
57
 
58
58
 
59
- song = Song.new(:title => "Fallout", :composers => ["Steward Copeland", "Sting"])
59
+ song = Song.new(:title => "Fallout", :composers => ["Stewart Copeland", "Sting"])
60
60
  puts song.extend(SongRepresenter).to_json
61
61
 
62
62
 
@@ -143,7 +143,7 @@ module SongRepresenter
143
143
  property :track
144
144
  collection :composers
145
145
  end
146
- song = Song.new(:title => "Fallout", :composers => ["Steward Copeland", "Sting"])
146
+ song = Song.new(:title => "Fallout", :composers => ["Stewart Copeland", "Sting"])
147
147
  puts song.extend(SongRepresenter).to_xml
148
148
 
149
149
  reset_representer(SongRepresenter)
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ class SerializeDeserializeTest < BaseTest
4
+ subject { Struct.new(:song).new.extend(representer) }
5
+
6
+ describe "deserialize" do
7
+ representer! do
8
+ property :song,
9
+ :instance => lambda { |fragment, *| fragment.to_s.upcase },
10
+ :prepare => lambda { |fragment, *| fragment }, # TODO: allow false.
11
+ :deserialize => lambda { |object, fragment, args|
12
+ "#{object} #{fragment} #{args.inspect}"
13
+ }
14
+ end
15
+
16
+ it { subject.from_hash({"song" => Object}, {:volume => 9}).song.must_equal "OBJECT Object {:volume=>9}" }
17
+ end
18
+
19
+ describe "serialize" do
20
+ representer! do
21
+ property :song,
22
+ :representable => true,
23
+ :prepare => lambda { |fragment, *| fragment }, # TODO: allow false.
24
+ :serialize => lambda { |object, args|
25
+ "#{object} #{args.inspect}"
26
+ }
27
+ end
28
+
29
+ before { subject.song = "Arrested In Shanghai" }
30
+
31
+ it { subject.to_hash({:volume => 9}).must_equal({"song"=>"Arrested In Shanghai {:volume=>9}"}) }
32
+ end
33
+ end
metadata CHANGED
@@ -1,167 +1,167 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: representable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
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-04-14 00:00:00.000000000 Z
11
+ date: 2014-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: multi_json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: uber
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
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
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: test_xml
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.1.6
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.1.6
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: minitest
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  version: 5.0.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 5.0.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: mocha
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - '>='
102
102
  - !ruby/object:Gem::Version
103
103
  version: 0.13.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.13.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: mongoid
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - '>='
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: virtus
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
131
  version: 0.5.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
138
  version: 0.5.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: yajl-ruby
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - '>='
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - '>='
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: json
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - "~>"
157
+ - - ~>
158
158
  - !ruby/object:Gem::Version
159
159
  version: 1.7.7
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - "~>"
164
+ - - ~>
165
165
  - !ruby/object:Gem::Version
166
166
  version: 1.7.7
167
167
  description: Renders and parses JSON/XML/YAML documents from and to Ruby objects.
@@ -172,8 +172,8 @@ executables: []
172
172
  extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
- - ".gitignore"
176
- - ".travis.yml"
175
+ - .gitignore
176
+ - .travis.yml
177
177
  - CHANGES.md
178
178
  - Gemfile
179
179
  - LICENSE
@@ -236,6 +236,7 @@ files:
236
236
  - test/prepare_test.rb
237
237
  - test/reader_writer_test.rb
238
238
  - test/representable_test.rb
239
+ - test/serialize_deserialize_test.rb
239
240
  - test/stringify_hash_test.rb
240
241
  - test/test_helper.rb
241
242
  - test/test_helper_test.rb
@@ -252,54 +253,19 @@ require_paths:
252
253
  - lib
253
254
  required_ruby_version: !ruby/object:Gem::Requirement
254
255
  requirements:
255
- - - ">="
256
+ - - '>='
256
257
  - !ruby/object:Gem::Version
257
258
  version: '0'
258
259
  required_rubygems_version: !ruby/object:Gem::Requirement
259
260
  requirements:
260
- - - ">="
261
+ - - '>='
261
262
  - !ruby/object:Gem::Version
262
263
  version: '0'
263
264
  requirements: []
264
265
  rubyforge_project:
265
- rubygems_version: 2.2.1
266
+ rubygems_version: 2.0.2
266
267
  signing_key:
267
268
  specification_version: 4
268
269
  summary: Renders and parses JSON/XML/YAML documents from and to Ruby objects. Includes
269
270
  plain properties, collections, nesting, coercion and more.
270
- test_files:
271
- - test/as_test.rb
272
- - test/class_test.rb
273
- - test/coercion_test.rb
274
- - test/config_test.rb
275
- - test/decorator_scope_test.rb
276
- - test/decorator_test.rb
277
- - test/definition_test.rb
278
- - test/example.rb
279
- - test/exec_context_test.rb
280
- - test/generic_test.rb
281
- - test/getter_setter_test.rb
282
- - test/hash_bindings_test.rb
283
- - test/hash_test.rb
284
- - test/if_test.rb
285
- - test/inherit_test.rb
286
- - test/inheritance_test.rb
287
- - test/inline_test.rb
288
- - test/instance_test.rb
289
- - test/is_representable_test.rb
290
- - test/json_test.rb
291
- - test/mongoid_test.rb
292
- - test/nested_test.rb
293
- - test/parse_strategy_test.rb
294
- - test/pass_options_test.rb
295
- - test/prepare_test.rb
296
- - test/reader_writer_test.rb
297
- - test/representable_test.rb
298
- - test/stringify_hash_test.rb
299
- - test/test_helper.rb
300
- - test/test_helper_test.rb
301
- - test/wrap_test.rb
302
- - test/xml_bindings_test.rb
303
- - test/xml_test.rb
304
- - test/yaml_test.rb
305
- has_rdoc:
271
+ test_files: []