paradocs 1.1.1 → 1.1.6
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.
- checksums.yaml +4 -4
- data/README.md +1 -11
- data/docs/changelog.md +3 -0
- data/docs/documentation_generation.md +2 -2
- data/lib/paradocs/default_types.rb +0 -10
- data/lib/paradocs/extensions/payload_builder.rb +2 -1
- data/lib/paradocs/extensions/structure.rb +11 -13
- data/lib/paradocs/field.rb +5 -1
- data/lib/paradocs/field_dsl.rb +12 -0
- data/lib/paradocs/policies.rb +12 -1
- data/lib/paradocs/schema.rb +2 -1
- data/lib/paradocs/struct.rb +1 -0
- data/lib/paradocs/version.rb +1 -1
- data/paradocs.gemspec +1 -1
- data/spec/custom_block_validator_spec.rb +1 -1
- data/spec/extensions/payload_builder_spec.rb +3 -3
- data/spec/extensions/structures_spec.rb +24 -18
- data/spec/field_spec.rb +1 -1
- data/spec/schema_spec.rb +6 -6
- data/spec/struct_spec.rb +8 -8
- data/spec/subschema_spec.rb +0 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcffa38b327e138205c221b0161f777bb59674f9
|
4
|
+
data.tar.gz: ce6d34f0dbcbba84201e0c37b12eea7b9804c353
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d18214752279c15cf66860f9f7e1b5cd3e57eb75b0160458713dca4b11c6b72712c33719e327de0443d7d40a2d481a5c6221fcdabaaf2db7098d648c178551f
|
7
|
+
data.tar.gz: 174ccfe6062589625e67642005134216cf03a821ac95af07ccdd4336a083023d98bbf61afd88907c3bf7a6b954dc8ef52d80b45467c2126935b4bbd1578b8aaf
|
data/README.md
CHANGED
@@ -37,14 +37,4 @@ form.errors # => {}
|
|
37
37
|
```
|
38
38
|
|
39
39
|
## Learn more
|
40
|
-
|
41
|
-
- [Built In Policies](https://github.com/mtkachenk0/paradocs/wiki/Policies#built-in-policies)
|
42
|
-
- [Type Policies](https://github.com/mtkachenk0/paradocs/wiki/Policies#type-coercions)
|
43
|
-
- [Presence Policies](https://github.com/mtkachenk0/paradocs/wiki/Policies#presence-policies)
|
44
|
-
- [Custom Policies](https://github.com/mtkachenk0/paradocs/wiki/Policies#custom-policies)
|
45
|
-
- [Schema](https://github.com/mtkachenk0/paradocs/wiki/schema)
|
46
|
-
- [Expanding fields dynamically](https://github.com/mtkachenk0/paradocs/wiki/schema#expanding-fields-dynamically)
|
47
|
-
- [Multiple schema definitions](https://github.com/mtkachenk0/paradocs/wiki/schema#multiple-schema-definitions)
|
48
|
-
- [Documentation Generation](https://github.com/mtkachenk0/paradocs/wiki/Documentation-Generation)
|
49
|
-
- [What if my fields are conditional?!](https://github.com/mtkachenk0/paradocs/wiki/subschema)
|
50
|
-
- [For those who need more: RTFM](https://github.com/mtkachenk0/paradocs/wiki)
|
40
|
+
Please read the [documentation](https://paradocs.readthedocs.io/en/latest)
|
data/docs/changelog.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.1.2
|
4
|
+
- Regenerate structures each time without saving them into instance attributes.
|
5
|
+
|
3
6
|
## 1.1.1
|
4
7
|
- Fixed bug with missing `errors` meta key in `Structure#all_nested` and `Structure#all_flatten` methods.
|
5
8
|
- Fixed bug with absent `nested_name` meta key in `#Structure#all_nested` method.
|
@@ -188,7 +188,7 @@ all_nested[:subschema] # =>
|
|
188
188
|
required: true,
|
189
189
|
present: true,
|
190
190
|
json_path: "$.data",
|
191
|
-
|
191
|
+
nested_name: "data",
|
192
192
|
structure: {
|
193
193
|
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
|
194
194
|
"test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"},
|
@@ -209,7 +209,7 @@ all_nested[:test_subschema] # =>
|
|
209
209
|
required: true,
|
210
210
|
present: true,
|
211
211
|
json_path: "$.data",
|
212
|
-
|
212
|
+
nested_name: "data",
|
213
213
|
structure: {
|
214
214
|
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
|
215
215
|
"test1" => {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"},
|
@@ -73,16 +73,6 @@ module Paradocs
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
Paradocs.policy :split do
|
77
|
-
coerce do |v, k, c|
|
78
|
-
v.kind_of?(Array) ? v : v.to_s.split(/\s*,\s*/)
|
79
|
-
end
|
80
|
-
|
81
|
-
meta_data do
|
82
|
-
{type: :array}
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
76
|
Paradocs.policy :datetime do
|
87
77
|
coerce do |v, k, c|
|
88
78
|
DateTime.parse(v.to_s)
|
@@ -21,7 +21,8 @@ module Paradocs
|
|
21
21
|
next if key.start_with?(Paradocs.config.meta_prefix) # skip all the meta fields
|
22
22
|
ex_value = restore_one(key, value, &block)
|
23
23
|
next if ex_value == @skip_word
|
24
|
-
|
24
|
+
key = value[:alias] || key
|
25
|
+
[key.to_s, ex_value]
|
25
26
|
end.compact.to_h
|
26
27
|
end
|
27
28
|
|
@@ -14,12 +14,8 @@ module Paradocs
|
|
14
14
|
@root = root
|
15
15
|
end
|
16
16
|
|
17
|
-
def flush!
|
18
|
-
@nested, @all_nested, @flatten, @all_flatten = [nil] * 4
|
19
|
-
end
|
20
|
-
|
21
17
|
def nested(&block)
|
22
|
-
|
18
|
+
schema.fields.each_with_object({errors => [], subschemes => {}}) do |(_, field), result|
|
23
19
|
meta, sc = collect_meta(field, root)
|
24
20
|
if sc
|
25
21
|
meta[:structure] = self.class.new(sc, ignore_transparent, meta[:json_path]).nested(&block)
|
@@ -27,8 +23,10 @@ module Paradocs
|
|
27
23
|
else
|
28
24
|
result[errors] += field.possible_errors
|
29
25
|
end
|
30
|
-
|
31
|
-
|
26
|
+
|
27
|
+
field_key = field.meta_data[:alias] || field.key
|
28
|
+
result[field_key] = meta unless ignore_transparent && field.transparent?
|
29
|
+
yield(field_key, meta) if block_given?
|
32
30
|
|
33
31
|
next unless field.mutates_schema?
|
34
32
|
schema.subschemes.each do |name, subschema|
|
@@ -39,7 +37,7 @@ module Paradocs
|
|
39
37
|
end
|
40
38
|
|
41
39
|
def all_nested(&block)
|
42
|
-
|
40
|
+
all_flatten(&block).each_with_object({}) do |(name, struct), obj|
|
43
41
|
obj[name] = {}
|
44
42
|
# sort the flatten struct to have iterated 1lvl keys before 2lvl and so on...
|
45
43
|
struct.sort_by { |k, v| k.to_s.count(".") }.each do |key, value|
|
@@ -61,13 +59,12 @@ module Paradocs
|
|
61
59
|
end
|
62
60
|
|
63
61
|
def all_flatten(schema_structure=nil, &block)
|
64
|
-
return @all_flatten if @all_flatten
|
65
62
|
schema_structure ||= flatten(&block)
|
66
63
|
if schema_structure[subschemes].empty?
|
67
64
|
schema_structure.delete(subschemes) # don't include redundant key
|
68
|
-
return
|
65
|
+
return {DEFAULT => schema_structure}
|
69
66
|
end
|
70
|
-
|
67
|
+
schema_structure[subschemes].each_with_object({}) do |(name, subschema), result|
|
71
68
|
if subschema[subschemes].empty?
|
72
69
|
result[name] = schema_structure.merge(subschema)
|
73
70
|
result[name][errors] += schema_structure[errors]
|
@@ -83,7 +80,7 @@ module Paradocs
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def flatten(&block)
|
86
|
-
|
83
|
+
schema.fields.each_with_object({errors => [], subschemes => {}}) do |(_, field), obj|
|
87
84
|
meta, sc = collect_meta(field, root)
|
88
85
|
humanized_name = meta.delete(:nested_name)
|
89
86
|
obj[humanized_name] = meta unless ignore_transparent && field.transparent?
|
@@ -108,7 +105,8 @@ module Paradocs
|
|
108
105
|
private
|
109
106
|
|
110
107
|
def collect_meta(field, root)
|
111
|
-
|
108
|
+
field_key = field.meta_data[:alias] || field.key
|
109
|
+
json_path = root.empty? ? "$.#{field_key}" : "#{root}.#{field_key}"
|
112
110
|
meta = field.meta_data.merge(json_path: json_path)
|
113
111
|
sc = meta.delete(:schema)
|
114
112
|
meta[:mutates_schema] = true if meta.delete(:mutates_schema)
|
data/lib/paradocs/field.rb
CHANGED
@@ -132,7 +132,11 @@ module Paradocs
|
|
132
132
|
context.add_error e.message
|
133
133
|
rescue StandardError => e
|
134
134
|
raise e if policy.is_a? Paradocs::Schema # from the inner level, just reraise
|
135
|
-
|
135
|
+
if Paradocs.config.explicit_errors
|
136
|
+
error = ConfigurationError.new("<#{e.class}:#{e.message}> should be registered in the policy")
|
137
|
+
error.set_backtrace(e.backtrace)
|
138
|
+
raise error
|
139
|
+
end
|
136
140
|
context.add_error policy.message unless Paradocs.config.explicit_errors
|
137
141
|
[value, false]
|
138
142
|
end
|
data/lib/paradocs/field_dsl.rb
CHANGED
@@ -32,5 +32,17 @@ module Paradocs
|
|
32
32
|
def length(opts)
|
33
33
|
policy :length, opts
|
34
34
|
end
|
35
|
+
|
36
|
+
def description(text)
|
37
|
+
meta description: text
|
38
|
+
end
|
39
|
+
|
40
|
+
def as(identifier)
|
41
|
+
meta alias: identifier
|
42
|
+
end
|
43
|
+
|
44
|
+
def example(value)
|
45
|
+
meta example: value
|
46
|
+
end
|
35
47
|
end
|
36
48
|
end
|
data/lib/paradocs/policies.rb
CHANGED
@@ -5,7 +5,7 @@ module Paradocs
|
|
5
5
|
class Format < Paradocs::BasePolicy
|
6
6
|
attr_reader :message
|
7
7
|
|
8
|
-
def initialize(fmt, msg
|
8
|
+
def initialize(fmt, msg="invalid format")
|
9
9
|
@message = msg
|
10
10
|
@fmt = fmt
|
11
11
|
end
|
@@ -18,12 +18,23 @@ module Paradocs
|
|
18
18
|
!payload.key?(key) || !!(value.to_s =~ @fmt)
|
19
19
|
end
|
20
20
|
end
|
21
|
+
|
22
|
+
class Split < Paradocs::BasePolicy
|
23
|
+
def initialize(delimiter=/\s*,\s*/)
|
24
|
+
@delimiter = delimiter
|
25
|
+
end
|
26
|
+
|
27
|
+
def coerce(v, *)
|
28
|
+
v.kind_of?(Array) ? v : v.to_s.split(@delimiter)
|
29
|
+
end
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
33
|
# Default validators
|
24
34
|
EMAIL_REGEXP = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i.freeze
|
25
35
|
|
26
36
|
Paradocs.policy :format, Policies::Format
|
37
|
+
Paradocs.policy :split, Policies::Split
|
27
38
|
Paradocs.policy :email, Policies::Format.new(EMAIL_REGEXP, 'invalid email')
|
28
39
|
|
29
40
|
Paradocs.policy :noop do
|
data/lib/paradocs/schema.rb
CHANGED
@@ -181,7 +181,8 @@ module Paradocs
|
|
181
181
|
invoke_subschemes!(val, context, flds: flds)
|
182
182
|
flds.each_with_object({}) do |(_, field), m|
|
183
183
|
r = field.resolve(val, context.sub(field.key))
|
184
|
-
|
184
|
+
key = field.meta_data[:alias] || field.key
|
185
|
+
m[key] = r.value if r.eligible?
|
185
186
|
end
|
186
187
|
end
|
187
188
|
|
data/lib/paradocs/struct.rb
CHANGED
data/lib/paradocs/version.rb
CHANGED
data/paradocs.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Paradocs::VERSION
|
9
9
|
spec.authors = ["Maxim Tkachenko", "Ismael Celis"]
|
10
10
|
spec.email = ["tkachenko.maxim.w@gmail.com", "ismaelct@gmail.com"]
|
11
|
-
spec.description = %q{Flexible
|
11
|
+
spec.description = %q{Flexible DRY validations with API docs generation done right TLDR; parametrics on steroids.}
|
12
12
|
spec.summary = %q{A huge add-on for original gem mostly focused on retrieving the more metadata from declared schemas as possible.}
|
13
13
|
spec.homepage = "https://paradocs.readthedocs.io/en/latest"
|
14
14
|
spec.license = "MIT"
|
@@ -81,7 +81,7 @@ describe 'custom block validator' do
|
|
81
81
|
|
82
82
|
it "catches unregistered error and raises Configuration error" do
|
83
83
|
expect { schema.resolve(age: 101).errors }.to raise_error(Paradocs::ConfigurationError)
|
84
|
-
.with_message("ZeroDivisionError should be registered in the policy")
|
84
|
+
.with_message("<ZeroDivisionError:divided by 0> should be registered in the policy")
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -22,7 +22,7 @@ describe Paradocs::Extensions::PayloadBuilder do
|
|
22
22
|
end
|
23
23
|
subschema(:fooschema) { }
|
24
24
|
subschema(:barschema) do
|
25
|
-
field(:barfield).present.type(:boolean)
|
25
|
+
field(:barfield).present.type(:boolean).as(:bar_field)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -32,7 +32,7 @@ describe Paradocs::Extensions::PayloadBuilder do
|
|
32
32
|
allow_any_instance_of(Array).to receive(:sample) { "bar" }
|
33
33
|
payloads = described_class.new(schema).build!
|
34
34
|
expect(payloads.keys.sort).to eq([:barschema, :fooschema, :subschema1, :subschema2_deep_schema, :subschema2_empty])
|
35
|
-
expect(payloads[:barschema]).to eq({"test" => nil, "foo" => {"bar" => "bar", "
|
35
|
+
expect(payloads[:barschema]).to eq({"test" => nil, "foo" => {"bar" => "bar", "bar_field" => nil}})
|
36
36
|
expect(payloads[:fooschema]).to eq({"test" => nil, "foo" => {"bar" => "bar"}})
|
37
37
|
expect(payloads[:subschema1]).to eq({"test" => nil, "foo" => {"bar" => "bar"}, "subtest1" => nil})
|
38
38
|
expect(payloads[:subschema2_deep_schema]).to eq({
|
@@ -57,7 +57,7 @@ describe Paradocs::Extensions::PayloadBuilder do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
expect(payloads.keys.sort).to eq([:barschema, :fooschema, :subschema1, :subschema2_deep_schema, :subschema2_empty])
|
60
|
-
expect(payloads[:barschema]).to eq({"test" => nil, "foo" => {"bar" => nil, "
|
60
|
+
expect(payloads[:barschema]).to eq({"test" => nil, "foo" => {"bar" => nil, "bar_field" => true}}) # barfield is change to true and bar is nil
|
61
61
|
expect(payloads[:fooschema]).to eq({"test" => nil, "foo" => {"bar" => nil}}) # bar is nil
|
62
62
|
expect(payloads[:subschema1]).to eq({"test" => nil, "foo" => {"bar" => nil}}) # subtest is missing, bar is nil
|
63
63
|
expect(payloads[:subschema2_deep_schema]).to eq({
|
@@ -18,8 +18,8 @@ describe Paradocs::Extensions::Structure do
|
|
18
18
|
subschema(:highest_level) { field(:test).present } # no mutations on this level -> subschema ignored
|
19
19
|
|
20
20
|
field(:data).type(:object).present.schema do
|
21
|
-
field(:id).type(:integer).present.policy(:policy_with_error)
|
22
|
-
field(:name).type(:string).meta(label: "very important staff")
|
21
|
+
field(:id).type(:integer).present.policy(:policy_with_error).as(:user_id)
|
22
|
+
field(:name).type(:string).meta(label: "very important staff").description("Example description").example("John")
|
23
23
|
field(:role).type(:string).declared.options(["admin", "user"]).default("user").mutates_schema! do |*|
|
24
24
|
:test_subschema
|
25
25
|
end
|
@@ -64,17 +64,20 @@ describe Paradocs::Extensions::Structure do
|
|
64
64
|
test_field: {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"}
|
65
65
|
}
|
66
66
|
})
|
67
|
-
expect(data_structure[:
|
67
|
+
expect(data_structure[:user_id]).to eq({
|
68
68
|
type: :integer,
|
69
69
|
required: true,
|
70
70
|
present: true,
|
71
71
|
policy_with_error: {errors: [ArgumentError]},
|
72
|
-
|
73
|
-
|
72
|
+
alias: :user_id,
|
73
|
+
json_path: "$.data.user_id",
|
74
|
+
nested_name: "data.user_id"
|
74
75
|
})
|
75
76
|
expect(data_structure[:name]).to eq({
|
76
77
|
type: :string,
|
77
78
|
label: "very important staff",
|
79
|
+
description: "Example description",
|
80
|
+
example: "John",
|
78
81
|
mutates_schema: true,
|
79
82
|
block_works: true,
|
80
83
|
json_path: "$.data.name",
|
@@ -129,17 +132,20 @@ describe Paradocs::Extensions::Structure do
|
|
129
132
|
json_path: "$.data.extra[].extra",
|
130
133
|
policy_with_silent_error: {errors: []}
|
131
134
|
},
|
132
|
-
"data.
|
135
|
+
"data.user_id" => {
|
133
136
|
type: :integer,
|
134
137
|
required: true,
|
135
138
|
present: true,
|
136
|
-
|
139
|
+
alias: :user_id,
|
140
|
+
json_path: "$.data.user_id",
|
137
141
|
policy_with_error: {errors: [ArgumentError]}
|
138
142
|
},
|
139
143
|
"data.name" => {
|
140
144
|
type: :string,
|
141
145
|
json_path: "$.data.name",
|
142
146
|
label: "very important staff",
|
147
|
+
description: "Example description",
|
148
|
+
example: "John",
|
143
149
|
mutates_schema: true
|
144
150
|
},
|
145
151
|
"data.role" => {
|
@@ -176,8 +182,8 @@ describe Paradocs::Extensions::Structure do
|
|
176
182
|
subschema: {
|
177
183
|
_errors: [ArgumentError],
|
178
184
|
"data" => {type: :object, required: true, present: true, json_path: "$.data"},
|
179
|
-
"data.
|
180
|
-
"data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true},
|
185
|
+
"data.user_id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, alias: :user_id, json_path: "$.data.user_id"},
|
186
|
+
"data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, description: "Example description", example: "John"},
|
181
187
|
"data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
|
182
188
|
"data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
|
183
189
|
"data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
|
@@ -186,8 +192,8 @@ describe Paradocs::Extensions::Structure do
|
|
186
192
|
test_subschema: {
|
187
193
|
_errors: [ArgumentError],
|
188
194
|
"data" => {type: :object, required: true, present: true, json_path: "$.data"},
|
189
|
-
"data.
|
190
|
-
"data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true},
|
195
|
+
"data.user_id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, alias: :user_id, json_path: "$.data.user_id"},
|
196
|
+
"data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, description: "Example description", example: "John"},
|
191
197
|
"data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
|
192
198
|
"data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
|
193
199
|
"data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
|
@@ -211,8 +217,8 @@ describe Paradocs::Extensions::Structure do
|
|
211
217
|
structure: {
|
212
218
|
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", nested_name: "data.role", mutates_schema: true},
|
213
219
|
"test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"},
|
214
|
-
"
|
215
|
-
"name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
|
220
|
+
"user_id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, alias: :user_id, json_path: "$.data.user_id", nested_name: "data.user_id"},
|
221
|
+
"name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name", description: "Example description", example: "John"},
|
216
222
|
"extra" => {
|
217
223
|
type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
|
218
224
|
structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}
|
@@ -229,11 +235,11 @@ describe Paradocs::Extensions::Structure do
|
|
229
235
|
json_path: "$.data",
|
230
236
|
nested_name: "data",
|
231
237
|
structure: {
|
232
|
-
"role"
|
233
|
-
"test1"
|
234
|
-
"
|
235
|
-
"name"
|
236
|
-
"extra"
|
238
|
+
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", nested_name: "data.role", mutates_schema: true},
|
239
|
+
"test1" => {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"},
|
240
|
+
"user_id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, alias: :user_id, json_path: "$.data.user_id", nested_name: "data.user_id"},
|
241
|
+
"name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name", description: "Example description", example: "John"},
|
242
|
+
"extra" => {
|
237
243
|
type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
|
238
244
|
structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}}
|
239
245
|
}
|
data/spec/field_spec.rb
CHANGED
data/spec/schema_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe Paradocs::Schema do
|
|
16
16
|
|
17
17
|
subject do
|
18
18
|
described_class.new do
|
19
|
-
field(:title).policy(:string).present
|
19
|
+
field(:title).policy(:string).present.as(:article_title)
|
20
20
|
field(:price).policy(:integer).meta(label: "A price")
|
21
21
|
field(:status).policy(:string).options(['visible', 'hidden'])
|
22
22
|
field(:tags).policy(:split).policy(:array)
|
@@ -33,8 +33,8 @@ describe Paradocs::Schema do
|
|
33
33
|
describe "#structure" do
|
34
34
|
it "represents data structure and meta data" do
|
35
35
|
sc = subject.structure.nested
|
36
|
-
expect(sc[:
|
37
|
-
expect(sc[:
|
36
|
+
expect(sc[:article_title][:present]).to be true
|
37
|
+
expect(sc[:article_title][:type]).to eq :string
|
38
38
|
expect(sc[:price][:type]).to eq :integer
|
39
39
|
expect(sc[:price][:label]).to eq "A price"
|
40
40
|
expect(sc[:variants][:type]).to eq :array
|
@@ -76,7 +76,7 @@ describe Paradocs::Schema do
|
|
76
76
|
|
77
77
|
output = subject.resolve(payload).output
|
78
78
|
expect(output).to eq({
|
79
|
-
|
79
|
+
article_title: "title",
|
80
80
|
price: 100,
|
81
81
|
status: "visible",
|
82
82
|
tags: ["tag"],
|
@@ -101,7 +101,7 @@ describe Paradocs::Schema do
|
|
101
101
|
variants: [{name: 'v1', sku: 'ABC', stock: '10', available_if_no_stock: true}]
|
102
102
|
},
|
103
103
|
{
|
104
|
-
|
104
|
+
article_title: 'iPhone 6 Plus',
|
105
105
|
price: 100,
|
106
106
|
status: 'visible',
|
107
107
|
tags: ['tag1', 'tag2'],
|
@@ -114,7 +114,7 @@ describe Paradocs::Schema do
|
|
114
114
|
variants: [{name: 'v1', available_if_no_stock: '1'}]
|
115
115
|
},
|
116
116
|
{
|
117
|
-
|
117
|
+
article_title: 'iPhone 6 Plus',
|
118
118
|
variants: [{name: 'v1', stock: 1, available_if_no_stock: true}]
|
119
119
|
})
|
120
120
|
|
data/spec/struct_spec.rb
CHANGED
@@ -16,13 +16,13 @@ describe Paradocs::Struct do
|
|
16
16
|
include Paradocs::Struct
|
17
17
|
|
18
18
|
schema do
|
19
|
-
field(:title).type(:string).present
|
19
|
+
field(:title).type(:string).present.as(:example_title)
|
20
20
|
field(:friends).type(:array).default([]).schema friend_class
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
new_instance = klass.new
|
25
|
-
expect(new_instance.
|
25
|
+
expect(new_instance.example_title).to eq ''
|
26
26
|
expect(new_instance.friends).to eq []
|
27
27
|
expect(new_instance.valid?).to be false
|
28
28
|
expect(new_instance.errors['$.title']).not_to be_nil
|
@@ -35,7 +35,7 @@ describe Paradocs::Struct do
|
|
35
35
|
]
|
36
36
|
})
|
37
37
|
|
38
|
-
expect(instance.
|
38
|
+
expect(instance.example_title).to eq 'foo'
|
39
39
|
expect(instance.friends.size).to eq 2
|
40
40
|
expect(instance.friends.first.name).to eq 'Ismael'
|
41
41
|
expect(instance.friends.first).to be_a friend_class
|
@@ -154,7 +154,7 @@ describe Paradocs::Struct do
|
|
154
154
|
schema do
|
155
155
|
field(:title).type(:string).present
|
156
156
|
field(:friends).type(:array).schema do
|
157
|
-
field(:name).type(:string)
|
157
|
+
field(:name).type(:string).as(:person_name)
|
158
158
|
field(:age).type(:integer).default(20)
|
159
159
|
end
|
160
160
|
end
|
@@ -171,8 +171,8 @@ describe Paradocs::Struct do
|
|
171
171
|
expect(instance.to_h).to eq({
|
172
172
|
title: 'foo',
|
173
173
|
friends: [
|
174
|
-
{
|
175
|
-
{
|
174
|
+
{person_name: 'Jane', age: 20},
|
175
|
+
{person_name: 'Joe', age: 39},
|
176
176
|
]
|
177
177
|
})
|
178
178
|
|
@@ -190,7 +190,7 @@ describe Paradocs::Struct do
|
|
190
190
|
include Paradocs::Struct
|
191
191
|
|
192
192
|
schema do
|
193
|
-
field(:title).type(:string).present
|
193
|
+
field(:title).type(:string).present.as(:example_title)
|
194
194
|
field(:friends).type(:array).schema do
|
195
195
|
field(:name).type(:string)
|
196
196
|
field(:age).type(:integer).default(20)
|
@@ -213,7 +213,7 @@ describe Paradocs::Struct do
|
|
213
213
|
]
|
214
214
|
)
|
215
215
|
|
216
|
-
expect(instance.
|
216
|
+
expect(instance.example_title).to eq 'foo'
|
217
217
|
expect(instance.email).to eq 'email@me.com'
|
218
218
|
expect(instance.friends.size).to eq 2
|
219
219
|
end
|
data/spec/subschema_spec.rb
CHANGED
@@ -72,7 +72,6 @@ describe "schemes with subschemes" do
|
|
72
72
|
expect(result.errors).to eq({"$.fail_field"=>["is required"]})
|
73
73
|
expect(result.output).to eq({error: :here, fail_field: nil})
|
74
74
|
expect(schema.structure.nested).to eq(structure)
|
75
|
-
schema.structure.flush!
|
76
75
|
expect(schema.structure(ignore_transparent: false).nested).to eq(structure.merge(
|
77
76
|
error: {transparent: true, mutates_schema: true, json_path: "$.error", nested_name: "error"}
|
78
77
|
))
|
@@ -80,9 +79,7 @@ describe "schemes with subschemes" do
|
|
80
79
|
result = schema.resolve({})
|
81
80
|
expect(result.errors).to eq({"$.success_field"=>["is required"]})
|
82
81
|
expect(result.output).to eq({success_field: nil})
|
83
|
-
schema.structure.flush!
|
84
82
|
expect(schema.structure.nested).to eq(structure)
|
85
|
-
schema.structure.flush!
|
86
83
|
expect(schema.structure(ignore_transparent: false).nested).to eq(structure.merge(
|
87
84
|
error: {transparent: true, mutates_schema: true, json_path: "$.error", nested_name: "error"}
|
88
85
|
))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paradocs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxim Tkachenko
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-12-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -67,8 +67,8 @@ dependencies:
|
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
|
-
description: Flexible
|
71
|
-
|
70
|
+
description: Flexible DRY validations with API docs generation done right TLDR; parametrics
|
71
|
+
on steroids.
|
72
72
|
email:
|
73
73
|
- tkachenko.maxim.w@gmail.com
|
74
74
|
- ismaelct@gmail.com
|