paradocs 1.0.22 → 1.1.2
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/.readthedocs.yml +5 -0
- data/README.md +7 -1045
- data/docs/changelog.md +17 -0
- data/docs/custom_configuration.md +10 -0
- data/docs/documentation_generation.md +304 -0
- data/docs/faq.md +21 -0
- data/docs/form_objects_dsl.md +90 -0
- data/docs/index.md +106 -0
- data/docs/payload_builder.md +105 -0
- data/docs/policies.md +309 -0
- data/docs/schema.md +294 -0
- data/docs/struct.md +135 -0
- data/docs/subschema.md +29 -0
- data/lib/paradocs.rb +2 -1
- data/lib/paradocs/extensions/payload_builder.rb +44 -0
- data/lib/paradocs/extensions/structure.rb +116 -0
- data/lib/paradocs/policies.rb +0 -1
- data/lib/paradocs/schema.rb +30 -9
- data/lib/paradocs/struct.rb +4 -4
- data/lib/paradocs/version.rb +1 -1
- data/lib/paradocs/whitelist.rb +11 -10
- data/mkdocs.yml +17 -0
- data/paradocs.gemspec +4 -4
- data/requirements.txt +1 -0
- data/spec/extensions/payload_builder_spec.rb +70 -0
- data/spec/extensions/structures_spec.rb +244 -0
- data/spec/schema_spec.rb +1 -1
- data/spec/struct_spec.rb +37 -9
- data/spec/subschema_spec.rb +4 -4
- data/spec/whitelist_spec.rb +33 -0
- metadata +27 -10
- data/lib/paradocs/extensions/insides.rb +0 -77
- data/spec/schema_structures_spec.rb +0 -169
data/lib/paradocs/whitelist.rb
CHANGED
@@ -32,12 +32,14 @@ module Paradocs
|
|
32
32
|
|
33
33
|
def resolve(payload, schema, context)
|
34
34
|
filtered_payload = {}
|
35
|
+
coercion_block = Paradocs.config.whitelist_coercion
|
36
|
+
coercion_block = coercion_block.is_a?(Proc) && coercion_block
|
35
37
|
payload.dup.each do |key, value|
|
36
38
|
key = key.to_sym
|
37
39
|
schema = Schema.new if schema.nil?
|
38
40
|
schema.send(:flush!)
|
39
41
|
schema.send(:invoke_subschemes!, payload, context)
|
40
|
-
|
42
|
+
meta = get_meta_data(schema, key)
|
41
43
|
if value.is_a?(Hash)
|
42
44
|
field_schema = find_schema_by(schema, key)
|
43
45
|
value = resolve(value, field_schema, context)
|
@@ -47,13 +49,14 @@ module Paradocs
|
|
47
49
|
field_schema = find_schema_by(schema, key)
|
48
50
|
resolve(v, field_schema, context)
|
49
51
|
else
|
50
|
-
v = FILTERED unless whitelisted?(
|
52
|
+
v = FILTERED unless whitelisted?(meta, key)
|
51
53
|
v
|
52
54
|
end
|
53
55
|
end
|
54
56
|
else
|
55
|
-
|
56
|
-
|
57
|
+
|
58
|
+
value = if whitelisted?(meta, key)
|
59
|
+
coercion_block ? coercion_block.call(value, meta) : value
|
57
60
|
elsif value.nil? || value.try(:blank?) || value.try(:empty?)
|
58
61
|
!!value == value ? value : EMPTY
|
59
62
|
else
|
@@ -61,7 +64,6 @@ module Paradocs
|
|
61
64
|
end
|
62
65
|
value
|
63
66
|
end
|
64
|
-
|
65
67
|
filtered_payload[key] = value
|
66
68
|
end
|
67
69
|
|
@@ -71,13 +73,12 @@ module Paradocs
|
|
71
73
|
private
|
72
74
|
|
73
75
|
def find_schema_by(schema, key)
|
74
|
-
|
75
|
-
|
76
|
+
meta = get_meta_data(schema, key)
|
77
|
+
meta[:schema]
|
76
78
|
end
|
77
79
|
|
78
|
-
def whitelisted?(
|
79
|
-
|
80
|
-
meta_data[:whitelisted] || Paradocs.config.whitelisted_keys.include?(key)
|
80
|
+
def whitelisted?(meta, key)
|
81
|
+
meta[:whitelisted] || Paradocs.config.whitelisted_keys.include?(key)
|
81
82
|
end
|
82
83
|
|
83
84
|
def get_meta_data(schema, key)
|
data/mkdocs.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
site_name: Paradocs
|
2
|
+
theme:
|
3
|
+
name: readthedocs
|
4
|
+
nav_style: dark
|
5
|
+
nav:
|
6
|
+
- 'index.md'
|
7
|
+
- 'policies.md'
|
8
|
+
- 'schema.md'
|
9
|
+
- 'struct.md'
|
10
|
+
- 'form_objects_dsl.md'
|
11
|
+
- 'subschema.md'
|
12
|
+
- 'documentation_generation.md'
|
13
|
+
- 'payload_builder.md'
|
14
|
+
- 'custom_configuration.md'
|
15
|
+
- 'faq.md'
|
16
|
+
- 'changelog.md'
|
17
|
+
|
data/paradocs.gemspec
CHANGED
@@ -6,11 +6,11 @@ require 'paradocs/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "paradocs"
|
8
8
|
spec.version = Paradocs::VERSION
|
9
|
-
spec.authors = ["
|
10
|
-
spec.email = ["
|
9
|
+
spec.authors = ["Maxim Tkachenko", "Ismael Celis"]
|
10
|
+
spec.email = ["tkachenko.maxim.w@gmail.com", "ismaelct@gmail.com"]
|
11
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.}
|
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
|
-
spec.homepage = "https://
|
13
|
+
spec.homepage = "https://paradocs.readthedocs.io/en/latest"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 2.1"
|
22
|
-
spec.add_development_dependency "rake",
|
22
|
+
spec.add_development_dependency "rake", '~> 12.3'
|
23
23
|
spec.add_development_dependency "rspec", '3.4.0'
|
24
24
|
spec.add_development_dependency "pry", "~> 0"
|
25
25
|
end
|
data/requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
mkdocs==1.1.2
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Paradocs::Extensions::PayloadBuilder do
|
4
|
+
let(:schema) do
|
5
|
+
Paradocs::Schema.new do
|
6
|
+
field(:test).present.type(:string).mutates_schema! { :subschema1 }
|
7
|
+
subschema(:subschema1) do
|
8
|
+
field(:subtest1).declared.type(:number)
|
9
|
+
end
|
10
|
+
subschema(:subschema2) do
|
11
|
+
field(:subtest2).required.type(:array).schema do
|
12
|
+
field(:hello).type(:string).mutates_schema! { |*| :deep_schema }
|
13
|
+
subschema(:deep_schema) { field(:deep_field).type(:boolean) }
|
14
|
+
subschema(:empty) { }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# 2 mutation fields and more than 1 subschema pack work good in validation but docs
|
18
|
+
# will contain only 1 subschema at once: foo subschemes will never be mixed with test subschemes
|
19
|
+
field(:foo).required.type(:object).schema do
|
20
|
+
field(:bar).present.type(:string).options(["foo", "bar"]).mutates_schema! do |value, *|
|
21
|
+
value == "foo" ? :fooschema : :barschema
|
22
|
+
end
|
23
|
+
subschema(:fooschema) { }
|
24
|
+
subschema(:barschema) do
|
25
|
+
field(:barfield).present.type(:boolean)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "gives an example payload and takes into account the subschemes" do
|
32
|
+
allow_any_instance_of(Array).to receive(:sample) { "bar" }
|
33
|
+
payloads = described_class.new(schema).build!
|
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}})
|
36
|
+
expect(payloads[:fooschema]).to eq({"test" => nil, "foo" => {"bar" => "bar"}})
|
37
|
+
expect(payloads[:subschema1]).to eq({"test" => nil, "foo" => {"bar" => "bar"}, "subtest1" => nil})
|
38
|
+
expect(payloads[:subschema2_deep_schema]).to eq({
|
39
|
+
"subtest2" => [{"deep_field" => nil, "hello" => nil}], "test" => nil, "foo" => {"bar" => "bar"}
|
40
|
+
})
|
41
|
+
expect(payloads[:subschema2_empty]).to eq({
|
42
|
+
"test" => nil, "foo" => {"bar" => "bar"}, "subtest2" => [{"hello" => nil}]
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
it "yields a usefull block that changes the result" do
|
47
|
+
payloads = described_class.new(schema).build! do |key, meta, example, skip_word|
|
48
|
+
if key == "bar"
|
49
|
+
nil
|
50
|
+
elsif meta[:type] == :boolean
|
51
|
+
true
|
52
|
+
elsif key == "subtest1"
|
53
|
+
skip_word # this key value pair will be ommited
|
54
|
+
else
|
55
|
+
example # return suggested value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
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
|
61
|
+
expect(payloads[:fooschema]).to eq({"test" => nil, "foo" => {"bar" => nil}}) # bar is nil
|
62
|
+
expect(payloads[:subschema1]).to eq({"test" => nil, "foo" => {"bar" => nil}}) # subtest is missing, bar is nil
|
63
|
+
expect(payloads[:subschema2_deep_schema]).to eq({
|
64
|
+
"subtest2" => [{"deep_field" => true, "hello" => nil}], "test" => nil, "foo" => {"bar" => nil}
|
65
|
+
})
|
66
|
+
expect(payloads[:subschema2_empty]).to eq({
|
67
|
+
"test" => nil, "foo" => {"bar" => nil}, "subtest2" => [{"hello" => nil}]
|
68
|
+
})
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Paradocs::Extensions::Structure 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
|
+
describe "#nested" do
|
43
|
+
it "generates nested data for documentation generation" do
|
44
|
+
result = schema.structure.nested { |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
|
+
end
|
111
|
+
|
112
|
+
describe "#flatten" do
|
113
|
+
it "generates flatten data for documentation generation" do
|
114
|
+
expect(schema.structure.flatten { |key, meta| meta[:block_works] = true if key.split(".").size == 1 }).to eq({
|
115
|
+
"data" => {
|
116
|
+
type: :object,
|
117
|
+
required: true,
|
118
|
+
present: true,
|
119
|
+
block_works: true,
|
120
|
+
json_path: "$.data"
|
121
|
+
},
|
122
|
+
"data.extra" => {
|
123
|
+
type: :array,
|
124
|
+
required: true,
|
125
|
+
json_path: "$.data.extra[]"
|
126
|
+
},
|
127
|
+
"data.extra.extra" => {
|
128
|
+
default: false,
|
129
|
+
json_path: "$.data.extra[].extra",
|
130
|
+
policy_with_silent_error: {errors: []}
|
131
|
+
},
|
132
|
+
"data.id" => {
|
133
|
+
type: :integer,
|
134
|
+
required: true,
|
135
|
+
present: true,
|
136
|
+
json_path: "$.data.id",
|
137
|
+
policy_with_error: {errors: [ArgumentError]}
|
138
|
+
},
|
139
|
+
"data.name" => {
|
140
|
+
type: :string,
|
141
|
+
json_path: "$.data.name",
|
142
|
+
label: "very important staff",
|
143
|
+
mutates_schema: true
|
144
|
+
},
|
145
|
+
"data.role" => {
|
146
|
+
type: :string,
|
147
|
+
options: ["admin", "user"],
|
148
|
+
default: "user",
|
149
|
+
json_path: "$.data.role",
|
150
|
+
mutates_schema: true
|
151
|
+
},
|
152
|
+
_errors: [ArgumentError],
|
153
|
+
_subschemes: {
|
154
|
+
test_subschema: {
|
155
|
+
_errors: [],
|
156
|
+
_subschemes: {},
|
157
|
+
"data.test1"=>{
|
158
|
+
required: true,
|
159
|
+
present: true,
|
160
|
+
json_path: "$.data.test1"
|
161
|
+
}
|
162
|
+
},
|
163
|
+
subschema: {
|
164
|
+
_errors: [],
|
165
|
+
_subschemes: {},
|
166
|
+
"data.test_field" => {required: true, present: true, json_path: "$.data.test_field"}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
})
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#all_flatten" do
|
174
|
+
it "generates N structures, where N = number of unique combinations of applied subschemas" do
|
175
|
+
expect(schema.structure.all_flatten).to eq({
|
176
|
+
subschema: {
|
177
|
+
_errors: [ArgumentError],
|
178
|
+
"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},
|
181
|
+
"data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
|
182
|
+
"data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
|
183
|
+
"data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
|
184
|
+
"data.test_field" => {required: true, present: true, json_path: "$.data.test_field"}
|
185
|
+
},
|
186
|
+
test_subschema: {
|
187
|
+
_errors: [ArgumentError],
|
188
|
+
"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},
|
191
|
+
"data.role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", mutates_schema: true},
|
192
|
+
"data.extra" => {type: :array, required: true, json_path: "$.data.extra[]"},
|
193
|
+
"data.extra.extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra"},
|
194
|
+
"data.test1" => {required: true, present: true, json_path: "$.data.test1"}
|
195
|
+
}
|
196
|
+
})
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#all_nested" do
|
201
|
+
it "generates N structures, where N = number of unique combinations of applied subschemas" do
|
202
|
+
result = schema.structure.all_nested
|
203
|
+
expect(result[:subschema]).to eq({
|
204
|
+
_errors: [ArgumentError],
|
205
|
+
"data" => {
|
206
|
+
type: :object,
|
207
|
+
required: true,
|
208
|
+
present: true,
|
209
|
+
json_path: "$.data",
|
210
|
+
nested_name: "data",
|
211
|
+
structure: {
|
212
|
+
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", nested_name: "data.role", mutates_schema: true},
|
213
|
+
"test_field" => {required: true, present: true, json_path: "$.data.test_field", nested_name: "data.test_field"},
|
214
|
+
"id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
|
215
|
+
"name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
|
216
|
+
"extra" => {
|
217
|
+
type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
|
218
|
+
structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
})
|
223
|
+
expect(result[:test_subschema]).to eq({
|
224
|
+
_errors: [ArgumentError],
|
225
|
+
"data" => {
|
226
|
+
type: :object,
|
227
|
+
required: true,
|
228
|
+
present: true,
|
229
|
+
json_path: "$.data",
|
230
|
+
nested_name: "data",
|
231
|
+
structure: {
|
232
|
+
"role" => {type: :string, options: ["admin", "user"], default: "user", json_path: "$.data.role", nested_name: "data.role", mutates_schema: true},
|
233
|
+
"test1" => {required: true, present: true, json_path: "$.data.test1", nested_name: "data.test1"},
|
234
|
+
"id" => {type: :integer, required: true, present: true, policy_with_error: {errors: [ArgumentError]}, json_path: "$.data.id", nested_name: "data.id"},
|
235
|
+
"name" => {type: :string, label: "very important staff", json_path: "$.data.name", mutates_schema: true, nested_name: "data.name"},
|
236
|
+
"extra" => {
|
237
|
+
type: :array, required: true, json_path: "$.data.extra[]", nested_name: "data.extra",
|
238
|
+
structure: {"extra" => {default: false, policy_with_silent_error: {errors: []}, json_path: "$.data.extra[].extra", nested_name: "data.extra.extra"}}}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
})
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
data/spec/schema_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe Paradocs::Schema do
|
|
32
32
|
|
33
33
|
describe "#structure" do
|
34
34
|
it "represents data structure and meta data" do
|
35
|
-
sc = subject.structure
|
35
|
+
sc = subject.structure.nested
|
36
36
|
expect(sc[:title][:present]).to be true
|
37
37
|
expect(sc[:title][:type]).to eq :string
|
38
38
|
expect(sc[:price][:type]).to eq :integer
|
data/spec/struct_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'paradocs/struct'
|
3
3
|
|
4
4
|
describe Paradocs::Struct do
|
5
|
-
it
|
5
|
+
it 'works' do
|
6
6
|
friend_class = Class.new do
|
7
7
|
include Paradocs::Struct
|
8
8
|
|
@@ -53,7 +53,7 @@ describe Paradocs::Struct do
|
|
53
53
|
expect(invalid_instance.friends[1].errors['$.name']).not_to be_nil
|
54
54
|
end
|
55
55
|
|
56
|
-
it
|
56
|
+
it 'is inmutable by default' do
|
57
57
|
klass = Class.new do
|
58
58
|
include Paradocs::Struct
|
59
59
|
|
@@ -66,7 +66,7 @@ describe Paradocs::Struct do
|
|
66
66
|
|
67
67
|
instance = klass.new
|
68
68
|
expect {
|
69
|
-
instance.title =
|
69
|
+
instance.title = 'foo'
|
70
70
|
}.to raise_error NoMethodError
|
71
71
|
|
72
72
|
expect {
|
@@ -74,7 +74,7 @@ describe Paradocs::Struct do
|
|
74
74
|
}.to raise_error RuntimeError
|
75
75
|
end
|
76
76
|
|
77
|
-
it
|
77
|
+
it 'works with anonymous nested schemas' do
|
78
78
|
klass = Class.new do
|
79
79
|
include Paradocs::Struct
|
80
80
|
|
@@ -125,7 +125,7 @@ describe Paradocs::Struct do
|
|
125
125
|
expect(user.friends.first.salutation).to eq 'my age is 43'
|
126
126
|
end
|
127
127
|
|
128
|
-
it
|
128
|
+
it 'wraps regular schemas in structs' do
|
129
129
|
friend_schema = Paradocs::Schema.new do
|
130
130
|
field(:name)
|
131
131
|
end
|
@@ -147,7 +147,7 @@ describe Paradocs::Struct do
|
|
147
147
|
expect(instance.friends.first.name).to eq 'Ismael'
|
148
148
|
end
|
149
149
|
|
150
|
-
it
|
150
|
+
it '#to_h' do
|
151
151
|
klass = Class.new do
|
152
152
|
include Paradocs::Struct
|
153
153
|
|
@@ -185,7 +185,7 @@ describe Paradocs::Struct do
|
|
185
185
|
expect(new_instance.to_h[:title]).to eq 'foo'
|
186
186
|
end
|
187
187
|
|
188
|
-
it
|
188
|
+
it 'works with inheritance' do
|
189
189
|
klass = Class.new do
|
190
190
|
include Paradocs::Struct
|
191
191
|
|
@@ -218,7 +218,7 @@ describe Paradocs::Struct do
|
|
218
218
|
expect(instance.friends.size).to eq 2
|
219
219
|
end
|
220
220
|
|
221
|
-
it
|
221
|
+
it 'implements deep struct equality' do
|
222
222
|
klass = Class.new do
|
223
223
|
include Paradocs::Struct
|
224
224
|
|
@@ -268,7 +268,7 @@ describe Paradocs::Struct do
|
|
268
268
|
expect(s1 == s4).to be false
|
269
269
|
end
|
270
270
|
|
271
|
-
it
|
271
|
+
it '#merge returns a new instance' do
|
272
272
|
klass = Class.new do
|
273
273
|
include Paradocs::Struct
|
274
274
|
|
@@ -301,6 +301,20 @@ describe Paradocs::Struct do
|
|
301
301
|
expect(copy.friends.first.name).to eq 'jane'
|
302
302
|
end
|
303
303
|
|
304
|
+
it 'passes the environment to the schema' do
|
305
|
+
klass = Class.new do
|
306
|
+
include Paradocs::Struct
|
307
|
+
|
308
|
+
schema do
|
309
|
+
field(:age).type(:integer)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
new_instance = klass.new({}, { key: :value })
|
314
|
+
|
315
|
+
expect(new_instance.send(:_results).environment).to eq({ key: :value })
|
316
|
+
end
|
317
|
+
|
304
318
|
describe '.new!' do
|
305
319
|
it 'raises a useful exception if invalid data' do
|
306
320
|
klass = Class.new do
|
@@ -320,5 +334,19 @@ describe Paradocs::Struct do
|
|
320
334
|
valid = klass.new!(title: 'foo')
|
321
335
|
expect(valid.title).to eq 'foo'
|
322
336
|
end
|
337
|
+
|
338
|
+
it 'passes the environment to the schema' do
|
339
|
+
klass = Class.new do
|
340
|
+
include Paradocs::Struct
|
341
|
+
|
342
|
+
schema do
|
343
|
+
field(:title).type(:string).present
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
new_instance = klass.new!({ title: 'test' }, { key: :value })
|
348
|
+
|
349
|
+
expect(new_instance.send(:_results).environment).to eq({ key: :value })
|
350
|
+
end
|
323
351
|
end
|
324
352
|
end
|