shale 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +98 -2
- data/lib/shale/adapter/nokogiri.rb +1 -1
- data/lib/shale/adapter/ox.rb +2 -1
- data/lib/shale/error.rb +12 -0
- data/lib/shale/mapping/descriptor/dict.rb +10 -1
- data/lib/shale/mapping/dict.rb +4 -3
- data/lib/shale/mapping/dict_base.rb +27 -2
- data/lib/shale/schema/json_generator/base.rb +9 -3
- data/lib/shale/schema/json_generator/collection.rb +17 -2
- data/lib/shale/schema/json_generator/float.rb +6 -1
- data/lib/shale/schema/json_generator/integer.rb +6 -1
- data/lib/shale/schema/json_generator/object.rb +10 -2
- data/lib/shale/schema/json_generator/string.rb +5 -1
- data/lib/shale/schema/json_generator.rb +7 -3
- data/lib/shale/schema/xml_compiler.rb +12 -12
- data/lib/shale/type/complex.rb +11 -0
- data/lib/shale/utils.rb +1 -1
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +12 -16
- data/shale.gemspec +3 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60a0f059693d5ea371ffca8b475ebb261ee99096509e588d2f1163a96bf8fbc0
|
4
|
+
data.tar.gz: c1af0c61c7d9a93bd601188c50916d4f702228052541adee34456c4d7dac8b9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31bd59c352febaf287eda07a79f56e5fe942fd86623f532e48c25ff5e946bb53fc879c3f8bb13121989268057beb4ee740f8aac7b1275dda8b9a2d21a5f75aaf
|
7
|
+
data.tar.gz: 127b46cdeb0960643aa60410597f7ace1815dd19e3845cd0cb7c2ea3d2d44b4326333656bdf96209effcf17daabbc5a70de9f430acd42e21d961e2c356d9be9f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## [1.1.0] - 2024-02-17
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- [bkjohnson] Add support for JSON Schema validation keywords (#29)
|
5
|
+
- Add support for Ruby 3.3
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- Drop support for Ruby 2.6 and Ruby 2.7
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
- Fix Ox adapter incorrectly handling documents with XML declaration
|
12
|
+
|
1
13
|
## [1.0.0] - 2023-07-15
|
2
14
|
|
3
15
|
### Added
|
data/README.md
CHANGED
@@ -17,7 +17,7 @@ Documentation with interactive examples is available at [Shale website](https://
|
|
17
17
|
|
18
18
|
## Installation
|
19
19
|
|
20
|
-
Shale supports Ruby (MRI)
|
20
|
+
Shale supports Ruby (MRI) 3.0+
|
21
21
|
|
22
22
|
Add this line to your application's Gemfile:
|
23
23
|
|
@@ -353,6 +353,25 @@ person.to_xml
|
|
353
353
|
|
354
354
|
### Converting CSV to object
|
355
355
|
|
356
|
+
To use CSV with Shale you have to set adapter.
|
357
|
+
Shale comes with adapter for [csv](https://github.com/ruby/csv).
|
358
|
+
For details see [Adapters](#adapters) section.
|
359
|
+
|
360
|
+
To set it, first make sure CSV gem is installed:
|
361
|
+
|
362
|
+
```
|
363
|
+
$ gem install csv
|
364
|
+
```
|
365
|
+
|
366
|
+
then setup adapter:
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
require 'shale/adapter/csv'
|
370
|
+
Shale.csv_adapter = Shale::Adapter::CSV
|
371
|
+
```
|
372
|
+
|
373
|
+
Now you can use CSV with Shale.
|
374
|
+
|
356
375
|
CSV represents a flat data structure, so you can't map properties to complex types directly,
|
357
376
|
but you can use methods to map properties to complex types
|
358
377
|
(see [Using methods to extract and generate data](#using-methods-to-extract-and-generate-data)
|
@@ -1155,7 +1174,7 @@ end
|
|
1155
1174
|
### Adapters
|
1156
1175
|
|
1157
1176
|
Shale uses adapters for parsing and generating documents.
|
1158
|
-
By default Ruby's standard JSON
|
1177
|
+
By default Ruby's standard JSON and YAML parsers are used for handling JSON and YAML documents.
|
1159
1178
|
|
1160
1179
|
You can change it by providing your own adapter. For JSON, YAML, TOML and CSV adapter must
|
1161
1180
|
implement `.load` and `.dump` class methods.
|
@@ -1183,6 +1202,14 @@ require 'shale/adapter/toml_rb'
|
|
1183
1202
|
Shale.toml_adapter = Shale::Adapter::TomlRB
|
1184
1203
|
```
|
1185
1204
|
|
1205
|
+
To handle CSV documents you have to set CSV adapter. Shale provides adapter for `csv` parser:
|
1206
|
+
|
1207
|
+
```ruby
|
1208
|
+
require 'shale'
|
1209
|
+
require 'shale/adapter/csv'
|
1210
|
+
Shale.csv_adapter = Shale::Adapter::CSV
|
1211
|
+
```
|
1212
|
+
|
1186
1213
|
To handle XML documents you have to explicitly set XML adapter.
|
1187
1214
|
Shale provides adapters for most popular Ruby XML parsers:
|
1188
1215
|
|
@@ -1288,6 +1315,75 @@ end
|
|
1288
1315
|
Shale::Schema::JSONGenerator.register_json_type(MyEmailType, MyEmailJSONType)
|
1289
1316
|
```
|
1290
1317
|
|
1318
|
+
To add validation keywords to the schema, you can use a custom model and do this:
|
1319
|
+
|
1320
|
+
```ruby
|
1321
|
+
require 'shale/schema'
|
1322
|
+
|
1323
|
+
class PersonMapper < Shale::Mapper
|
1324
|
+
model Person
|
1325
|
+
|
1326
|
+
attribute :first_name, Shale::Type::String
|
1327
|
+
attribute :last_name, Shale::Type::String
|
1328
|
+
attribute :address, Shale::Type::String
|
1329
|
+
attribute :age, Shale::Type::Integer
|
1330
|
+
|
1331
|
+
json do
|
1332
|
+
properties max_properties: 5
|
1333
|
+
|
1334
|
+
map "first_name", to: :first_name, schema: { required: true }
|
1335
|
+
map "last_name", to: :last_name, schema: { required: true }
|
1336
|
+
map "address", to: :age, schema: { max_length: 128 }
|
1337
|
+
map "age", to: :age, schema: { minimum: 1, maximum: 150 }
|
1338
|
+
end
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
Shale::Schema.to_json(
|
1342
|
+
PersonMapper,
|
1343
|
+
pretty: true
|
1344
|
+
)
|
1345
|
+
|
1346
|
+
# =>
|
1347
|
+
#
|
1348
|
+
# {
|
1349
|
+
# "$schema": "https://json-schema.org/draft/2020-12/schema",
|
1350
|
+
# "description": "My description",
|
1351
|
+
# "$ref": "#/$defs/Person",
|
1352
|
+
# "$defs": {
|
1353
|
+
# "Person": {
|
1354
|
+
# "type": "object",
|
1355
|
+
# "maxProperties": 5,
|
1356
|
+
# "properties": {
|
1357
|
+
# "first_name": {
|
1358
|
+
# "type": "string"
|
1359
|
+
# },
|
1360
|
+
# "last_name": {
|
1361
|
+
# "type": "string"
|
1362
|
+
# },
|
1363
|
+
# "age": {
|
1364
|
+
# "type": [
|
1365
|
+
# "integer",
|
1366
|
+
# "null"
|
1367
|
+
# ],
|
1368
|
+
# "minimum": 1,
|
1369
|
+
# "maximum": 150
|
1370
|
+
# },
|
1371
|
+
# "address": {
|
1372
|
+
# "type": [
|
1373
|
+
# "string",
|
1374
|
+
# "null"
|
1375
|
+
# ],
|
1376
|
+
# "maxLength": 128
|
1377
|
+
# }
|
1378
|
+
# },
|
1379
|
+
# "required": ["first_name", "last_name"]
|
1380
|
+
# }
|
1381
|
+
# }
|
1382
|
+
# }
|
1383
|
+
```
|
1384
|
+
|
1385
|
+
Validation keywords are supported for all types, only the global `enum` and `const` types are not supported.
|
1386
|
+
|
1291
1387
|
### Compiling JSON Schema into Shale model
|
1292
1388
|
|
1293
1389
|
:warning: Only **[Draft 2020-12](https://json-schema.org/draft/2020-12/schema)** JSON Schema is supported
|
data/lib/shale/adapter/ox.rb
CHANGED
@@ -22,7 +22,8 @@ module Shale
|
|
22
22
|
#
|
23
23
|
# @api private
|
24
24
|
def self.load(xml)
|
25
|
-
|
25
|
+
element = ::Ox.parse(xml)
|
26
|
+
Node.new(element.respond_to?(:root) ? element.root : element)
|
26
27
|
rescue ::Ox::ParseError => e
|
27
28
|
raise ParseError, "Document is invalid: #{e.message}"
|
28
29
|
end
|
data/lib/shale/error.rb
CHANGED
@@ -38,6 +38,18 @@ module Shale
|
|
38
38
|
Shale.xml_adapter = Shale::Adapter::Ox
|
39
39
|
MSG
|
40
40
|
|
41
|
+
# Error message displayed when CSV adapter is not set
|
42
|
+
# @api private
|
43
|
+
CSV_ADAPTER_NOT_SET_MESSAGE = <<~MSG
|
44
|
+
CSV Adapter is not set.
|
45
|
+
To use Shale with CSV documents you have to install parser and set adapter.
|
46
|
+
|
47
|
+
# To use csv gem:
|
48
|
+
# Make sure csv is installed eg. execute: gem install csv
|
49
|
+
require 'shale/adapter/csv'
|
50
|
+
Shale.csv_adapter = Shale::Adapter::CSV
|
51
|
+
MSG
|
52
|
+
|
41
53
|
# Error for assigning value to not existing attribute
|
42
54
|
#
|
43
55
|
# @api private
|
@@ -49,6 +49,13 @@ module Shale
|
|
49
49
|
# @api private
|
50
50
|
attr_reader :group
|
51
51
|
|
52
|
+
# Return schema hash
|
53
|
+
#
|
54
|
+
# @return [Hash]
|
55
|
+
#
|
56
|
+
# @api private
|
57
|
+
attr_reader :schema
|
58
|
+
|
52
59
|
# Initialize instance
|
53
60
|
#
|
54
61
|
# @param [String] name
|
@@ -57,14 +64,16 @@ module Shale
|
|
57
64
|
# @param [Hash, nil] methods
|
58
65
|
# @param [String, nil] group
|
59
66
|
# @param [true, false] render_nil
|
67
|
+
# @param [Hash, nil] schema
|
60
68
|
#
|
61
69
|
# @api private
|
62
|
-
def initialize(name:, attribute:, receiver:, methods:, group:, render_nil:)
|
70
|
+
def initialize(name:, attribute:, receiver:, methods:, group:, render_nil:, schema: nil)
|
63
71
|
@name = name
|
64
72
|
@attribute = attribute
|
65
73
|
@receiver = receiver
|
66
74
|
@group = group
|
67
75
|
@render_nil = render_nil
|
76
|
+
@schema = schema
|
68
77
|
|
69
78
|
if methods
|
70
79
|
@method_from = methods[:from]
|
data/lib/shale/mapping/dict.rb
CHANGED
@@ -16,12 +16,13 @@ module Shale
|
|
16
16
|
# @param [Symbol, nil] receiver
|
17
17
|
# @param [Hash, nil] using
|
18
18
|
# @param [true, false, nil] render_nil
|
19
|
+
# @param [Hash, nil] schema
|
19
20
|
#
|
20
21
|
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
21
22
|
#
|
22
|
-
# @api
|
23
|
-
def map(key, to: nil, receiver: nil, using: nil, render_nil: nil)
|
24
|
-
super(key, to: to, receiver: receiver, using: using, render_nil: render_nil)
|
23
|
+
# @api public
|
24
|
+
def map(key, to: nil, receiver: nil, using: nil, render_nil: nil, schema: nil)
|
25
|
+
super(key, to: to, receiver: receiver, using: using, render_nil: render_nil, schema: schema)
|
25
26
|
end
|
26
27
|
|
27
28
|
# Set render_nil default
|
@@ -16,6 +16,13 @@ module Shale
|
|
16
16
|
# @api private
|
17
17
|
attr_reader :keys
|
18
18
|
|
19
|
+
# Return hash for hash with properties for root Object
|
20
|
+
#
|
21
|
+
# @return [Hash]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
attr_reader :root
|
25
|
+
|
19
26
|
# Initialize instance
|
20
27
|
#
|
21
28
|
# @param [true, false] render_nil_default
|
@@ -23,6 +30,7 @@ module Shale
|
|
23
30
|
# @api private
|
24
31
|
def initialize(render_nil_default: false)
|
25
32
|
@keys = {}
|
33
|
+
@root = {}
|
26
34
|
@finalized = false
|
27
35
|
@render_nil_default = render_nil_default
|
28
36
|
end
|
@@ -35,11 +43,12 @@ module Shale
|
|
35
43
|
# @param [Hash, nil] using
|
36
44
|
# @param [String, nil] group
|
37
45
|
# @param [true, false, nil] render_nil
|
46
|
+
# @param [Hash, nil] schema
|
38
47
|
#
|
39
48
|
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
40
49
|
#
|
41
50
|
# @api private
|
42
|
-
def map(key, to: nil, receiver: nil, using: nil, group: nil, render_nil: nil)
|
51
|
+
def map(key, to: nil, receiver: nil, using: nil, group: nil, render_nil: nil, schema: nil)
|
43
52
|
Validator.validate_arguments(key, to, receiver, using)
|
44
53
|
|
45
54
|
@keys[key] = Descriptor::Dict.new(
|
@@ -48,10 +57,26 @@ module Shale
|
|
48
57
|
receiver: receiver,
|
49
58
|
methods: using,
|
50
59
|
group: group,
|
51
|
-
render_nil: render_nil.nil? ? @render_nil_default : render_nil
|
60
|
+
render_nil: render_nil.nil? ? @render_nil_default : render_nil,
|
61
|
+
schema: schema
|
52
62
|
)
|
53
63
|
end
|
54
64
|
|
65
|
+
# Allow schema properties to be set on the object
|
66
|
+
#
|
67
|
+
# @param [Integer] min_properties
|
68
|
+
# @param [Integer] max_properties
|
69
|
+
# @param [Hash] dependent_required
|
70
|
+
#
|
71
|
+
# @api public
|
72
|
+
def properties(min_properties: nil, max_properties: nil, dependent_required: nil)
|
73
|
+
@root = {
|
74
|
+
min_properties: min_properties,
|
75
|
+
max_properties: max_properties,
|
76
|
+
dependent_required: dependent_required,
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
55
80
|
# Set the "finalized" instance variable to true
|
56
81
|
#
|
57
82
|
# @api private
|
@@ -12,15 +12,21 @@ module Shale
|
|
12
12
|
# @api private
|
13
13
|
attr_reader :name
|
14
14
|
|
15
|
-
# Return
|
15
|
+
# Return schema hash
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
attr_reader :schema
|
19
|
+
|
20
|
+
# Set nullable
|
16
21
|
#
|
17
22
|
# @api private
|
18
23
|
attr_writer :nullable
|
19
24
|
|
20
|
-
def initialize(name, default: nil)
|
25
|
+
def initialize(name, default: nil, schema: nil)
|
21
26
|
@name = name.gsub('::', '_')
|
22
27
|
@default = default
|
23
|
-
@
|
28
|
+
@schema = schema || {}
|
29
|
+
@nullable = !schema&.[](:required)
|
24
30
|
end
|
25
31
|
|
26
32
|
# Return JSON Schema fragment as Ruby Hash
|
@@ -7,13 +7,20 @@ module Shale
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class Collection
|
10
|
+
# Return schema hash
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
attr_reader :schema
|
14
|
+
|
10
15
|
# Initialize Collection object
|
11
16
|
#
|
12
17
|
# @param [Shale::Schema::JSONGenerator::Base] type
|
18
|
+
# @param [Hash] schema
|
13
19
|
#
|
14
20
|
# @api private
|
15
|
-
def initialize(type)
|
21
|
+
def initialize(type, schema: nil)
|
16
22
|
@type = type
|
23
|
+
@schema = schema
|
17
24
|
end
|
18
25
|
|
19
26
|
# Delegate name to wrapped type object
|
@@ -31,7 +38,15 @@ module Shale
|
|
31
38
|
#
|
32
39
|
# @api private
|
33
40
|
def as_json
|
34
|
-
|
41
|
+
schema = @schema || {}
|
42
|
+
|
43
|
+
{ 'type' => 'array',
|
44
|
+
'items' => @type.as_type,
|
45
|
+
'minItems' => schema[:min_items],
|
46
|
+
'maxItems' => schema[:max_items],
|
47
|
+
'uniqueItems' => schema[:unique],
|
48
|
+
'minContains' => schema[:min_contains],
|
49
|
+
'maxContains' => schema[:max_contains] }.compact
|
35
50
|
end
|
36
51
|
end
|
37
52
|
end
|
@@ -15,7 +15,12 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'number'
|
18
|
+
{ 'type' => 'number',
|
19
|
+
'exclusiveMinimum' => schema[:exclusive_minimum],
|
20
|
+
'exclusiveMaximum' => schema[:exclusive_maximum],
|
21
|
+
'minimum' => schema[:minimum],
|
22
|
+
'maximum' => schema[:maximum],
|
23
|
+
'multipleOf' => schema[:multiple_of] }.compact
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -15,7 +15,12 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'integer'
|
18
|
+
{ 'type' => 'integer',
|
19
|
+
'exclusiveMinimum' => schema[:exclusive_minimum],
|
20
|
+
'exclusiveMaximum' => schema[:exclusive_maximum],
|
21
|
+
'minimum' => schema[:minimum],
|
22
|
+
'maximum' => schema[:maximum],
|
23
|
+
'multipleOf' => schema[:multiple_of] }.compact
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -16,10 +16,12 @@ module Shale
|
|
16
16
|
# Array<Shale::Schema::JSONGenerator::Base,
|
17
17
|
# Shale::Schema::JSONGenerator::Collection>
|
18
18
|
# ] properties
|
19
|
+
# @param [Hash] root
|
19
20
|
#
|
20
21
|
# @api private
|
21
|
-
def initialize(name, properties)
|
22
|
+
def initialize(name, properties, root)
|
22
23
|
super(name)
|
24
|
+
@root = root
|
23
25
|
@properties = properties
|
24
26
|
end
|
25
27
|
|
@@ -29,10 +31,16 @@ module Shale
|
|
29
31
|
#
|
30
32
|
# @api private
|
31
33
|
def as_type
|
34
|
+
required_props = @properties.filter_map { |prop| prop.name if prop&.schema&.[](:required) }
|
35
|
+
|
32
36
|
{
|
33
37
|
'type' => 'object',
|
34
38
|
'properties' => @properties.to_h { |el| [el.name, el.as_json] },
|
35
|
-
|
39
|
+
'required' => required_props.empty? ? nil : required_props,
|
40
|
+
'minProperties' => @root[:min_properties],
|
41
|
+
'maxProperties' => @root[:max_properties],
|
42
|
+
'dependentRequired' => @root[:dependent_required],
|
43
|
+
}.compact
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
@@ -15,7 +15,11 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'string'
|
18
|
+
{ 'type' => 'string',
|
19
|
+
'format' => schema[:format],
|
20
|
+
'minLength' => schema[:min_length],
|
21
|
+
'maxLength' => schema[:max_length],
|
22
|
+
'pattern' => schema[:pattern] }.compact
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -96,14 +96,18 @@ module Shale
|
|
96
96
|
default = attribute.type.as_json(value)
|
97
97
|
end
|
98
98
|
|
99
|
-
json_type = json_klass.new(
|
99
|
+
json_type = json_klass.new(
|
100
|
+
mapping.name,
|
101
|
+
default: default,
|
102
|
+
schema: mapping.schema
|
103
|
+
)
|
100
104
|
end
|
101
105
|
|
102
|
-
json_type = Collection.new(json_type) if attribute.collection?
|
106
|
+
json_type = Collection.new(json_type, schema: mapping.schema) if attribute.collection?
|
103
107
|
properties << json_type
|
104
108
|
end
|
105
109
|
|
106
|
-
objects << Object.new(type.model.name, properties)
|
110
|
+
objects << Object.new(type.model.name, properties, type.json_mapping.root)
|
107
111
|
end
|
108
112
|
|
109
113
|
Schema.new(objects, id: id, title: title, description: description).as_json
|
@@ -34,51 +34,51 @@ module Shale
|
|
34
34
|
|
35
35
|
# XML Schema "schema" element name
|
36
36
|
# @api private
|
37
|
-
XS_SCHEMA = "#{XS_NAMESPACE_URI}:schema"
|
37
|
+
XS_SCHEMA = "#{XS_NAMESPACE_URI}:schema".freeze
|
38
38
|
|
39
39
|
# XML Schema "element" element name
|
40
40
|
# @api private
|
41
|
-
XS_ELEMENT = "#{XS_NAMESPACE_URI}:element"
|
41
|
+
XS_ELEMENT = "#{XS_NAMESPACE_URI}:element".freeze
|
42
42
|
|
43
43
|
# XML Schema "attribute" element name
|
44
44
|
# @api private
|
45
|
-
XS_ATTRIBUTE = "#{XS_NAMESPACE_URI}:attribute"
|
45
|
+
XS_ATTRIBUTE = "#{XS_NAMESPACE_URI}:attribute".freeze
|
46
46
|
|
47
47
|
# XML Schema "attribute" element name
|
48
48
|
# @api private
|
49
|
-
XS_SIMPLE_TYPE = "#{XS_NAMESPACE_URI}:simpleType"
|
49
|
+
XS_SIMPLE_TYPE = "#{XS_NAMESPACE_URI}:simpleType".freeze
|
50
50
|
|
51
51
|
# XML Schema "simpleContent" element name
|
52
52
|
# @api private
|
53
|
-
XS_SIMPLE_CONTENT = "#{XS_NAMESPACE_URI}:simpleContent"
|
53
|
+
XS_SIMPLE_CONTENT = "#{XS_NAMESPACE_URI}:simpleContent".freeze
|
54
54
|
|
55
55
|
# XML Schema "restriction" element name
|
56
56
|
# @api private
|
57
|
-
XS_RESTRICTION = "#{XS_NAMESPACE_URI}:restriction"
|
57
|
+
XS_RESTRICTION = "#{XS_NAMESPACE_URI}:restriction".freeze
|
58
58
|
|
59
59
|
# XML Schema "group" element name
|
60
60
|
# @api private
|
61
|
-
XS_GROUP = "#{XS_NAMESPACE_URI}:group"
|
61
|
+
XS_GROUP = "#{XS_NAMESPACE_URI}:group".freeze
|
62
62
|
|
63
63
|
# XML Schema "attributeGroup" element name
|
64
64
|
# @api private
|
65
|
-
XS_ATTRIBUTE_GROUP = "#{XS_NAMESPACE_URI}:attributeGroup"
|
65
|
+
XS_ATTRIBUTE_GROUP = "#{XS_NAMESPACE_URI}:attributeGroup".freeze
|
66
66
|
|
67
67
|
# XML Schema "complexType" element name
|
68
68
|
# @api private
|
69
|
-
XS_COMPLEX_TYPE = "#{XS_NAMESPACE_URI}:complexType"
|
69
|
+
XS_COMPLEX_TYPE = "#{XS_NAMESPACE_URI}:complexType".freeze
|
70
70
|
|
71
71
|
# XML Schema "complexContent" element name
|
72
72
|
# @api private
|
73
|
-
XS_COMPLEX_CONTENT = "#{XS_NAMESPACE_URI}:complexContent"
|
73
|
+
XS_COMPLEX_CONTENT = "#{XS_NAMESPACE_URI}:complexContent".freeze
|
74
74
|
|
75
75
|
# XML Schema "extension" element name
|
76
76
|
# @api private
|
77
|
-
XS_EXTENSION = "#{XS_NAMESPACE_URI}:extension"
|
77
|
+
XS_EXTENSION = "#{XS_NAMESPACE_URI}:extension".freeze
|
78
78
|
|
79
79
|
# XML Schema "anyType" type
|
80
80
|
# @api private
|
81
|
-
XS_TYPE_ANY = "#{XS_NAMESPACE_URI}:anyType"
|
81
|
+
XS_TYPE_ANY = "#{XS_NAMESPACE_URI}:anyType".freeze
|
82
82
|
|
83
83
|
# XML Schema "date" types
|
84
84
|
# @api private
|
data/lib/shale/type/complex.rb
CHANGED
@@ -373,6 +373,7 @@ module Shale
|
|
373
373
|
#
|
374
374
|
# @api public
|
375
375
|
def from_csv(csv, only: nil, except: nil, context: nil, headers: false, **csv_options)
|
376
|
+
validate_csv_adapter
|
376
377
|
data = Shale.csv_adapter.load(csv, **csv_options.merge(headers: csv_mapping.keys.keys))
|
377
378
|
|
378
379
|
data.shift if headers
|
@@ -398,6 +399,7 @@ module Shale
|
|
398
399
|
#
|
399
400
|
# @api public
|
400
401
|
def to_csv(instance, only: nil, except: nil, context: nil, headers: false, **csv_options)
|
402
|
+
validate_csv_adapter
|
401
403
|
data = as_csv([*instance], only: only, except: except, context: context)
|
402
404
|
|
403
405
|
cols = csv_mapping.keys.values
|
@@ -892,6 +894,15 @@ module Shale
|
|
892
894
|
raise AdapterError, XML_ADAPTER_NOT_SET_MESSAGE unless Shale.xml_adapter
|
893
895
|
end
|
894
896
|
|
897
|
+
# Validate CSV adapter
|
898
|
+
#
|
899
|
+
# @raise [AdapterError]
|
900
|
+
#
|
901
|
+
# @api private
|
902
|
+
def validate_csv_adapter
|
903
|
+
raise AdapterError, CSV_ADAPTER_NOT_SET_MESSAGE unless Shale.csv_adapter
|
904
|
+
end
|
905
|
+
|
895
906
|
# Convert array with attributes to a hash
|
896
907
|
#
|
897
908
|
# @param [Array] ary
|
data/lib/shale/utils.rb
CHANGED
@@ -31,7 +31,7 @@ module Shale
|
|
31
31
|
# @api private
|
32
32
|
def self.classify(str)
|
33
33
|
# names may include a period, which will need to be stripped out
|
34
|
-
str = str.to_s.gsub(
|
34
|
+
str = str.to_s.gsub('.', '')
|
35
35
|
|
36
36
|
str = str.sub(/^[a-z\d]*/) { |match| upcase_first(match) || match }
|
37
37
|
|
data/lib/shale/version.rb
CHANGED
data/lib/shale.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'yaml'
|
4
4
|
|
5
5
|
require_relative 'shale/mapper'
|
6
|
-
require_relative 'shale/adapter/csv'
|
7
6
|
require_relative 'shale/adapter/json'
|
8
7
|
require_relative 'shale/type/boolean'
|
9
8
|
require_relative 'shale/type/date'
|
@@ -52,6 +51,12 @@ require_relative 'shale/version'
|
|
52
51
|
# Shale.xml_adapter = Shale::Adapter::Ox
|
53
52
|
# Shale.xml_adapter # => Shale::Adapter::Ox
|
54
53
|
#
|
54
|
+
# @example setting CSV adapter for handling CSV documents
|
55
|
+
# require 'shale/adapter/csv'
|
56
|
+
#
|
57
|
+
# Shale.csv_adapter = Shale::Adapter::CSV
|
58
|
+
# Shale.csv_adapter # => Shale::Adapter::CSV
|
59
|
+
#
|
55
60
|
# @api public
|
56
61
|
module Shale
|
57
62
|
class << self
|
@@ -93,11 +98,15 @@ module Shale
|
|
93
98
|
#
|
94
99
|
# @param [.load, .dump] adapter
|
95
100
|
#
|
96
|
-
# @example
|
101
|
+
# @example setting adapter
|
97
102
|
# Shale.csv_adapter = Shale::Adapter::CSV
|
98
103
|
#
|
104
|
+
# @example getting adapter
|
105
|
+
# Shale.csv_adapter
|
106
|
+
# # => Shale::Adapter::CSV
|
107
|
+
#
|
99
108
|
# @api public
|
100
|
-
|
109
|
+
attr_accessor :csv_adapter
|
101
110
|
|
102
111
|
# XML adapter accessor. Available adapters are Shale::Adapter::REXML,
|
103
112
|
# Shale::Adapter::Nokogiri and Shale::Adapter::Ox
|
@@ -139,18 +148,5 @@ module Shale
|
|
139
148
|
def yaml_adapter
|
140
149
|
@yaml_adapter || YAML
|
141
150
|
end
|
142
|
-
|
143
|
-
# Return CSV adapter. By default CSV is used
|
144
|
-
#
|
145
|
-
# @return [.load, .dump]
|
146
|
-
#
|
147
|
-
# @example
|
148
|
-
# Shale.csv_adapter
|
149
|
-
# # => Shale::Adapter::CSV
|
150
|
-
#
|
151
|
-
# @api public
|
152
|
-
def csv_adapter
|
153
|
-
@csv_adapter || Adapter::CSV
|
154
|
-
end
|
155
151
|
end
|
156
152
|
end
|
data/shale.gemspec
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shale
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kamil Giszczak
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2024-02-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bigdecimal
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: Ruby object mapper and serializer for XML, JSON, TOML, CSV and YAML.
|
14
28
|
email:
|
15
29
|
- beerkg@gmail.com
|
@@ -118,14 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
132
|
requirements:
|
119
133
|
- - ">="
|
120
134
|
- !ruby/object:Gem::Version
|
121
|
-
version:
|
135
|
+
version: 3.0.0
|
122
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
137
|
requirements:
|
124
138
|
- - ">="
|
125
139
|
- !ruby/object:Gem::Version
|
126
140
|
version: '0'
|
127
141
|
requirements: []
|
128
|
-
rubygems_version: 3.
|
142
|
+
rubygems_version: 3.5.3
|
129
143
|
signing_key:
|
130
144
|
specification_version: 4
|
131
145
|
summary: Ruby object mapper and serializer for XML, JSON, TOML, CSV and YAML.
|