paradocs 1.1.0 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0df2185fac7b1e70254c9531622e135c6609f309
4
- data.tar.gz: 701ec92673e9044bc8a8384e251276aa7863d37e
3
+ metadata.gz: ba77710f31f4b6d12c2c764807c1274a7409e18f
4
+ data.tar.gz: 79e70eed1f40fbc5b2c7fab32b935ecee813b7b8
5
5
  SHA512:
6
- metadata.gz: aa14905a01be3d1d54589aabc53fbc2f14d3a17352742a9eece1e76b324f146d94f5860ae4f59d738007e809c1fb0eb3ae95579d2a8237798e80a7a6f43ff2b9
7
- data.tar.gz: 0c5fedee64178f630d403db573b2d8a4e2e4bc44b88e65df636c88aa1d9857836267d77ed34a1236036ff97bb105e37252f4948d46fcdc600850e682a5db082d
6
+ metadata.gz: 2365143b9765af228b14ed88105837d34fdba6b3da914e7cf71750e6bea120d6418767b7cd94678480b97ab7735af049129c3c180a6f46d7d590630d09f0d490
7
+ data.tar.gz: eae4b0b0593f473ac51fc5214bef19c8571490cde4a63b6274a755fc81c1099c226030eaeec56eb15eb91e4263062c57d0c31bf7c50bd01038ef3371c7382031
data/README.md CHANGED
@@ -37,14 +37,4 @@ form.errors # => {}
37
37
  ```
38
38
 
39
39
  ## Learn more
40
- - [Getting Started](https://github.com/mtkachenk0/paradocs/wiki/Getting-Started)
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)
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## 1.1.2
4
+ - Regenerate structures each time without saving them into instance attributes.
5
+
6
+ ## 1.1.1
7
+ - Fixed bug with missing `errors` meta key in `Structure#all_nested` and `Structure#all_flatten` methods.
8
+ - Fixed bug with absent `nested_name` meta key in `#Structure#all_nested` method.
9
+ - Added opportunity to sort generated by `PayloadBuilder` payload in the way it is described in schema.
10
+
11
+ ## 1.1.0
12
+ > `Schema#structure` is not comptatible with previous versions
13
+
14
+ - Added `Paradocs::Extensions::StructureBuilder`. See [more](payload_builder)
15
+ - `Parardocs::Extensions::Structure` has replaced `Paradocs::Extensions::Insides` and changed `Schema#structure` behavior
16
+ - `Paradocs::Extensions::Structure` got more structure generation methods. See [Documentation Generation](documentation_generation)
17
+
@@ -188,12 +188,16 @@ all_nested[:subschema] # =>
188
188
  required: true,
189
189
  present: true,
190
190
  json_path: "$.data",
191
+ nested_name: "data",
191
192
  structure: {
192
- "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
193
- "extra" => {type: :array, required: true, json_path: "$.data.extra[]", structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"}}},
194
- "test_field" => {required: true, present: true, json_path: "$.data.test_field"},
195
- "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
196
- "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true}
193
+ "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
194
+ "test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"},
195
+ "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
196
+ "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
197
+ "extra" => {
198
+ type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
199
+ structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}
200
+ }
197
201
  }
198
202
  }
199
203
  }
@@ -205,12 +209,16 @@ all_nested[:test_subschema] # =>
205
209
  required: true,
206
210
  present: true,
207
211
  json_path: "$.data",
212
+ nested_name: "data",
208
213
  structure: {
209
- "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
210
- "extra" => {type: :array, required: true, json_path: "$.data.extra[]", structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"}}},
211
- "test1" => {required: true, present: true, json_path: "$.data.test1"},
212
- "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
213
- "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true}
214
+ "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
215
+ "test1" => {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"},
216
+ "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
217
+ "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
218
+ "extra" => {
219
+ type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
220
+ structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}
221
+ }
214
222
  }
215
223
  }
216
224
  }
@@ -219,33 +227,38 @@ all_nested[:test_subschema] # =>
219
227
  ## Structure#all_flatten
220
228
  > This method returns all available combinations of schema (built on subschema) without nesting (the same way as Structure#flatten method does)
221
229
 
222
- Schema is the same as described in Structure#all_nested
230
+ Schema is the same as described in `Structure#all_nested`
223
231
  ```rb
224
232
  schema.structure.all_flatten # =>
225
233
  {
226
234
  subschema: {
227
235
  _errors: [],
228
- "data" => {type: :object, required: true, present: true, json_path: "$.data"},
229
- "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
230
- "data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true},
231
- "data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
232
- "data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
233
- "data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
234
- "data.test_field" => {required: true, present: true, json_path: "$.data.test_field"}
236
+ "data" => {type: :object, required: true, present: true, json_path: "$.data", nested_name: "data"},
237
+ "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
238
+ "data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
239
+ "data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
240
+ "data.extra" => {type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra"},
241
+ "data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"},
242
+ "data.test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"}
235
243
  },
236
244
  test_subschema: {
237
245
  _errors: [],
238
- "data" => {type: :object, required: true, present: true, json_path: "$.data"},
239
- "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
240
- "data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true},
241
- "data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
242
- "data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
243
- "data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
244
- "data.test1" => {required: true, present: true, json_path: "$.data.test1"}
246
+ "data" => {type: :object, required: true, present: true, json_path: "$.data", nested_name: "data"},
247
+ "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
248
+ "data.name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
249
+ "data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true, nested_name: "data.role"},
250
+ "data.extra" => {type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra"},
251
+ "data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"},
252
+ "data.test1" => {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"}
245
253
  }
246
254
  }
247
255
  ```
248
256
 
257
+ ## Passing a block
258
+ Given block to the methods above (`#flatten`, `#nested`, `#all_flatten`, `#all_nested`) will be executed for
259
+ each field, passing you as arguments `field.key` and `field.meta`. Mutating the second argument `field.meta`
260
+ will reflect onto returned `meta`.
261
+
249
262
  ## Schema#walk
250
263
 
251
264
  The `#walk` method can recursively walk a schema definition and extract meta data or field attributes.
@@ -1,9 +1,8 @@
1
1
  # Generate examples from the Schema
2
2
 
3
- > Schema instance provides #example_payloads method that returns example of all possible structures.
3
+ > `Schema` instance provides `#example_payloads` method that returns example of all possible structures.
4
4
 
5
- NOTE: PayloadBuilder sets nil values by default. If options are given - builder will take on of them, if default is set - builder will use it.
6
- > PayloadBuilder#build! method takes a block as argument that may help you adding your custom rules.
5
+ NOTE: `PayloadBuilder` sets nil values by default. If options are given - builder will take on of them, if default is set - builder will use it.
7
6
 
8
7
  #### Example schema
9
8
  ```ruby
@@ -59,12 +58,14 @@ schema.example_payloads.to_json # =>
59
58
  ```
60
59
 
61
60
  ## Customize payload generation logic
62
- PayloadBuilder#build! allows passing a block that will receive the following arguments:
61
+ `PayloadBuilder#build!` arguments:
63
62
 
64
- - key: Field name
65
- - meta: Field meta data (that includes (if provided) field types, presence data, policies and other meta data
66
- - example_value: Provided by generator example value.
67
- - skip_word: Return this argument back if you want this item to be ommitted.
63
+ 1. `sort_by_schema: true` will try to return payload in the same way as declared in the schema.
64
+ 2. `&block` will be executed for each key receiving the following arguments:
65
+ - `key`: Field name
66
+ - `meta`: Field meta data (that includes (if provided) field types, presence data, policies and other meta data
67
+ - `example_value`: Provided by generator example value.
68
+ - `skip_word`: Return this argument back if you want this item to be ommitted.
68
69
 
69
70
  ```rb
70
71
  block = Proc.new do |key, meta, example, skip_word|
@@ -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)
@@ -8,8 +8,9 @@ module Paradocs
8
8
  @skip_word = skip_word
9
9
  end
10
10
 
11
- def build!(&block)
12
- structure.all_nested.map { |name, struct| [name, build_simple_structure(struct, &block)] }.to_h
11
+ def build!(sort_by_schema: false, &block)
12
+ result = structure.all_nested.map { |name, struct| [name, build_simple_structure(struct, &block)] }.to_h
13
+ sort_by_schema ? schema.resolve(result).output : result
13
14
  end
14
15
 
15
16
  private
@@ -20,7 +21,8 @@ module Paradocs
20
21
  next if key.start_with?(Paradocs.config.meta_prefix) # skip all the meta fields
21
22
  ex_value = restore_one(key, value, &block)
22
23
  next if ex_value == @skip_word
23
- [key, ex_value]
24
+ key = value[:alias] || key
25
+ [key.to_s, ex_value]
24
26
  end.compact.to_h
25
27
  end
26
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
- @nested ||= schema.fields.each_with_object({errors => [], subschemes => {}}) do |(_, field), result|
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
- result[field.key] = meta unless ignore_transparent && field.transparent?
31
- yield(field.key, meta) if block_given?
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,12 +37,13 @@ module Paradocs
39
37
  end
40
38
 
41
39
  def all_nested(&block)
42
- @all_nested ||= all_flatten(&block).each_with_object({}) do |(name, struct), obj|
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|
46
44
  target = obj[name]
47
45
  key, value = key.to_s, value.clone # clone the values, because we do mutation below
46
+ value.merge!(nested_name: key) if value.respond_to?(:merge) # it can be array (_errors)
48
47
  next target[key.to_sym] = value if key.start_with?(Paradocs.config.meta_prefix) # copy meta fields
49
48
 
50
49
  parts = key.split(".")
@@ -60,17 +59,18 @@ module Paradocs
60
59
  end
61
60
 
62
61
  def all_flatten(schema_structure=nil, &block)
63
- return @all_flatten if @all_flatten
64
62
  schema_structure ||= flatten(&block)
65
63
  if schema_structure[subschemes].empty?
66
64
  schema_structure.delete(subschemes) # don't include redundant key
67
- return @all_flatten = {DEFAULT => schema_structure}
65
+ return {DEFAULT => schema_structure}
68
66
  end
69
- @all_flatten = schema_structure[subschemes].each_with_object({}) do |(name, subschema), result|
67
+ schema_structure[subschemes].each_with_object({}) do |(name, subschema), result|
70
68
  if subschema[subschemes].empty?
71
- result[name] = schema_structure.merge(subschema)
72
- result[name].delete(subschemes)
73
- next result[name]
69
+ result[name] = schema_structure.merge(subschema)
70
+ result[name][errors] += schema_structure[errors]
71
+ result[name][errors].uniq!
72
+ result[name].delete(subschemes)
73
+ next result[name]
74
74
  end
75
75
 
76
76
  all_flatten(subschema).each do |sub_name, schema|
@@ -80,7 +80,7 @@ module Paradocs
80
80
  end
81
81
 
82
82
  def flatten(&block)
83
- @flatten ||= schema.fields.each_with_object({errors => [], subschemes => {}}) do |(_, field), obj|
83
+ schema.fields.each_with_object({errors => [], subschemes => {}}) do |(_, field), obj|
84
84
  meta, sc = collect_meta(field, root)
85
85
  humanized_name = meta.delete(:nested_name)
86
86
  obj[humanized_name] = meta unless ignore_transparent && field.transparent?
@@ -105,7 +105,8 @@ module Paradocs
105
105
  private
106
106
 
107
107
  def collect_meta(field, root)
108
- json_path = root.empty? ? "$.#{field.key}" : "#{root}.#{field.key}"
108
+ field_key = field.meta_data[:alias] || field.key
109
+ json_path = root.empty? ? "$.#{field_key}" : "#{root}.#{field_key}"
109
110
  meta = field.meta_data.merge(json_path: json_path)
110
111
  sc = meta.delete(:schema)
111
112
  meta[:mutates_schema] = true if meta.delete(:mutates_schema)
@@ -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
@@ -5,7 +5,7 @@ module Paradocs
5
5
  class Format < Paradocs::BasePolicy
6
6
  attr_reader :message
7
7
 
8
- def initialize(fmt, msg = "invalid format")
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
@@ -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
- m[field.key] = r.value if r.eligible?
184
+ key = field.meta_data[:alias] || field.key
185
+ m[key] = r.value if r.eligible?
185
186
  end
186
187
  end
187
188
 
@@ -57,6 +57,7 @@ module Paradocs
57
57
  # this hook is called after schema definition in DSL module
58
58
  def paradocs_after_define_schema(schema)
59
59
  schema.fields.keys.each do |key|
60
+ key = schema.fields[key].meta_data[:alias] || key
60
61
  define_method key do
61
62
  _graph[key]
62
63
  end
@@ -1,3 +1,3 @@
1
1
  module Paradocs
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.5"
3
3
  end
data/mkdocs.yml CHANGED
@@ -13,4 +13,5 @@ nav:
13
13
  - 'payload_builder.md'
14
14
  - 'custom_configuration.md'
15
15
  - 'faq.md'
16
+ - 'changelog.md'
16
17
 
@@ -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 DSL for declaring allowed parameters focused on DRY validation that gives you opportunity to generate API documentation on-the-fly.}
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"
@@ -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", "barfield" => nil}})
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, "barfield" => true}}) # barfield is change to true and bar is 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[:id]).to eq({
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
- json_path: "$.data.id",
73
- nested_name: "data.id"
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.id" => {
135
+ "data.user_id" => {
133
136
  type: :integer,
134
137
  required: true,
135
138
  present: true,
136
- json_path: "$.data.id",
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" => {
@@ -174,20 +180,20 @@ describe Paradocs::Extensions::Structure do
174
180
  it "generates N structures, where N = number of unique combinations of applied subschemas" do
175
181
  expect(schema.structure.all_flatten).to eq({
176
182
  subschema: {
177
- _errors: [],
183
+ _errors: [ArgumentError],
178
184
  "data" => {type: :object, required: true, present: true, json_path: "$.data"},
179
- "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
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"},
184
190
  "data.test_field" => {required: true, present: true, json_path: "$.data.test_field"}
185
191
  },
186
192
  test_subschema: {
187
- _errors: [],
193
+ _errors: [ArgumentError],
188
194
  "data" => {type: :object, required: true, present: true, json_path: "$.data"},
189
- "data.id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
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"},
@@ -201,34 +207,41 @@ describe Paradocs::Extensions::Structure do
201
207
  it "generates N structures, where N = number of unique combinations of applied subschemas" do
202
208
  result = schema.structure.all_nested
203
209
  expect(result[:subschema]).to eq({
204
- _errors: [],
210
+ _errors: [ArgumentError],
205
211
  "data" => {
206
- type: :object,
207
- required: true,
208
- present: true,
209
- json_path: "$.data",
212
+ type: :object,
213
+ required: true,
214
+ present: true,
215
+ json_path: "$.data",
216
+ nested_name: "data",
210
217
  structure: {
211
- "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
212
- "extra" => {type: :array, required: true, json_path: "$.data.extra[]", structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"}}},
213
- "test_field" => {required: true, present: true, json_path: "$.data.test_field"},
214
- "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
215
- "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true}
218
+ "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", nested_name: "data.role", mutates_schema: true},
219
+ "test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"},
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"},
222
+ "extra" => {
223
+ type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
224
+ structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}
225
+ }
216
226
  }
217
227
  }
218
228
  })
219
229
  expect(result[:test_subschema]).to eq({
220
- _errors: [],
230
+ _errors: [ArgumentError],
221
231
  "data" => {
222
232
  type: :object,
223
233
  required: true,
224
234
  present: true,
225
235
  json_path: "$.data",
236
+ nested_name: "data",
226
237
  structure: {
227
- "role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
228
- "extra" => {type: :array, required: true, json_path: "$.data.extra[]", structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"}}},
229
- "test1" => {required: true, present: true, json_path: "$.data.test1"},
230
- "id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id"},
231
- "name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true}
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" => {
243
+ type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
244
+ structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}}
232
245
  }
233
246
  }
234
247
  })
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Paradocs::Field do
4
- let(:context) { Paradocs::Context.new }
4
+ let(:context) { Paradocs::Context.new }
5
5
 
6
6
  subject { described_class.new(:a_key) }
7
7
 
@@ -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[:title][:present]).to be true
37
- expect(sc[:title][:type]).to eq :string
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
- title: "title",
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
- title: 'iPhone 6 Plus',
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
- title: 'iPhone 6 Plus',
117
+ article_title: 'iPhone 6 Plus',
118
118
  variants: [{name: 'v1', stock: 1, available_if_no_stock: true}]
119
119
  })
120
120
 
@@ -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.title).to eq ''
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.title).to eq 'foo'
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
- {name: 'Jane', age: 20},
175
- {name: 'Joe', age: 39},
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.title).to eq 'foo'
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
@@ -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.0
4
+ version: 1.1.5
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-09-10 00:00:00.000000000 Z
12
+ date: 2020-11-23 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 DSL for declaring allowed parameters focused on DRY validation
71
- that gives you opportunity to generate API documentation on-the-fly.
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
@@ -88,6 +88,7 @@ files:
88
88
  - README.md
89
89
  - Rakefile
90
90
  - bin/console
91
+ - docs/changelog.md
91
92
  - docs/custom_configuration.md
92
93
  - docs/documentation_generation.md
93
94
  - docs/faq.md