representable 3.2.0 → 3.3.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +17 -10
  3. data/.github/workflows/ci_jruby.yml +21 -0
  4. data/.github/workflows/ci_truffleruby.yml +19 -0
  5. data/CHANGES.md +5 -0
  6. data/Gemfile +1 -1
  7. data/README.md +0 -1
  8. data/lib/representable/hash/binding.rb +1 -0
  9. data/lib/representable/json.rb +14 -2
  10. data/lib/representable/version.rb +1 -1
  11. data/lib/representable/xml/binding.rb +0 -7
  12. data/lib/representable/xml.rb +7 -0
  13. data/representable.gemspec +1 -3
  14. data/test/as_test.rb +8 -13
  15. data/test/benchmarking.rb +20 -25
  16. data/test/binding_test.rb +13 -5
  17. data/test/cached_test.rb +55 -35
  18. data/test/class_test.rb +46 -33
  19. data/test/coercion_test.rb +29 -19
  20. data/test/config/inherit_test.rb +12 -17
  21. data/test/config_test.rb +5 -7
  22. data/test/decorator_scope_test.rb +13 -11
  23. data/test/decorator_test.rb +11 -11
  24. data/test/default_test.rb +2 -2
  25. data/test/defaults_options_test.rb +37 -9
  26. data/test/definition_test.rb +10 -12
  27. data/test/examples/example.rb +43 -38
  28. data/test/examples/object.rb +7 -6
  29. data/test/exec_context_test.rb +18 -23
  30. data/test/features_test.rb +29 -10
  31. data/test/filter_test.rb +29 -20
  32. data/test/for_collection_test.rb +12 -15
  33. data/test/generic_test.rb +15 -22
  34. data/test/getter_setter_test.rb +11 -6
  35. data/test/hash_bindings_test.rb +21 -12
  36. data/test/hash_test.rb +53 -38
  37. data/test/heritage_test.rb +0 -1
  38. data/test/if_test.rb +25 -21
  39. data/test/include_exclude_test.rb +24 -16
  40. data/test/inherit_test.rb +114 -27
  41. data/test/inline_test.rb +42 -33
  42. data/test/instance_test.rb +151 -109
  43. data/test/is_representable_test.rb +19 -17
  44. data/test/json_test.rb +48 -46
  45. data/test/lonely_test.rb +35 -33
  46. data/test/nested_test.rb +16 -19
  47. data/test/object_test.rb +6 -6
  48. data/test/option_test.rb +10 -8
  49. data/test/parse_pipeline_test.rb +21 -15
  50. data/test/pipeline_test.rb +144 -108
  51. data/test/populator_test.rb +18 -15
  52. data/test/prepare_test.rb +15 -17
  53. data/test/private_options_test.rb +3 -2
  54. data/test/reader_writer_test.rb +4 -4
  55. data/test/realistic_benchmark.rb +21 -27
  56. data/test/render_nil_test.rb +1 -1
  57. data/test/represent_test.rb +14 -18
  58. data/test/representable_test.rb +86 -53
  59. data/test/schema_test.rb +51 -21
  60. data/test/serialize_deserialize_test.rb +14 -14
  61. data/test/skip_test.rb +39 -28
  62. data/test/stringify_hash_test.rb +29 -31
  63. data/test/test_helper.rb +31 -25
  64. data/test/test_helper_test.rb +7 -7
  65. data/test/uncategorized_test.rb +20 -15
  66. data/test/user_options_test.rb +12 -3
  67. data/test/wrap_test.rb +27 -17
  68. data/test/xml_assertions.rb +29 -0
  69. data/test/xml_bindings_test.rb +5 -8
  70. data/test/xml_namespace_test.rb +46 -39
  71. data/test/xml_test.rb +109 -88
  72. data/test/yaml_test.rb +73 -51
  73. metadata +7 -32
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class InstanceTest < BaseTest
4
4
  Song = Struct.new(:id, :title)
@@ -10,13 +10,13 @@ class InstanceTest < BaseTest
10
10
 
11
11
  describe "lambda { fragment } (new way of class: lambda { nil })" do
12
12
  representer! do
13
- property :title, :instance => lambda { |options| options[:fragment] }
13
+ property :title, :instance => ->(options) { options[:fragment] }
14
14
  end
15
15
 
16
16
  it "skips creating new instance" do
17
17
  object = Object.new
18
18
  object.instance_eval do
19
- def from_hash(hash, *args)
19
+ def from_hash(hash, *_args)
20
20
  hash
21
21
  end
22
22
  end
@@ -26,53 +26,71 @@ class InstanceTest < BaseTest
26
26
  end
27
27
  end
28
28
 
29
-
30
- # TODO: use *args in from_hash.
31
- # DISCUSS: do we need parse_strategy?
29
+ # TODO: use *args in from_hash.
30
+ # DISCUSS: do we need parse_strategy?
32
31
  describe "property with :instance" do
33
32
  representer!(:inject => :song_representer) do
34
33
  property :song,
35
- :instance => lambda { |options| options[:fragment]["id"] == song.id ? song : Song.find(options[:fragment]["id"]) },
36
- :extend => song_representer
34
+ :instance => ->(options) { options[:fragment]["id"] == song.id ? song : Song.find(options[:fragment]["id"]) },
35
+ :extend => song_representer
37
36
  end
38
37
 
39
- it( "xxx") { _(OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer).
40
- from_hash("song" => {"id" => 1}).song).must_equal Song.new(1, "The Answer Is Still No") }
38
+ it("xxx") {
39
+ _(
40
+ OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer)
41
+ .from_hash("song" => {"id" => 1}).song
42
+ ).must_equal Song.new(1, "The Answer Is Still No")
43
+ }
41
44
 
42
- it { _(OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer).
43
- from_hash("song" => {"id" => 2}).song).must_equal Song.new(2, "Invincible") }
45
+ it {
46
+ _(
47
+ OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer)
48
+ .from_hash("song" => {"id" => 2}).song
49
+ ).must_equal Song.new(2, "Invincible")
50
+ }
44
51
  end
45
52
 
46
-
47
53
  describe "collection with :instance" do
48
54
  representer!(:inject => :song_representer) do
49
55
  collection :songs,
50
- :instance => lambda { |options|
51
- options[:fragment]["id"] == songs[options[:index]].id ? songs[options[:index]] : Song.find(options[:fragment]["id"])
52
- }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
56
+ :instance => ->(options) {
57
+ options[:fragment]["id"] == songs[options[:index]].id ? songs[options[:index]] : Song.find(options[:fragment]["id"])
58
+ }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
53
59
 
54
- :extend => song_representer
60
+ :extend => song_representer
55
61
  end
56
62
 
57
63
  it {
58
- album= Struct.new(:songs).new([
59
- Song.new(1, "The Answer Is Still No"),
60
- Song.new(2, "")])
61
-
62
- _(album.
63
- extend(representer).
64
- from_hash("songs" => [{"id" => 2},{"id" => 2, "title"=>"The Answer Is Still No"}]).songs).must_equal [
65
- Song.new(2, "Invincible"), Song.new(2, "The Answer Is Still No")]
64
+ album = Struct.new(:songs).new(
65
+ [
66
+ Song.new(1, "The Answer Is Still No"),
67
+ Song.new(2, "")
68
+ ]
69
+ )
70
+
71
+ _(
72
+ album
73
+ .extend(representer)
74
+ .from_hash("songs" => [{"id" => 2}, {"id" => 2, "title" => "The Answer Is Still No"}]).songs
75
+ ).must_equal [
76
+ Song.new(2, "Invincible"), Song.new(2, "The Answer Is Still No")
77
+ ]
66
78
  }
67
79
  end
68
80
 
69
81
  describe "property with lambda receiving fragment and args" do
70
82
  representer!(:inject => :song_representer) do
71
- property :song, :instance => lambda { |options| Struct.new(:args, :id).new([options[:fragment], options[:user_options]]) }, :extend => song_representer
83
+ property :song, :instance => ->(options) {
84
+ Struct.new(:args, :id).new([options[:fragment], options[:user_options]])
85
+ }, :extend => song_representer
72
86
  end
73
87
 
74
- it { _(OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer).
75
- from_hash({"song" => {"id" => 1}}, user_options: { volume: 1 }).song.args).must_equal([{"id"=>1}, {:volume=>1}]) }
88
+ it {
89
+ _(
90
+ OpenStruct.new(:song => Song.new(1, "The Answer Is Still No")).extend(representer)
91
+ .from_hash({"song" => {"id" => 1}}, user_options: {volume: 1}).song.args
92
+ ).must_equal([{"id"=>1}, {:volume=>1}])
93
+ }
76
94
  end
77
95
 
78
96
  # TODO: raise and test instance:{nil}
@@ -100,26 +118,30 @@ class InstanceTest < BaseTest
100
118
  describe "sync" do
101
119
  representer!(:inject => :song_representer) do
102
120
  collection :songs,
103
- :instance => lambda { |options|
104
- songs[options[:index]]
105
- },
106
- :extend => song_representer,
107
- # :parse_strategy => :sync
108
- :setter => lambda { |*| }
121
+ :instance => ->(options) {
122
+ songs[options[:index]]
123
+ },
124
+ :extend => song_representer,
125
+ # :parse_strategy => :sync
126
+ :setter => ->(*) {}
109
127
  end
110
128
 
111
129
  it {
112
- album= Struct.new(:songs).new(songs = [
113
- Song.new(1, "The Answer Is Still No"),
114
- Song.new(2, "Invncble")])
130
+ album = Struct.new(:songs).new(
131
+ songs = [
132
+ Song.new(1, "The Answer Is Still No"),
133
+ Song.new(2, "Invncble")
134
+ ]
135
+ )
115
136
 
116
- album.
117
- extend(representer).
118
- from_hash("songs" => [{"title" => "The Answer Is Still No"}, {"title" => "Invincible"}])
137
+ album
138
+ .extend(representer)
139
+ .from_hash("songs" => [{"title" => "The Answer Is Still No"}, {"title" => "Invincible"}])
119
140
 
120
141
  _(album.songs).must_equal [
121
142
  Song.new(1, "The Answer Is Still No"),
122
- Song.new(2, "Invincible")]
143
+ Song.new(2, "Invincible")
144
+ ]
123
145
 
124
146
  _(songs.object_id).must_equal album.songs.object_id
125
147
  _(songs[0].object_id).must_equal album.songs[0].object_id
@@ -130,29 +152,34 @@ class InstanceTest < BaseTest
130
152
  describe "update existing elements, only" do
131
153
  representer!(:inject => :song_representer) do
132
154
  collection :songs,
133
- :instance => lambda { |options|
134
-
135
- #fragment["id"] == songs[i].id ? songs[i] : Song.find(fragment["id"])
136
- songs.find { |s| s.id == options[:fragment]["id"] }
137
- }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
138
-
139
- :extend => song_representer,
140
- # :parse_strategy => :sync
141
- :setter => lambda { |*| }
155
+ :instance => ->(options) {
156
+ # fragment["id"] == songs[i].id ? songs[i] : Song.find(fragment["id"])
157
+ songs.find { |s| s.id == options[:fragment]["id"] }
158
+ }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
159
+
160
+ :extend => song_representer,
161
+ # :parse_strategy => :sync
162
+ :setter => ->(*) {}
142
163
  end
143
164
 
144
165
  it("hooray") {
145
- album= Struct.new(:songs).new(songs = [
146
- Song.new(1, "The Answer Is Still No"),
147
- Song.new(2, "Invncble")])
148
-
149
- _(album.
150
- extend(representer).
151
- from_hash("songs" => [{"id" => 2, "title" => "Invincible"}]).
152
- songs).must_equal [
166
+ album = Struct.new(:songs).new(
167
+ songs = [
153
168
  Song.new(1, "The Answer Is Still No"),
154
- Song.new(2, "Invincible")]
155
- # TODO: check elements object_id!
169
+ Song.new(2, "Invncble")
170
+ ]
171
+ )
172
+
173
+ _(
174
+ album
175
+ .extend(representer)
176
+ .from_hash("songs" => [{"id" => 2, "title" => "Invincible"}])
177
+ .songs
178
+ ).must_equal [
179
+ Song.new(1, "The Answer Is Still No"),
180
+ Song.new(2, "Invincible")
181
+ ]
182
+ # TODO: check elements object_id!
156
183
 
157
184
  _(songs.object_id).must_equal album.songs.object_id
158
185
  _(songs[0].object_id).must_equal album.songs[0].object_id
@@ -160,88 +187,103 @@ class InstanceTest < BaseTest
160
187
  }
161
188
  end
162
189
 
163
-
164
190
  describe "add incoming elements, only" do
165
191
  representer!(:inject => :song_representer) do
166
192
  collection :songs,
167
- :instance => lambda { |options|
168
- songs << song=Song.new(2)
169
- song
170
- }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
171
-
172
- :extend => song_representer,
173
- # :parse_strategy => :sync
174
- :setter => lambda { |*| }
193
+ :instance => ->(_options) {
194
+ songs << song = Song.new(2)
195
+ song
196
+ }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
197
+
198
+ :extend => song_representer,
199
+ # :parse_strategy => :sync
200
+ :setter => ->(*) {}
175
201
  end
176
202
 
177
203
  it {
178
- album= Struct.new(:songs).new(songs = [
179
- Song.new(1, "The Answer Is Still No")])
180
-
181
- _(album.
182
- extend(representer).
183
- from_hash("songs" => [{"title" => "Invincible"}]).
184
- songs).must_equal [
185
- Song.new(1, "The Answer Is Still No"),
186
- Song.new(2, "Invincible")]
204
+ album = Struct.new(:songs).new(
205
+ songs = [
206
+ Song.new(1, "The Answer Is Still No")
207
+ ]
208
+ )
209
+
210
+ _(
211
+ album
212
+ .extend(representer)
213
+ .from_hash("songs" => [{"title" => "Invincible"}])
214
+ .songs
215
+ ).must_equal [
216
+ Song.new(1, "The Answer Is Still No"),
217
+ Song.new(2, "Invincible")
218
+ ]
187
219
 
188
220
  _(songs.object_id).must_equal album.songs.object_id
189
221
  _(songs[0].object_id).must_equal album.songs[0].object_id
190
222
  }
191
223
  end
192
224
 
193
-
194
225
  # not sure if this must be a library strategy
195
226
  describe "replace existing element" do
196
227
  representer!(:inject => :song_representer) do
197
228
  collection :songs,
198
- :instance => lambda { |options|
199
- id = options[:fragment].delete("replace_id")
200
- replaced = songs.find { |s| s.id == id }
201
- songs[songs.index(replaced)] = song=Song.new(3)
202
- song
203
- }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
204
-
205
- :extend => song_representer,
206
- # :parse_strategy => :sync
207
- :setter => lambda { |*| }
229
+ :instance => ->(options) {
230
+ id = options[:fragment].delete("replace_id")
231
+ replaced = songs.find { |s| s.id == id }
232
+ songs[songs.index(replaced)] = song = Song.new(3)
233
+ song
234
+ }, # let's not allow returning nil anymore. make sure we can still do everything as with nil. also, let's remove parse_strategy: sync.
235
+
236
+ :extend => song_representer,
237
+ # :parse_strategy => :sync
238
+ :setter => ->(*) {}
208
239
  end
209
240
 
210
241
  it {
211
- album= Struct.new(:songs).new(songs = [
212
- Song.new(1, "The Answer Is Still No"),
213
- Song.new(2, "Invincible")])
214
-
215
- _(album.
216
- extend(representer).
217
- from_hash("songs" => [{"replace_id"=>2, "id" => 3, "title" => "Soulmate"}]).
218
- songs).must_equal [
242
+ album = Struct.new(:songs).new(
243
+ songs = [
219
244
  Song.new(1, "The Answer Is Still No"),
220
- Song.new(3, "Soulmate")]
245
+ Song.new(2, "Invincible")
246
+ ]
247
+ )
248
+
249
+ _(
250
+ album
251
+ .extend(representer)
252
+ .from_hash("songs" => [{"replace_id" => 2, "id" => 3, "title" => "Soulmate"}])
253
+ .songs
254
+ ).must_equal [
255
+ Song.new(1, "The Answer Is Still No"),
256
+ Song.new(3, "Soulmate")
257
+ ]
221
258
 
222
259
  _(songs.object_id).must_equal album.songs.object_id
223
260
  _(songs[0].object_id).must_equal album.songs[0].object_id
224
261
  }
225
262
  end
226
263
 
227
-
228
264
  describe "replace collection" do
229
265
  representer!(:inject => :song_representer) do
230
266
  collection :songs,
231
- :extend => song_representer, :class => Song
267
+ :extend => song_representer, :class => Song
232
268
  end
233
269
 
234
270
  it {
235
- album= Struct.new(:songs).new(songs = [
236
- Song.new(1, "The Answer Is Still No")])
237
-
238
- _(album.
239
- extend(representer).
240
- from_hash("songs" => [{"title" => "Invincible"}]).
241
- songs).must_equal [
242
- Song.new(nil, "Invincible")]
271
+ album = Struct.new(:songs).new(
272
+ songs = [
273
+ Song.new(1, "The Answer Is Still No")
274
+ ]
275
+ )
276
+
277
+ _(
278
+ album
279
+ .extend(representer)
280
+ .from_hash("songs" => [{"title" => "Invincible"}])
281
+ .songs
282
+ ).must_equal [
283
+ Song.new(nil, "Invincible")
284
+ ]
243
285
 
244
286
  _(songs.object_id).wont_equal album.songs.object_id
245
287
  }
246
288
  end
247
- end
289
+ end
@@ -1,25 +1,26 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class IsRepresentableTest < BaseTest
4
4
  describe "representable: false, extend:" do
5
5
  representer!(:inject => :song_representer) do
6
6
  property :song,
7
- :representable => false,
8
- :extend => song_representer
7
+ :representable => false,
8
+ :extend => song_representer
9
9
  end
10
10
 
11
11
  it "does extend but doesn't call #to_hash" do
12
- _(Struct.new(:song).new(song = Object.new).extend(representer).
13
- to_hash).must_equal("song" => song)
12
+ _(
13
+ Struct.new(:song).new(song = Object.new).extend(representer)
14
+ .to_hash
15
+ ).must_equal("song" => song)
14
16
  _(song).must_be_kind_of Representable::Hash
15
17
  end
16
18
  end
17
19
 
18
-
19
20
  describe "representable: true, no extend:" do
20
21
  representer!(:inject => :song_representer) do
21
22
  property :song,
22
- :representable => true
23
+ :representable => true
23
24
  end
24
25
 
25
26
  it "doesn't extend but calls #to_hash" do
@@ -30,8 +31,10 @@ class IsRepresentableTest < BaseTest
30
31
  end
31
32
  end
32
33
 
33
- _(Struct.new(:song).new(song).extend(representer).
34
- to_hash).must_equal("song" => 1)
34
+ _(
35
+ Struct.new(:song).new(song).extend(representer)
36
+ .to_hash
37
+ ).must_equal("song" => 1)
35
38
  _(song).wont_be_kind_of Representable::Hash
36
39
  end
37
40
  end
@@ -41,19 +44,18 @@ class IsRepresentableTest < BaseTest
41
44
  describe "representable: false, with class:" do
42
45
  representer!(:inject => :song_representer) do
43
46
  property :song,
44
- :representable => false, :class => OpenStruct, :extend => song_representer
47
+ :representable => false, :class => OpenStruct, :extend => song_representer
45
48
  end
46
49
 
47
50
  it "does extend but doesn't call #from_hash" do
48
- hit = Struct.new(:song).new.extend(representer).
49
- from_hash("song" => 1)
51
+ hit = Struct.new(:song).new.extend(representer)
52
+ .from_hash("song" => 1)
50
53
 
51
54
  _(hit.song).must_equal OpenStruct.new
52
55
  _(hit.song).must_be_kind_of Representable::Hash
53
56
  end
54
57
  end
55
58
 
56
-
57
59
  describe "representable: true, without extend: but class:" do
58
60
  SongReader = Class.new do
59
61
  def from_hash(*)
@@ -63,15 +65,15 @@ class IsRepresentableTest < BaseTest
63
65
 
64
66
  representer!(:inject => :song_representer) do
65
67
  property :song,
66
- :representable => true, :class => SongReader
68
+ :representable => true, :class => SongReader
67
69
  end
68
70
 
69
71
  it "doesn't extend but calls #from_hash" do
70
- hit = Struct.new(:song).new.extend(representer).
71
- from_hash("song" => "Sonata No.2")
72
+ hit = Struct.new(:song).new.extend(representer)
73
+ .from_hash("song" => "Sonata No.2")
72
74
 
73
75
  _(hit.song).must_equal "Piano?"
74
76
  _(hit.song).wont_be_kind_of Representable::Hash
75
77
  end
76
78
  end
77
- end
79
+ end