representable 2.4.1 → 3.0.0

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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -12
  3. data/CHANGES.md +6 -27
  4. data/README.md +28 -1326
  5. data/lib/representable.rb +4 -14
  6. data/lib/representable/binding.rb +3 -7
  7. data/lib/representable/definition.rb +1 -2
  8. data/lib/representable/populator.rb +35 -0
  9. data/lib/representable/version.rb +1 -1
  10. data/test/definition_test.rb +0 -7
  11. data/test/exec_context_test.rb +2 -2
  12. data/test/instance_test.rb +0 -19
  13. data/test/realistic_benchmark.rb +0 -13
  14. data/test/representable_test.rb +0 -16
  15. data/test/skip_test.rb +1 -1
  16. data/test/test_helper.rb +0 -2
  17. metadata +3 -65
  18. data/lib/representable/deprecations.rb +0 -127
  19. data/lib/representable/parse_strategies.rb +0 -93
  20. data/test-with-deprecations/as_test.rb +0 -65
  21. data/test-with-deprecations/benchmarking.rb +0 -83
  22. data/test-with-deprecations/binding_test.rb +0 -46
  23. data/test-with-deprecations/blaaaaaaaa_test.rb +0 -69
  24. data/test-with-deprecations/cached_test.rb +0 -147
  25. data/test-with-deprecations/class_test.rb +0 -119
  26. data/test-with-deprecations/coercion_test.rb +0 -52
  27. data/test-with-deprecations/config/inherit_test.rb +0 -135
  28. data/test-with-deprecations/config_test.rb +0 -122
  29. data/test-with-deprecations/decorator_scope_test.rb +0 -28
  30. data/test-with-deprecations/decorator_test.rb +0 -96
  31. data/test-with-deprecations/default_test.rb +0 -34
  32. data/test-with-deprecations/defaults_options_test.rb +0 -93
  33. data/test-with-deprecations/definition_test.rb +0 -264
  34. data/test-with-deprecations/example.rb +0 -310
  35. data/test-with-deprecations/examples/object.rb +0 -31
  36. data/test-with-deprecations/exec_context_test.rb +0 -93
  37. data/test-with-deprecations/features_test.rb +0 -70
  38. data/test-with-deprecations/filter_test.rb +0 -57
  39. data/test-with-deprecations/for_collection_test.rb +0 -74
  40. data/test-with-deprecations/generic_test.rb +0 -116
  41. data/test-with-deprecations/getter_setter_test.rb +0 -21
  42. data/test-with-deprecations/hash_bindings_test.rb +0 -87
  43. data/test-with-deprecations/hash_test.rb +0 -160
  44. data/test-with-deprecations/heritage_test.rb +0 -62
  45. data/test-with-deprecations/if_test.rb +0 -79
  46. data/test-with-deprecations/include_exclude_test.rb +0 -88
  47. data/test-with-deprecations/inherit_test.rb +0 -159
  48. data/test-with-deprecations/inline_test.rb +0 -272
  49. data/test-with-deprecations/instance_test.rb +0 -266
  50. data/test-with-deprecations/is_representable_test.rb +0 -77
  51. data/test-with-deprecations/json_test.rb +0 -355
  52. data/test-with-deprecations/lonely_test.rb +0 -239
  53. data/test-with-deprecations/mongoid_test.rb +0 -31
  54. data/test-with-deprecations/nested_test.rb +0 -115
  55. data/test-with-deprecations/object_test.rb +0 -60
  56. data/test-with-deprecations/parse_pipeline_test.rb +0 -64
  57. data/test-with-deprecations/parse_strategy_test.rb +0 -279
  58. data/test-with-deprecations/pass_options_test.rb +0 -27
  59. data/test-with-deprecations/pipeline_test.rb +0 -277
  60. data/test-with-deprecations/populator_test.rb +0 -105
  61. data/test-with-deprecations/prepare_test.rb +0 -67
  62. data/test-with-deprecations/private_options_test.rb +0 -18
  63. data/test-with-deprecations/reader_writer_test.rb +0 -19
  64. data/test-with-deprecations/realistic_benchmark.rb +0 -115
  65. data/test-with-deprecations/render_nil_test.rb +0 -21
  66. data/test-with-deprecations/represent_test.rb +0 -88
  67. data/test-with-deprecations/representable_test.rb +0 -511
  68. data/test-with-deprecations/schema_test.rb +0 -148
  69. data/test-with-deprecations/serialize_deserialize_test.rb +0 -33
  70. data/test-with-deprecations/skip_test.rb +0 -81
  71. data/test-with-deprecations/stringify_hash_test.rb +0 -41
  72. data/test-with-deprecations/test_helper.rb +0 -135
  73. data/test-with-deprecations/test_helper_test.rb +0 -25
  74. data/test-with-deprecations/uncategorized_test.rb +0 -67
  75. data/test-with-deprecations/user_options_test.rb +0 -15
  76. data/test-with-deprecations/wrap_test.rb +0 -152
  77. data/test-with-deprecations/xml_bindings_test.rb +0 -62
  78. data/test-with-deprecations/xml_test.rb +0 -503
  79. data/test-with-deprecations/yaml_test.rb +0 -162
  80. data/test/parse_strategy_test.rb +0 -279
@@ -1,162 +0,0 @@
1
- require 'test_helper'
2
-
3
- class YamlTest < MiniTest::Spec
4
- def self.yaml_representer(&block)
5
- Module.new do
6
- include Representable::YAML
7
- instance_exec &block
8
- end
9
- end
10
-
11
- def yaml_representer(&block)
12
- self.class.yaml_representer(&block)
13
- end
14
-
15
-
16
- describe "property" do
17
- let (:yaml) { yaml_representer do property :best_song end }
18
-
19
- let (:album) { Album.new.tap do |album|
20
- album.best_song = "Liar"
21
- end }
22
-
23
- describe "#to_yaml" do
24
- it "renders plain property" do
25
- album.extend(yaml).to_yaml.must_equal(
26
- "---
27
- best_song: Liar
28
- ")
29
- end
30
-
31
- it "always renders values into strings" do
32
- Album.new.tap { |a| a.best_song = 8675309 }.extend(yaml).to_yaml.must_equal(
33
- "---
34
- best_song: 8675309
35
- "
36
- )
37
- end
38
- end
39
-
40
-
41
- describe "#from_yaml" do
42
- it "parses plain property" do
43
- album.extend(yaml).from_yaml(
44
- "---
45
- best_song: This Song Is Recycled
46
- ").best_song.must_equal "This Song Is Recycled"
47
- end
48
- end
49
-
50
-
51
- describe "with :class and :extend" do
52
- yaml_song = yaml_representer do property :name end
53
- let (:yaml_album) { Module.new do
54
- include Representable::YAML
55
- property :best_song, :extend => yaml_song, :class => Song
56
- end }
57
-
58
- let (:album) { Album.new.tap do |album|
59
- album.best_song = Song.new("Liar")
60
- end }
61
-
62
-
63
- describe "#to_yaml" do
64
- it "renders embedded typed property" do
65
- album.extend(yaml_album).to_yaml.must_equal "---
66
- best_song:
67
- name: Liar
68
- "
69
- end
70
- end
71
-
72
- describe "#from_yaml" do
73
- it "parses embedded typed property" do
74
- album.extend(yaml_album).from_yaml("---
75
- best_song:
76
- name: Go With Me
77
- ").must_equal Album.new(nil,Song.new("Go With Me"))
78
- end
79
- end
80
- end
81
- end
82
-
83
-
84
- describe "collection" do
85
- let (:yaml) { yaml_representer do collection :songs end }
86
-
87
- let (:album) { Album.new.tap do |album|
88
- album.songs = ["Jackhammer", "Terrible Man"]
89
- end }
90
-
91
-
92
- describe "#to_yaml" do
93
- it "renders a block style list per default" do
94
- album.extend(yaml).to_yaml.must_equal "---
95
- songs:
96
- - Jackhammer
97
- - Terrible Man
98
- "
99
- end
100
-
101
- it "renders a flow style list when :style => :flow set" do
102
- yaml = yaml_representer { collection :songs, :style => :flow }
103
- album.extend(yaml).to_yaml.must_equal "---
104
- songs: [Jackhammer, Terrible Man]
105
- "
106
- end
107
- end
108
-
109
-
110
- describe "#from_yaml" do
111
- it "parses a block style list" do
112
- album.extend(yaml).from_yaml("---
113
- songs:
114
- - Off Key Melody
115
- - Sinking").must_equal Album.new(["Off Key Melody", "Sinking"])
116
-
117
- end
118
-
119
- it "parses a flow style list" do
120
- album.extend(yaml).from_yaml("---
121
- songs: [Off Key Melody, Sinking]").must_equal Album.new(["Off Key Melody", "Sinking"])
122
- end
123
- end
124
-
125
-
126
- describe "with :class and :extend" do
127
- let (:yaml_album) { Module.new do
128
- include Representable::YAML
129
- collection :songs, :class => Song do
130
- property :name
131
- property :track
132
- end
133
- end }
134
-
135
- let (:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
136
-
137
-
138
- describe "#to_yaml" do
139
- it "renders collection of typed property" do
140
- album.extend(yaml_album).to_yaml.must_equal "---
141
- songs:
142
- - name: Liar
143
- track: 1
144
- - name: What I Know
145
- track: 2
146
- "
147
- end
148
- end
149
-
150
- describe "#from_yaml" do
151
- it "parses collection of typed property" do
152
- album.extend(yaml_album).from_yaml("---
153
- songs:
154
- - name: One Shot Deal
155
- track: 4
156
- - name: Three Way Dance
157
- track: 5").must_equal Album.new([Song.new("One Shot Deal", 4), Song.new("Three Way Dance", 5)])
158
- end
159
- end
160
- end
161
- end
162
- end
@@ -1,279 +0,0 @@
1
- require 'test_helper'
2
-
3
- # parse_strategy: :sync
4
- # parse_strategy: :replace
5
- # parse_strategy: :find_or_instantiate ("expand" since we don't delete existing unmatched in target)
6
-
7
-
8
- class ParseStrategySyncTest < BaseTest
9
- for_formats(
10
- :hash => [Representable::Hash, {"song"=>{"title"=>"Resist Stance"}}, {"song"=>{"title"=>"Suffer"}}],
11
- :xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><song><title>Suffer</title></song></open_struct>",],
12
- :yaml => [Representable::YAML, "---\nsong:\n title: Resist Stance\n", "---\nsong:\n title: Suffer\n"],
13
- ) do |format, mod, output, input|
14
-
15
- describe "[#{format}] property with parse_strategy: :sync" do # TODO: introduce :representable option?
16
- let (:format) { format }
17
-
18
- representer!(:module => mod, :name => :song_representer) do
19
- property :title
20
- self.representation_wrap = :song if format == :xml
21
- end
22
-
23
- representer!(:inject => :song_representer, :module => mod) do
24
- property :song, :parse_strategy => :sync, :extend => song_representer
25
- end
26
-
27
- let (:hit) { hit = OpenStruct.new(:song => song).extend(representer) }
28
-
29
- it "calls #to_hash on song instance, nothing else" do
30
- render(hit).must_equal_document(output)
31
- end
32
-
33
-
34
- it "calls #from_hash on the existing song instance, nothing else" do
35
- song_id = hit.song.object_id
36
-
37
- parse(hit, input)
38
-
39
- hit.song.title.must_equal "Suffer"
40
- hit.song.object_id.must_equal song_id
41
- end
42
- end
43
- end
44
-
45
- # FIXME: there's a bug with XML and the collection name!
46
- for_formats(
47
- :hash => [Representable::Hash, {"songs"=>[{"title"=>"Resist Stance"}]}, {"songs"=>[{"title"=>"Suffer"}]}],
48
- #:json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"],
49
- :xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><songs><title>Suffer</title></songs></open_struct>"],
50
- :yaml => [Representable::YAML, "---\nsongs:\n- title: Resist Stance\n", "---\nsongs:\n- title: Suffer\n"],
51
- ) do |format, mod, output, input|
52
-
53
- describe "[#{format}] collection with :parse_strategy: :sync" do # TODO: introduce :representable option?
54
- let (:format) { format }
55
- representer!(:module => mod, :name => :song_representer) do
56
- property :title
57
- self.representation_wrap = :song if format == :xml
58
- end
59
-
60
- representer!(:inject => :song_representer, :module => mod) do
61
- collection :songs, :parse_strategy => :sync, :extend => song_representer
62
- end
63
-
64
- let (:album) { OpenStruct.new(:songs => [song]).extend(representer) }
65
-
66
- it "calls #to_hash on song instances, nothing else" do
67
- render(album).must_equal_document(output)
68
- end
69
-
70
- it "calls #from_hash on the existing song instance, nothing else" do
71
- collection_id = album.songs.object_id
72
- song = album.songs.first
73
- song_id = song.object_id
74
-
75
- parse(album, input)
76
-
77
- album.songs.first.title.must_equal "Suffer"
78
- song.title.must_equal "Suffer"
79
- #album.songs.object_id.must_equal collection_id # TODO: don't replace!
80
- song.object_id.must_equal song_id
81
- end
82
- end
83
- end
84
-
85
-
86
- # Sync errors, when model and incoming are not in sync.
87
- describe ":sync with error" do
88
- representer! do
89
- property :song, :parse_strategy => :sync do
90
- property :title
91
- end
92
- end
93
-
94
- # object.song is nil whereas the document contains one.
95
- it do
96
- assert_raises Representable::DeserializeError do
97
- OpenStruct.new.extend(representer).from_hash({"song" => {"title" => "Perpetual"}})
98
- end
99
- end
100
- end
101
-
102
-
103
-
104
- # Lonely Collection
105
- for_formats(
106
- :hash => [Representable::Hash::Collection, [{"title"=>"Resist Stance"}], [{"title"=>"Suffer"}]],
107
- # :xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><songs><title>Suffer</title></songs></open_struct>"],
108
- ) do |format, mod, output, input|
109
-
110
- describe "[#{format}] lonely collection with :parse_strategy: :sync" do # TODO: introduce :representable option?
111
- let (:format) { format }
112
- representer!(:module => Representable::Hash, :name => :song_representer) do
113
- property :title
114
- self.representation_wrap = :song if format == :xml
115
- end
116
-
117
- representer!(:inject => :song_representer, :module => mod) do
118
- items :parse_strategy => :sync, :extend => song_representer
119
- end
120
-
121
- let (:album) { [song].extend(representer) }
122
-
123
- it "calls #to_hash on song instances, nothing else" do
124
- render(album).must_equal_document(output)
125
- end
126
-
127
- it "calls #from_hash on the existing song instance, nothing else" do
128
- #collection_id = album.object_id
129
- song = album.first
130
- song_id = song.object_id
131
-
132
- parse(album, input)
133
-
134
- album.first.title.must_equal "Suffer"
135
- song.title.must_equal "Suffer"
136
- song.object_id.must_equal song_id
137
- end
138
- end
139
- end
140
- end
141
-
142
-
143
- class ParseStrategyFindOrInstantiateTest < BaseTest
144
- # parse_strategy: :find_or_instantiate
145
-
146
- Song = Struct.new(:id, :title)
147
- Song.class_eval do
148
- def self.find_by(attributes={})
149
- return new(1, "Resist Stan") if attributes[:id]==1# we should return the same object here
150
- new
151
- end
152
- end
153
-
154
- representer!(:name => :song_representer) do
155
- property :title
156
- end
157
-
158
-
159
- describe "collection" do
160
- representer!(:inject => :song_representer) do
161
- collection :songs, :parse_strategy => :find_or_instantiate, :extend => song_representer, :class => Song
162
- end
163
-
164
- let (:album) { Struct.new(:songs).new([]).extend(representer) }
165
-
166
-
167
- it "replaces the existing collection with a new consisting of existing items or new items" do
168
- songs_id = album.songs.object_id
169
-
170
- album.from_hash({"songs"=>[{"id" => 1, "title"=>"Resist Stance"}, {"title"=>"Suffer"}]})
171
-
172
- album.songs[0].title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
173
- album.songs[0].id.must_equal 1
174
- album.songs[1].title.must_equal "Suffer"
175
- album.songs[1].id.must_equal nil
176
-
177
- album.songs.object_id.wont_equal songs_id
178
- end
179
-
180
- # TODO: test with existing collection
181
- end
182
-
183
-
184
- describe "property" do
185
- representer!(:inject => :song_representer) do
186
- property :song, :parse_strategy => :find_or_instantiate, :extend => song_representer, :class => Song
187
- end
188
-
189
- let (:album) { Struct.new(:song).new.extend(representer) }
190
-
191
-
192
- it "finds song by id" do
193
- album.from_hash({"song"=>{"id" => 1, "title"=>"Resist Stance"}})
194
-
195
- album.song.title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
196
- album.song.id.must_equal 1
197
- end
198
-
199
- it "creates song" do
200
- album.from_hash({"song"=>{"title"=>"Off The Track"}})
201
-
202
- album.song.title.must_equal "Off The Track"
203
- album.song.id.must_equal nil
204
- end
205
- end
206
-
207
-
208
- describe "property with dynamic :class" do
209
- representer!(:inject => :song_representer) do
210
- property :song, :parse_strategy => :find_or_instantiate, :extend => song_representer,
211
- :class => lambda { |options| options[:fragment]["class"] }
212
- end
213
-
214
- let (:album) { Struct.new(:song).new.extend(representer) }
215
-
216
-
217
- it "finds song by id" do
218
- album.from_hash({"song"=>{"id" => 1, "title"=>"Resist Stance", "class"=>Song}})
219
-
220
- album.song.title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
221
- album.song.id.must_equal 1
222
- end
223
- end
224
- end
225
-
226
-
227
- class ParseStrategyLambdaTest < MiniTest::Spec
228
- Song = Struct.new(:id, :title)
229
- Song.class_eval do
230
- def self.find_by(attributes={})
231
- return new(1, "Resist Stan") if attributes[:id]==1# we should return the same object here
232
- new
233
- end
234
- end
235
-
236
- representer!(:name => :song_representer) do
237
- property :title
238
- end
239
-
240
- # property with instance: lambda, using representable's setter. # TODO: that should be handled better via my api.
241
- describe "property parse_strategy: lambda, representable: false" do
242
- representer! do
243
- property :title,
244
- :instance => lambda { |options| options[:fragment].to_s }, # this will still call song.title= "8675309".
245
- :representable => false # don't call object.from_hash
246
- end
247
-
248
- let (:song) { Song.new(nil, nil) }
249
- it { song.extend(representer).from_hash("title" => 8675309).title.must_equal "8675309" }
250
- end
251
-
252
-
253
- describe "collection" do
254
- representer!(:inject => :song_representer) do
255
- collection :songs, :parse_strategy => lambda { |options|
256
- songs << song = Song.new
257
- song
258
- }, :extend => song_representer
259
- end
260
-
261
- let (:album) { Struct.new(:songs).new([Song.new(1, "A Walk")]).extend(representer) }
262
-
263
-
264
- it "adds to existing collection" do
265
- songs_id = album.songs.object_id
266
-
267
- album.from_hash({"songs"=>[{"title"=>"Resist Stance"}]})
268
-
269
- album.songs[0].title.must_equal "A Walk" # note how title is updated from "Resist Stan"
270
- album.songs[0].id.must_equal 1
271
- album.songs[1].title.must_equal "Resist Stance"
272
- album.songs[1].id.must_equal nil
273
-
274
- album.songs.object_id.must_equal songs_id
275
- end
276
-
277
- # TODO: test with existing collection
278
- end
279
- end