paradocs 1.0.22 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,16 +71,16 @@ describe "schemes with subschemes" do
71
71
  result = schema.resolve({error: :here})
72
72
  expect(result.errors).to eq({"$.fail_field"=>["is required"]})
73
73
  expect(result.output).to eq({error: :here, fail_field: nil})
74
- expect(schema.structure).to eq(structure)
75
- expect(schema.structure(ignore_transparent: false)).to eq(structure.merge(
74
+ expect(schema.structure.nested).to eq(structure)
75
+ expect(schema.structure(ignore_transparent: false).nested).to eq(structure.merge(
76
76
  error: {transparent: true, mutates_schema: true, json_path: "$.error", nested_name: "error"}
77
77
  ))
78
78
 
79
79
  result = schema.resolve({})
80
80
  expect(result.errors).to eq({"$.success_field"=>["is required"]})
81
81
  expect(result.output).to eq({success_field: nil})
82
- expect(schema.structure).to eq(structure)
83
- expect(schema.structure(ignore_transparent: false)).to eq(structure.merge(
82
+ expect(schema.structure.nested).to eq(structure)
83
+ expect(schema.structure(ignore_transparent: false).nested).to eq(structure.merge(
84
84
  error: {transparent: true, mutates_schema: true, json_path: "$.error", nested_name: "error"}
85
85
  ))
86
86
  end
@@ -93,5 +93,38 @@ describe "classes including Whitelist module" do
93
93
  }
94
94
  )
95
95
  end
96
+
97
+ context "when Paradocs.config.whitelist_coercion block is set" do
98
+ before { Paradocs.config.whitelist_coercion = Proc.new { |value, meta| meta[:type] != :string ? "FILTER" : value.to_s }}
99
+
100
+ it "executes block for each value" do
101
+ whitelisted = TestWhitelist.new.filter!(input, schema)
102
+ expect(whitelisted).to eq(
103
+ {
104
+ unexpected: "[FILTERED]",
105
+ from_config: "FILTER",
106
+ data: [
107
+ {
108
+ id: "5",
109
+ name: "[EMPTY]",
110
+ unexpected: "[EMPTY]",
111
+ empty_array: [],
112
+ subschema_1: "FILTER",
113
+ subfield_1: "FILTER",
114
+ subschema_2: "[FILTERED]",
115
+ subfield_2: "FILTER",
116
+ empty_hash: {},
117
+ extra: {
118
+ id: "6",
119
+ name: "[FILTERED]",
120
+ unexpected: "[FILTERED]",
121
+ empty_string: "[EMPTY]"
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ )
127
+ end
128
+ end
96
129
  end
97
130
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paradocs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.22
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
- - Ismael Celis
8
7
  - Maxim Tkachenko
8
+ - Ismael Celis
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-08-26 00:00:00.000000000 Z
12
+ date: 2020-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
34
+ version: '12.3'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: '12.3'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -70,8 +70,8 @@ dependencies:
70
70
  description: Flexible DSL for declaring allowed parameters focused on DRY validation
71
71
  that gives you opportunity to generate API documentation on-the-fly.
72
72
  email:
73
- - ismaelct@gmail.com
74
73
  - tkachenko.maxim.w@gmail.com
74
+ - ismaelct@gmail.com
75
75
  executables:
76
76
  - console
77
77
  extensions: []
@@ -80,6 +80,7 @@ files:
80
80
  - ".github/workflows/spec.yml"
81
81
  - ".gitignore"
82
82
  - ".gitlab-ci.yml"
83
+ - ".readthedocs.yml"
83
84
  - ".rspec"
84
85
  - ".travis.yml"
85
86
  - Gemfile
@@ -87,12 +88,24 @@ files:
87
88
  - README.md
88
89
  - Rakefile
89
90
  - bin/console
91
+ - docs/changelog.md
92
+ - docs/custom_configuration.md
93
+ - docs/documentation_generation.md
94
+ - docs/faq.md
95
+ - docs/form_objects_dsl.md
96
+ - docs/index.md
97
+ - docs/payload_builder.md
98
+ - docs/policies.md
99
+ - docs/schema.md
100
+ - docs/struct.md
101
+ - docs/subschema.md
90
102
  - lib/paradocs.rb
91
103
  - lib/paradocs/base_policy.rb
92
104
  - lib/paradocs/context.rb
93
105
  - lib/paradocs/default_types.rb
94
106
  - lib/paradocs/dsl.rb
95
- - lib/paradocs/extensions/insides.rb
107
+ - lib/paradocs/extensions/payload_builder.rb
108
+ - lib/paradocs/extensions/structure.rb
96
109
  - lib/paradocs/field.rb
97
110
  - lib/paradocs/field_dsl.rb
98
111
  - lib/paradocs/policies.rb
@@ -103,23 +116,26 @@ files:
103
116
  - lib/paradocs/support.rb
104
117
  - lib/paradocs/version.rb
105
118
  - lib/paradocs/whitelist.rb
119
+ - mkdocs.yml
106
120
  - paradocs.gemspec
121
+ - requirements.txt
107
122
  - spec/custom_block_validator_spec.rb
108
123
  - spec/custom_validator.rb
109
124
  - spec/dsl_spec.rb
110
125
  - spec/expand_spec.rb
126
+ - spec/extensions/payload_builder_spec.rb
127
+ - spec/extensions/structures_spec.rb
111
128
  - spec/field_spec.rb
112
129
  - spec/helpers.rb
113
130
  - spec/policies_spec.rb
114
131
  - spec/schema_spec.rb
115
- - spec/schema_structures_spec.rb
116
132
  - spec/schema_walk_spec.rb
117
133
  - spec/spec_helper.rb
118
134
  - spec/struct_spec.rb
119
135
  - spec/subschema_spec.rb
120
136
  - spec/validators_spec.rb
121
137
  - spec/whitelist_spec.rb
122
- homepage: https://github.com/mtkachenk0/paradocs
138
+ homepage: https://paradocs.readthedocs.io/en/latest
123
139
  licenses:
124
140
  - MIT
125
141
  metadata: {}
@@ -149,11 +165,12 @@ test_files:
149
165
  - spec/custom_validator.rb
150
166
  - spec/dsl_spec.rb
151
167
  - spec/expand_spec.rb
168
+ - spec/extensions/payload_builder_spec.rb
169
+ - spec/extensions/structures_spec.rb
152
170
  - spec/field_spec.rb
153
171
  - spec/helpers.rb
154
172
  - spec/policies_spec.rb
155
173
  - spec/schema_spec.rb
156
- - spec/schema_structures_spec.rb
157
174
  - spec/schema_walk_spec.rb
158
175
  - spec/spec_helper.rb
159
176
  - spec/struct_spec.rb
@@ -1,77 +0,0 @@
1
- module Paradocs
2
- module Extensions
3
- module Insides
4
- def structure(ignore_transparent: true, root: "", &block)
5
- flush!
6
- fields.each_with_object({meta_keys[:errors] => [], meta_keys[:subschemes] => {}}) do |(_, field), obj|
7
- meta, sc = collect_meta(field, root)
8
- if sc
9
- meta[:structure] = sc.structure(ignore_transparent: ignore_transparent, root: meta[:json_path], &block)
10
- obj[meta_keys[:errors]] += meta[:structure].delete(meta_keys[:errors])
11
- else
12
- obj[meta_keys[:errors]] += field.possible_errors
13
- end
14
- obj[field.key] = meta unless ignore_transparent && field.transparent?
15
- yield(field.key, meta) if block_given?
16
-
17
- next unless field.mutates_schema?
18
- subschemes.each do |name, subschema|
19
- obj[meta_keys[:subschemes]][name] = subschema.structure(ignore_transparent: ignore_transparent, root: root, &block)
20
- obj[meta_keys[:errors]] += obj[meta_keys[:subschemes]][name][meta_keys[:errors]]
21
- end
22
- end
23
- end
24
-
25
- def flatten_structure(ignore_transparent: true, root: "", &block)
26
- flush!
27
- fields.each_with_object({meta_keys[:errors] => [], meta_keys[:subschemes] => {}}) do |(_, field), obj|
28
- meta, sc = collect_meta(field, root)
29
- humanized_name = meta.delete(:nested_name)
30
- obj[humanized_name] = meta unless ignore_transparent && field.transparent?
31
-
32
- if sc
33
- deep_result = sc.flatten_structure(ignore_transparent: ignore_transparent, root: meta[:json_path], &block)
34
- obj[meta_keys[:errors]] += deep_result.delete(meta_keys[:errors])
35
- obj[meta_keys[:subschemes]].merge!(deep_result.delete(meta_keys[:subschemes]))
36
- obj.merge!(deep_result)
37
- else
38
- obj[meta_keys[:errors]] += field.possible_errors
39
- end
40
- yield(humanized_name, meta) if block_given?
41
- next unless field.mutates_schema?
42
- subschemes.each do |name, subschema|
43
- obj[meta_keys[:subschemes]][name] ||= subschema.flatten_structure(ignore_transparent: ignore_transparent, root: root, &block)
44
- obj[meta_keys[:errors]] += obj[meta_keys[:subschemes]][name][meta_keys[:errors]]
45
- end
46
- end
47
- end
48
-
49
- def walk(meta_key = nil, &visitor)
50
- r = visit(meta_key, &visitor)
51
- Results.new(r, {}, {})
52
- end
53
-
54
- def visit(meta_key = nil, &visitor)
55
- fields.each_with_object({}) do |(_, field), m|
56
- m[field.key] = field.visit(meta_key, &visitor)
57
- end
58
- end
59
-
60
- private
61
-
62
- def collect_meta(field, root)
63
- json_path = root.empty? ? "$.#{field.key}" : "#{root}.#{field.key}"
64
- meta = field.meta_data.merge(json_path: json_path)
65
- sc = meta.delete(:schema)
66
- meta[:mutates_schema] = true if meta.delete(:mutates_schema)
67
- json_path << "[]" if meta[:type] == :array
68
- meta[:nested_name] = json_path.gsub("[]", "")[2..-1]
69
- [meta, sc]
70
- end
71
-
72
- def meta_keys
73
- %i(errors subschemes).map! { |key| [key, "#{Paradocs.config.meta_prefix}#{key}".to_sym] }.to_h
74
- end
75
- end
76
- end
77
- end
@@ -1,169 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Schema structures generation" do
4
- Paradocs.policy :policy_with_error do
5
- register_error ArgumentError
6
-
7
- validate do |*|
8
- raise ArgumentError
9
- end
10
- end
11
-
12
- Paradocs.policy :policy_with_silent_error do
13
- register_silent_error RuntimeError
14
- end
15
-
16
- let(:schema) do
17
- Paradocs::Schema.new do
18
- subschema(:highest_level) { field(:test).present } # no mutations on this level -> subschema ignored
19
-
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")
23
- field(:role).type(:string).declared.options(["admin", "user"]).default("user").mutates_schema! do |*|
24
- :test_subschema
25
- end
26
- field(:extra).type(:array).required.schema do
27
- field(:extra).declared.default(false).policy(:policy_with_silent_error)
28
- end
29
-
30
- mutation_by!(:name) { :subschema }
31
-
32
- subschema(:subschema) do
33
- field(:test_field).present
34
- end
35
- subschema(:test_subschema) do
36
- field(:test1).present
37
- end
38
- end
39
- end
40
- end
41
-
42
-
43
- it "generates nested data for documentation generation" do
44
- result = schema.structure { |k, meta| meta[:block_works] = true unless meta[:present] }
45
- expect(result[:_subschemes]).to eq({})
46
- expect(result[:_errors]).to eq([ArgumentError])
47
- data_structure = result[:data].delete(:structure)
48
- expect(result[:data]).to eq({
49
- type: :object,
50
- required: true,
51
- present: true,
52
- json_path: "$.data",
53
- nested_name: "data",
54
- })
55
- expect(data_structure[:_subschemes]).to eq({
56
- test_subschema: {
57
- _errors: [],
58
- _subschemes: {},
59
- test1: {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"}
60
- },
61
- subschema: {
62
- _errors: [],
63
- _subschemes: {},
64
- test_field: {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"}
65
- }
66
- })
67
- expect(data_structure[:id]).to eq({
68
- type: :integer,
69
- required: true,
70
- present: true,
71
- policy_with_error: {errors: [ArgumentError]},
72
- json_path: "$.data.id",
73
- nested_name: "data.id"
74
- })
75
- expect(data_structure[:name]).to eq({
76
- type: :string,
77
- label: "very important staff",
78
- mutates_schema: true,
79
- block_works: true,
80
- json_path: "$.data.name",
81
- nested_name: "data.name"
82
- })
83
- expect(data_structure[:role]).to eq({
84
- type: :string,
85
- options: ["admin", "user"],
86
- default: "user",
87
- mutates_schema: true,
88
- block_works: true,
89
- json_path: "$.data.role",
90
- nested_name: "data.role"
91
- })
92
- expect(data_structure[:extra]).to eq({
93
- type: :array,
94
- required: true,
95
- block_works: true,
96
- json_path: "$.data.extra[]",
97
- nested_name: "data.extra",
98
- structure: {
99
- extra: {
100
- default: false,
101
- block_works: true,
102
- json_path: "$.data.extra[].extra",
103
- nested_name: "data.extra.extra",
104
- policy_with_silent_error: {errors: []}
105
- },
106
- _subschemes: {}
107
- }
108
- })
109
- end
110
-
111
- it "generates flatten data for documentation generation" do
112
- expect(schema.flatten_structure { |key, meta| meta[:block_works] = true if key.split(".").size == 1 }).to eq({
113
- "data" => {
114
- type: :object,
115
- required: true,
116
- present: true,
117
- block_works: true,
118
- json_path: "$.data"
119
- },
120
- "data.extra" => {
121
- type: :array,
122
- required: true,
123
- json_path: "$.data.extra[]"
124
- },
125
- "data.extra.extra" => {
126
- default: false,
127
- json_path: "$.data.extra[].extra",
128
- policy_with_silent_error: {errors: []}
129
- },
130
- "data.id" => {
131
- type: :integer,
132
- required: true,
133
- present: true,
134
- json_path: "$.data.id",
135
- policy_with_error: {errors: [ArgumentError]}
136
- },
137
- "data.name" => {
138
- type: :string,
139
- json_path: "$.data.name",
140
- label: "very important staff",
141
- mutates_schema: true
142
- },
143
- "data.role" => {
144
- type: :string,
145
- options: ["admin", "user"],
146
- default: "user",
147
- json_path: "$.data.role",
148
- mutates_schema: true
149
- },
150
- _errors: [ArgumentError],
151
- _subschemes: {
152
- test_subschema: {
153
- _errors: [],
154
- _subschemes: {},
155
- "data.test1"=>{
156
- required: true,
157
- present: true,
158
- json_path: "$.data.test1"
159
- }
160
- },
161
- subschema: {
162
- _errors: [],
163
- _subschemes: {},
164
- "data.test_field" => {required: true, present: true, json_path: "$.data.test_field"}
165
- }
166
- }
167
- })
168
- end
169
- end