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,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 { |fragment, *args| 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 { |fragment, 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 { |fragment, i, 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
@@ -1,27 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PassOptionsTest < BaseTest
4
- let (:format) { :hash }
5
- let (:song) { Struct.new(:title).new("Revolution") }
6
- let (:prepared) { representer.prepare song }
7
-
8
- describe "module" do
9
- representer! do
10
- property :title, :pass_options => true,
11
- :as => lambda { |args| [args.binding.name, args.user_options, args.represented, args.decorator] }
12
- end
13
-
14
- it { render(prepared, :volume => 1).must_equal_document({["title", {:volume=>1}, prepared, prepared] => "Revolution"}) }
15
- # it { parse(prepared, {"args" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
16
- end
17
-
18
- describe "decorator" do
19
- representer!(:decorator => true) do
20
- property :title, :pass_options => true,
21
- :as => lambda { |args| [args.binding.name, args.user_options, args.represented, args.decorator] }
22
- end
23
-
24
- it { render(prepared, :volume => 1).must_equal_document({["title", {:volume=>1}, song, prepared] => "Revolution"}) }
25
- # it { parse(prepared, {"args" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
26
- end
27
- end
@@ -1,277 +0,0 @@
1
- require "test_helper"
2
-
3
- class PipelineTest < MiniTest::Spec
4
- Song = Struct.new(:title, :artist)
5
- Artist = Struct.new(:name)
6
- Album = Struct.new(:ratings, :artists)
7
-
8
- R = Representable
9
- P = R::Pipeline
10
-
11
- Getter = ->(input, options) { "Yo" }
12
- StopOnNil = ->(input, options) { input }
13
- SkipRender = ->(input, *) { input == "Yo" ? input : P::Stop }
14
-
15
- Prepare = ->(input, options) { "Prepare(#{input})" }
16
- Deserialize = ->(input, options) { "Deserialize(#{input}, #{options[:fragment]})" }
17
-
18
- SkipParse = ->(input, options) { input }
19
- CreateObject = ->(input, options) { OpenStruct.new }
20
-
21
-
22
- Setter = ->(input, options) { "Setter(#{input})" }
23
-
24
- AssignFragment = ->(input, options) { options[:fragment] = input }
25
-
26
- it "linear" do
27
- P[SkipParse, Setter].("doc", {fragment: 1}).must_equal "Setter(doc)"
28
-
29
-
30
- # parse style.
31
- P[AssignFragment, SkipParse, CreateObject, Prepare].("Bla", {}).must_equal "Prepare(#<OpenStruct>)"
32
-
33
-
34
- # render style.
35
- P[Getter, StopOnNil, SkipRender, Prepare, Setter].(nil, {}).
36
- must_equal "Setter(Prepare(Yo))"
37
-
38
- # pipeline = Representable::Pipeline[SkipParse , SetResult, ModifyResult]
39
- # pipeline.(fragment: "yo!").must_equal "modified object from yo!"
40
- end
41
-
42
- Stopping = ->(input, options) { return P::Stop if options[:fragment] == "stop!"; input }
43
-
44
-
45
- it "stopping" do
46
-
47
-
48
- pipeline = Representable::Pipeline[SkipParse, Stopping, Prepare]
49
- pipeline.(nil, fragment: "oy!").must_equal "Prepare()"
50
- pipeline.(nil, fragment: "stop!").must_equal Representable::Pipeline::Stop
51
- end
52
-
53
- describe "Collect" do
54
- Reverse = ->(input, options) { input.reverse }
55
- Add = ->(input, options) { "#{input}+" }
56
- let(:pipeline) { R::Collect[Reverse, Add] }
57
-
58
- it { pipeline.(["yo!", "oy!"], {}).must_equal ["!oy+", "!yo+"] }
59
-
60
- describe "Pipeline with Collect" do
61
- let(:pipeline) { P[Reverse, R::Collect[Reverse, Add]] }
62
- it { pipeline.(["yo!", "oy!"], {}).must_equal ["!yo+", "!oy+"] }
63
- end
64
- end
65
-
66
-
67
-
68
-
69
- ######### scalar property
70
-
71
- let (:title) {
72
- dfn = R::Definition.new(:title)
73
-
74
- R::Hash::Binding.new(dfn)
75
- }
76
-
77
- it "rendering scalar property" do
78
- doc = {}
79
- P[
80
- R::GetValue,
81
- R::StopOnSkipable,
82
- R::AssignName,
83
- R::WriteFragment
84
- ].(nil, {represented: Song.new("Lime Green"), binding: title, doc: doc}).must_equal "Lime Green"
85
-
86
- doc.must_equal({"title"=>"Lime Green"})
87
- end
88
-
89
- it "parsing scalar property" do
90
- P[
91
- R::AssignName,
92
- R::ReadFragment,
93
- R::StopOnNotFound,
94
- R::OverwriteOnNil,
95
- # R::SkipParse,
96
- R::SetValue,
97
- ].extend(P::Debug).(doc={"title"=>"Eruption"}, {represented: song=Song.new("Lime Green"), binding: title, doc: doc}).must_equal "Eruption"
98
- song.title.must_equal "Eruption"
99
- end
100
-
101
-
102
-
103
- module ArtistRepresenter
104
- include Representable::Hash
105
- property :name
106
- end
107
-
108
- let (:artist) {
109
- dfn = R::Definition.new(:artist, extend: ArtistRepresenter, class: Artist)
110
-
111
- R::Hash::Binding.new(dfn)
112
- }
113
-
114
- let (:song_model) { Song.new("Lime Green", Artist.new("Diesel Boy")) }
115
-
116
- it "rendering typed property" do
117
- doc = {}
118
- P[
119
- R::GetValue,
120
- R::StopOnSkipable,
121
- R::StopOnNil,
122
- R::SkipRender,
123
- R::Decorate,
124
- R::Serialize,
125
- R::AssignName,
126
- R::WriteFragment
127
- ].extend(P::Debug).(nil, {represented: song_model, binding: artist, doc: doc, options: {}}).must_equal({"name" => "Diesel Boy"})
128
-
129
- doc.must_equal({"artist"=>{"name"=>"Diesel Boy"}})
130
- end
131
-
132
- it "parsing typed property" do
133
- P[
134
- R::AssignName,
135
- R::ReadFragment,
136
- R::StopOnNotFound,
137
- R::OverwriteOnNil,
138
- # R::SkipParse,
139
- R::AssignFragment,
140
- R::CreateObject::Class,
141
- R::Decorate,
142
- R::Deserialize,
143
- R::SetValue,
144
- ].extend(P::Debug).(doc={"artist"=>{"name"=>"Doobie Brothers"}}, {represented: song_model, binding: artist, doc: doc, options: {}}).must_equal model=Artist.new("Doobie Brothers")
145
- song_model.artist.must_equal model
146
- end
147
-
148
-
149
- ######### collection :ratings
150
-
151
- let (:ratings) {
152
- dfn = R::Definition.new(:ratings, collection: true)
153
-
154
- R::Hash::Binding::Collection.new(dfn)
155
- }
156
- it "render scalar collection" do
157
- doc = {}
158
- P[
159
- R::GetValue,
160
- R::StopOnSkipable,
161
- R::Collect[
162
- R::SkipRender,
163
- ],
164
- R::AssignName,
165
- R::WriteFragment
166
- ].extend(P::Debug).(nil, {represented: Album.new([1,2,3]), binding: ratings, doc: doc}).must_equal([1,2,3])
167
-
168
- doc.must_equal({"ratings"=>[1,2,3]})
169
- end
170
-
171
- ######### collection :songs, extend: SongRepresenter
172
- let (:artists) {
173
- dfn = R::Definition.new(:artists, collection: true, extend: ArtistRepresenter, class: Artist)
174
-
175
- R::Hash::Binding::Collection.new(dfn)
176
- }
177
- it "render typed collection" do
178
- doc = {}
179
- P[
180
- R::GetValue,
181
- R::StopOnSkipable,
182
- R::Collect[
183
- R::SkipRender,
184
- R::Decorate,
185
- R::Serialize,
186
- ],
187
- R::AssignName,
188
- R::WriteFragment
189
- ].extend(P::Debug).(nil, {represented: Album.new(nil, [Artist.new("Diesel Boy"), Artist.new("Van Halen")]), binding: artists, doc: doc, options: {}}).must_equal([{"name"=>"Diesel Boy"}, {"name"=>"Van Halen"}])
190
-
191
- doc.must_equal({"artists"=>[{"name"=>"Diesel Boy"}, {"name"=>"Van Halen"}]})
192
- end
193
-
194
- let (:album_model) { Album.new(nil, [Artist.new("Diesel Boy"), Artist.new("Van Halen")]) }
195
-
196
- it "parse typed collection" do
197
- doc = {"artists"=>[{"name"=>"Diesel Boy"}, {"name"=>"Van Halen"}]}
198
- P[
199
- R::AssignName,
200
- R::ReadFragment,
201
- R::StopOnNotFound,
202
- R::OverwriteOnNil,
203
- # R::SkipParse,
204
- R::Collect[
205
- R::AssignFragment,
206
- R::SkipRender,
207
- R::CreateObject::Class,
208
- R::Decorate,
209
- R::Deserialize,
210
- ],
211
- R::SetValue,
212
- ].extend(P::Debug).(doc, {represented: album_model, binding: artists, doc: doc, options: {}}).must_equal([Artist.new("Diesel Boy"), Artist.new("Van Halen")])
213
-
214
- album_model.artists.must_equal([Artist.new("Diesel Boy"), Artist.new("Van Halen")])
215
- end
216
-
217
- # TODO: test with arrays, too, not "only" Pipeline instances.
218
- describe "#Insert Pipeline[], Function, replace: OldFunction" do
219
- let (:pipeline) { P[R::GetValue, R::StopOnSkipable, R::StopOnNil] }
220
-
221
- it "returns Pipeline instance when passing in Pipeline instance" do
222
- P::Insert.(pipeline, R::Default, replace: R::StopOnSkipable).must_be_instance_of(R::Pipeline)
223
- end
224
-
225
- it "replaces if exists" do
226
- # pipeline.insert!(R::Default, replace: R::StopOnSkipable)
227
- P::Insert.(pipeline, R::Default, replace: R::StopOnSkipable).must_equal P[R::GetValue, R::Default, R::StopOnNil]
228
- pipeline.must_equal P[R::GetValue, R::StopOnSkipable, R::StopOnNil]
229
- end
230
-
231
- it "replaces Function instance" do
232
- pipeline = P[R::Prepare, R::StopOnSkipable, R::StopOnNil]
233
- P::Insert.(pipeline, R::Default, replace: R::Prepare).must_equal P[R::Default, R::StopOnSkipable, R::StopOnNil]
234
- pipeline.must_equal P[R::Prepare, R::StopOnSkipable, R::StopOnNil]
235
- end
236
-
237
- it "does not replace when not existing" do
238
- P::Insert.(pipeline, R::Default, replace: R::Prepare)
239
- pipeline.must_equal P[R::GetValue, R::StopOnSkipable, R::StopOnNil]
240
- end
241
-
242
- it "applies on nested Collect" do
243
- pipeline = P[R::GetValue, R::Collect[R::GetValue, R::StopOnSkipable], R::StopOnNil]
244
-
245
- P::Insert.(pipeline, R::Default, replace: R::StopOnSkipable).extend(P::Debug).inspect.must_equal "Pipeline[GetValue, Collect[GetValue, Default], StopOnNil]"
246
- pipeline.must_equal P[R::GetValue, R::Collect[R::GetValue, R::StopOnSkipable], R::StopOnNil]
247
-
248
-
249
- P::Insert.(pipeline, R::Default, replace: R::StopOnNil).extend(P::Debug).inspect.must_equal "Pipeline[GetValue, Collect[GetValue, StopOnSkipable], Default]"
250
- end
251
-
252
- it "applies on nested Collect with Function::CreateObject" do
253
- pipeline = P[R::GetValue, R::Collect[R::GetValue, R::CreateObject], R::StopOnNil]
254
-
255
- P::Insert.(pipeline, R::Default, replace: R::CreateObject).extend(P::Debug).inspect.must_equal "Pipeline[GetValue, Collect[GetValue, Default], StopOnNil]"
256
- pipeline.must_equal P[R::GetValue, R::Collect[R::GetValue, R::CreateObject], R::StopOnNil]
257
- end
258
- end
259
-
260
- describe "Insert.(delete: true)" do
261
- let(:pipeline) { P[R::GetValue, R::StopOnNil] }
262
-
263
- it do
264
- P::Insert.(pipeline, R::GetValue, delete: true).extend(P::Debug).inspect.must_equal "Pipeline[StopOnNil]"
265
- pipeline.extend(P::Debug).inspect.must_equal "Pipeline[GetValue, StopOnNil]"
266
- end
267
- end
268
-
269
- describe "Insert.(delete: true) with Collect" do
270
- let(:pipeline) { P[R::GetValue, R::Collect[R::GetValue, R::StopOnSkipable], R::StopOnNil] }
271
-
272
- it do
273
- P::Insert.(pipeline, R::GetValue, delete: true).extend(P::Debug).inspect.must_equal "Pipeline[Collect[StopOnSkipable], StopOnNil]"
274
- pipeline.extend(P::Debug).inspect.must_equal "Pipeline[GetValue, Collect[GetValue, StopOnSkipable], StopOnNil]"
275
- end
276
- end
277
- end