representable 3.1.1 → 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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +17 -4
  3. data/.github/workflows/ci_jruby.yml +21 -0
  4. data/.github/workflows/ci_truffleruby.yml +19 -0
  5. data/CHANGES.md +9 -0
  6. data/Gemfile +1 -1
  7. data/README.md +8 -10
  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 +3 -10
  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 +11 -97
  74. data/lib/representable/virtus_coercion.rb +0 -38
  75. data/test/virtus_coercion_test.rb +0 -52
data/test/yaml_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class YamlPublicMethodsTest < Minitest::Spec
4
4
  #---
@@ -9,10 +9,12 @@ class YamlPublicMethodsTest < Minitest::Spec
9
9
  property :name
10
10
  end
11
11
 
12
- let(:data) { %{---
12
+ let(:data) do
13
+ %{---
13
14
  id: 1
14
15
  name: Rancid
15
- } }
16
+ }
17
+ end
16
18
 
17
19
  it { _(BandRepresenter.new(Band.new).from_yaml(data)[:id, :name]).must_equal [1, "Rancid"] }
18
20
  it { _(BandRepresenter.new(Band.new).parse(data)[:id, :name]).must_equal [1, "Rancid"] }
@@ -25,7 +27,7 @@ name: Rancid
25
27
  it { _(BandRepresenter.new(band).render).must_equal data }
26
28
  end
27
29
 
28
- class YamlTest < MiniTest::Spec
30
+ class YamlTest < Minitest::Spec
29
31
  def self.yaml_representer(&block)
30
32
  Module.new do
31
33
  include Representable::YAML
@@ -37,53 +39,59 @@ class YamlTest < MiniTest::Spec
37
39
  self.class.yaml_representer(&block)
38
40
  end
39
41
 
40
-
41
42
  describe "property" do
42
- let(:yaml) { yaml_representer do property :best_song end }
43
+ let(:yaml) { yaml_representer { property :best_song } }
43
44
 
44
- let(:album) { Album.new.tap do |album|
45
- album.best_song = "Liar"
46
- end }
45
+ let(:album) do
46
+ Album.new.tap do |album|
47
+ album.best_song = "Liar"
48
+ end
49
+ end
47
50
 
48
51
  describe "#to_yaml" do
49
52
  it "renders plain property" do
50
53
  _(album.extend(yaml).to_yaml).must_equal(
51
- "---
54
+ "---
52
55
  best_song: Liar
53
- ")
56
+ "
57
+ )
54
58
  end
55
59
 
56
60
  it "always renders values into strings" do
57
61
  _(Album.new.tap { |a| a.best_song = 8675309 }.extend(yaml).to_yaml).must_equal(
58
- "---
62
+ "---
59
63
  best_song: 8675309
60
64
  "
61
- )
65
+ )
62
66
  end
63
67
  end
64
68
 
65
-
66
69
  describe "#from_yaml" do
67
70
  it "parses plain property" do
68
- _(album.extend(yaml).from_yaml(
69
- "---
71
+ _(
72
+ album.extend(yaml).from_yaml(
73
+ "---
70
74
  best_song: This Song Is Recycled
71
- ").best_song).must_equal "This Song Is Recycled"
75
+ "
76
+ ).best_song
77
+ ).must_equal "This Song Is Recycled"
72
78
  end
73
79
  end
74
80
 
75
-
76
81
  describe "with :class and :extend" do
77
- yaml_song = yaml_representer do property :name end
78
- let(:yaml_album) { Module.new do
79
- include Representable::YAML
80
- property :best_song, :extend => yaml_song, :class => Song
81
- end }
82
-
83
- let(:album) { Album.new.tap do |album|
84
- album.best_song = Song.new("Liar")
85
- end }
82
+ yaml_song = yaml_representer { property :name }
83
+ let(:yaml_album) do
84
+ Module.new do
85
+ include Representable::YAML
86
+ property :best_song, :extend => yaml_song, :class => Song
87
+ end
88
+ end
86
89
 
90
+ let(:album) do
91
+ Album.new.tap do |album|
92
+ album.best_song = Song.new("Liar")
93
+ end
94
+ end
87
95
 
88
96
  describe "#to_yaml" do
89
97
  it "renders embedded typed property" do
@@ -96,23 +104,27 @@ best_song:
96
104
 
97
105
  describe "#from_yaml" do
98
106
  it "parses embedded typed property" do
99
- _(album.extend(yaml_album).from_yaml("---
107
+ _(
108
+ album.extend(yaml_album).from_yaml(
109
+ "---
100
110
  best_song:
101
111
  name: Go With Me
102
- ")).must_equal Album.new(nil,Song.new("Go With Me"))
112
+ "
113
+ )
114
+ ).must_equal Album.new(nil, Song.new("Go With Me"))
103
115
  end
104
116
  end
105
117
  end
106
118
  end
107
119
 
108
-
109
120
  describe "collection" do
110
- let(:yaml) { yaml_representer do collection :songs end }
111
-
112
- let(:album) { Album.new.tap do |album|
113
- album.songs = ["Jackhammer", "Terrible Man"]
114
- end }
121
+ let(:yaml) { yaml_representer { collection :songs } }
115
122
 
123
+ let(:album) do
124
+ Album.new.tap do |album|
125
+ album.songs = ["Jackhammer", "Terrible Man"]
126
+ end
127
+ end
116
128
 
117
129
  describe "#to_yaml" do
118
130
  it "renders a block style list per default" do
@@ -131,35 +143,41 @@ songs: [Jackhammer, Terrible Man]
131
143
  end
132
144
  end
133
145
 
134
-
135
146
  describe "#from_yaml" do
136
147
  it "parses a block style list" do
137
- _(album.extend(yaml).from_yaml("---
148
+ _(
149
+ album.extend(yaml).from_yaml(
150
+ "---
138
151
  songs:
139
152
  - Off Key Melody
140
- - Sinking")).must_equal Album.new(["Off Key Melody", "Sinking"])
141
-
153
+ - Sinking"
154
+ )
155
+ ).must_equal Album.new(["Off Key Melody", "Sinking"])
142
156
  end
143
157
 
144
158
  it "parses a flow style list" do
145
- _(album.extend(yaml).from_yaml("---
146
- songs: [Off Key Melody, Sinking]")).must_equal Album.new(["Off Key Melody", "Sinking"])
159
+ _(
160
+ album.extend(yaml).from_yaml(
161
+ "---
162
+ songs: [Off Key Melody, Sinking]"
163
+ )
164
+ ).must_equal Album.new(["Off Key Melody", "Sinking"])
147
165
  end
148
166
  end
149
167
 
150
-
151
168
  describe "with :class and :extend" do
152
- let(:yaml_album) { Module.new do
153
- include Representable::YAML
154
- collection :songs, :class => Song do
155
- property :name
156
- property :track
169
+ let(:yaml_album) do
170
+ Module.new do
171
+ include Representable::YAML
172
+ collection :songs, :class => Song do
173
+ property :name
174
+ property :track
175
+ end
157
176
  end
158
- end }
177
+ end
159
178
 
160
179
  let(:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
161
180
 
162
-
163
181
  describe "#to_yaml" do
164
182
  it "renders collection of typed property" do
165
183
  _(album.extend(yaml_album).to_yaml).must_equal "---
@@ -174,12 +192,16 @@ songs:
174
192
 
175
193
  describe "#from_yaml" do
176
194
  it "parses collection of typed property" do
177
- _(album.extend(yaml_album).from_yaml("---
195
+ _(
196
+ album.extend(yaml_album).from_yaml(
197
+ "---
178
198
  songs:
179
199
  - name: One Shot Deal
180
200
  track: 4
181
201
  - name: Three Way Dance
182
- track: 5")).must_equal Album.new([Song.new("One Shot Deal", 4), Song.new("Three Way Dance", 5)])
202
+ track: 5"
203
+ )
204
+ ).must_equal Album.new([Song.new("One Shot Deal", 4), Song.new("Three Way Dance", 5)])
183
205
  end
184
206
  end
185
207
  end
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: 3.1.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-13 00:00:00.000000000 Z
11
+ date: 2026-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber
@@ -72,20 +72,6 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
- - !ruby/object:Gem::Dependency
76
- name: test_xml
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: 0.1.6
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: 0.1.6
89
75
  - !ruby/object:Gem::Dependency
90
76
  name: minitest
91
77
  requirement: !ruby/object:Gem::Requirement
@@ -100,20 +86,6 @@ dependencies:
100
86
  - - ">="
101
87
  - !ruby/object:Gem::Version
102
88
  version: '0'
103
- - !ruby/object:Gem::Dependency
104
- name: virtus
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
89
  - !ruby/object:Gem::Dependency
118
90
  name: dry-types
119
91
  requirement: !ruby/object:Gem::Requirement
@@ -151,6 +123,8 @@ extensions: []
151
123
  extra_rdoc_files: []
152
124
  files:
153
125
  - ".github/workflows/ci.yml"
126
+ - ".github/workflows/ci_jruby.yml"
127
+ - ".github/workflows/ci_truffleruby.yml"
154
128
  - ".gitignore"
155
129
  - CHANGES.md
156
130
  - Gemfile
@@ -188,7 +162,6 @@ files:
188
162
  - lib/representable/represent.rb
189
163
  - lib/representable/serializer.rb
190
164
  - lib/representable/version.rb
191
- - lib/representable/virtus_coercion.rb
192
165
  - lib/representable/xml.rb
193
166
  - lib/representable/xml/binding.rb
194
167
  - lib/representable/xml/collection.rb
@@ -250,8 +223,8 @@ files:
250
223
  - test/test_helper_test.rb
251
224
  - test/uncategorized_test.rb
252
225
  - test/user_options_test.rb
253
- - test/virtus_coercion_test.rb
254
226
  - test/wrap_test.rb
227
+ - test/xml_assertions.rb
255
228
  - test/xml_bindings_test.rb
256
229
  - test/xml_namespace_test.rb
257
230
  - test/xml_test.rb
@@ -260,7 +233,7 @@ homepage: https://github.com/trailblazer/representable/
260
233
  licenses:
261
234
  - MIT
262
235
  metadata: {}
263
- post_install_message:
236
+ post_install_message:
264
237
  rdoc_options: []
265
238
  require_paths:
266
239
  - lib
@@ -268,75 +241,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
268
241
  requirements:
269
242
  - - ">="
270
243
  - !ruby/object:Gem::Version
271
- version: 2.4.0
244
+ version: 3.0.0
272
245
  required_rubygems_version: !ruby/object:Gem::Requirement
273
246
  requirements:
274
247
  - - ">="
275
248
  - !ruby/object:Gem::Version
276
249
  version: '0'
277
250
  requirements: []
278
- rubygems_version: 3.0.8
279
- signing_key:
251
+ rubygems_version: 3.2.3
252
+ signing_key:
280
253
  specification_version: 4
281
254
  summary: Renders and parses JSON/XML/YAML documents from and to Ruby objects. Includes
282
255
  plain properties, collections, nesting, coercion and more.
283
- test_files:
284
- - test/as_test.rb
285
- - test/benchmarking.rb
286
- - test/binding_test.rb
287
- - test/cached_test.rb
288
- - test/class_test.rb
289
- - test/coercion_test.rb
290
- - test/config/inherit_test.rb
291
- - test/config_test.rb
292
- - test/decorator_scope_test.rb
293
- - test/decorator_test.rb
294
- - test/default_test.rb
295
- - test/defaults_options_test.rb
296
- - test/definition_test.rb
297
- - test/examples/example.rb
298
- - test/examples/object.rb
299
- - test/exec_context_test.rb
300
- - test/features_test.rb
301
- - test/filter_test.rb
302
- - test/for_collection_test.rb
303
- - test/generic_test.rb
304
- - test/getter_setter_test.rb
305
- - test/hash_bindings_test.rb
306
- - test/hash_test.rb
307
- - test/heritage_test.rb
308
- - test/if_test.rb
309
- - test/include_exclude_test.rb
310
- - test/inherit_test.rb
311
- - test/inline_test.rb
312
- - test/instance_test.rb
313
- - test/is_representable_test.rb
314
- - test/json_test.rb
315
- - test/lonely_test.rb
316
- - test/nested_test.rb
317
- - test/object_test.rb
318
- - test/option_test.rb
319
- - test/parse_pipeline_test.rb
320
- - test/pipeline_test.rb
321
- - test/populator_test.rb
322
- - test/prepare_test.rb
323
- - test/private_options_test.rb
324
- - test/reader_writer_test.rb
325
- - test/realistic_benchmark.rb
326
- - test/render_nil_test.rb
327
- - test/represent_test.rb
328
- - test/representable_test.rb
329
- - test/schema_test.rb
330
- - test/serialize_deserialize_test.rb
331
- - test/skip_test.rb
332
- - test/stringify_hash_test.rb
333
- - test/test_helper.rb
334
- - test/test_helper_test.rb
335
- - test/uncategorized_test.rb
336
- - test/user_options_test.rb
337
- - test/virtus_coercion_test.rb
338
- - test/wrap_test.rb
339
- - test/xml_bindings_test.rb
340
- - test/xml_namespace_test.rb
341
- - test/xml_test.rb
342
- - test/yaml_test.rb
256
+ test_files: []
@@ -1,38 +0,0 @@
1
- gem 'virtus'
2
- require "virtus"
3
-
4
- module Representable
5
- module VirtusCoercion
6
- class Coercer
7
- def initialize(type)
8
- @type = type
9
- end
10
-
11
- # This gets called when the :render_filter or :parse_filter option is evaluated.
12
- # Usually the Coercer instance is an element in a Pipeline to allow >1 filters per property.
13
- def call(input, options)
14
- Virtus::Attribute.build(@type).coerce(input)
15
- end
16
- end
17
-
18
-
19
- def self.included(base)
20
- base.class_eval do
21
- extend ClassMethods
22
- register_feature VirtusCoercion
23
- end
24
- end
25
-
26
-
27
- module ClassMethods
28
- def property(name, options={}, &block)
29
- super.tap do |definition|
30
- return definition unless type = options[:type]
31
-
32
- definition.merge!(render_filter: coercer = Coercer.new(type))
33
- definition.merge!(parse_filter: coercer)
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,52 +0,0 @@
1
- require 'test_helper'
2
- require 'representable/virtus_coercion'
3
-
4
- class VirtusCoercionTest < MiniTest::Spec
5
- representer! do
6
- include Representable::VirtusCoercion
7
-
8
- property :title # no coercion.
9
- property :length, :type => Float
10
-
11
- property :band, :class => OpenStruct do
12
- property :founded, :type => Integer
13
- end
14
-
15
- collection :songs, :class => OpenStruct do
16
- property :ok, :type => Virtus::Attribute::Boolean
17
- end
18
- end
19
-
20
- let(:album) { OpenStruct.new(:title => "Dire Straits", :length => 41.34,
21
- :band => OpenStruct.new(:founded => "1977"),
22
- :songs => [OpenStruct.new(:ok => 1), OpenStruct.new(:ok => 0)]) }
23
-
24
- it { _(album.extend(representer).to_hash).must_equal({"title"=>"Dire Straits", "length"=>41.34, "band"=>{"founded"=>1977}, "songs"=>[{"ok"=>true}, {"ok"=>false}]}) }
25
-
26
- it {
27
- album = OpenStruct.new
28
- album.extend(representer)
29
- album.from_hash({"title"=>"Dire Straits", "length"=>"41.34", "band"=>{"founded"=>"1977"}, "songs"=>[{"ok"=>1}, {"ok"=>0}]})
30
-
31
- # it
32
- _(album.length).must_equal 41.34
33
- _(album.band.founded).must_equal 1977
34
- _(album.songs[0].ok).must_equal true
35
- }
36
-
37
-
38
- describe "with user :parse_filter and :render_filter" do
39
- representer! do
40
- include Representable::VirtusCoercion
41
-
42
- property :length, :type => Float,
43
- :parse_filter => lambda { |input, options| "#{input}.1" }, # happens BEFORE coercer.
44
- :render_filter => lambda { |fragment,*| "#{fragment}.1" }
45
- end
46
-
47
- # user's :parse_filter(s) are run before coercion.
48
- it { _(OpenStruct.new.extend(representer).from_hash("length"=>"1").length).must_equal 1.1 }
49
- # user's :render_filter(s) are run before coercion.
50
- it { _(OpenStruct.new(:length=>1).extend(representer).to_hash).must_equal({"length" => 1.1}) }
51
- end
52
- end