lurker 0.6.4 → 0.6.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: 6f19d765a42825a49246ece3cfe310a71ef07026
4
- data.tar.gz: 04db573bb51da7ac28f3f55c5a85990e6bb6768b
3
+ metadata.gz: a7c38c4fffd08ae1bcd1b7505298b8b1aaa1a6d2
4
+ data.tar.gz: ed4335b7f4d6d483482d1690882a6ab3a0518c97
5
5
  SHA512:
6
- metadata.gz: 4d203a0847bda1f56a2b8b39eda067d0d40f1ddde7bd27c5e800ae61f3000c7cae600c076d619bfc634c087c9f9e4480e6982c745c1f267c3689ec46d77671e7
7
- data.tar.gz: 98af7ab781606392252390b6f7f74a844b56d1d61910acd2b6b2c180fbb06dc03ed43b03b6b2d34f59dec7c5cdcc681a0bc188d6235d662335d54f1aa75638d9
6
+ metadata.gz: f989bfea051dc26d3d52fc169b02fe3addcc9b36e8512f55ae3523bdbc162ffa155e36d4a801945cc1872c0e7533f21ef105b179d92bc8f0ccc7cb131b84fe41
7
+ data.tar.gz: d5efae11ebaaeb2e4d5af01008ff0f06f5154c30612f0f8dcabb41e103d2c6190ce6a8a0035b65a9fe6e6f6350790f75a96946665daa9379ee75b24304526a6b
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -80,23 +80,23 @@ Feature: $ref defererencing through inlining
80
80
  Then the file "lurker/definitions/user_request_parameters.json" should contain exactly:
81
81
  """json
82
82
  {
83
- "description": "",
84
- "type": "object",
85
- "additionalProperties": false,
86
- "required": [
87
-
88
- ],
89
83
  "properties": {
90
84
  "name": {
91
- "description": "",
92
85
  "type": "string",
93
- "example": "Bob"
86
+ "example": "Bob",
87
+ "description": ""
94
88
  },
95
89
  "surname": {
96
90
  "description": "",
97
91
  "type": "string",
98
92
  "example": "Marley"
99
93
  }
100
- }
94
+ },
95
+ "description": "",
96
+ "type": "object",
97
+ "additionalProperties": false,
98
+ "required": [
99
+
100
+ ]
101
101
  }
102
102
  """
@@ -76,6 +76,7 @@ require 'lurker/json/schema'
76
76
  require 'lurker/json/schema/object'
77
77
  require 'lurker/json/schema/list'
78
78
  require 'lurker/json/schema/attribute'
79
+ require 'lurker/json/schema/polymorph'
79
80
  require 'lurker/json/schema/tuple'
80
81
  require 'lurker/json/schema/tuple/all_of'
81
82
  require 'lurker/json/schema/tuple/any_of'
@@ -15,6 +15,7 @@ module Lurker
15
15
  @root_schema = options[:root_schema]
16
16
  @parent_schema = options[:parent_schema]
17
17
  @parent_property = options[:parent_property]
18
+ @polymorph_if_empty = options.fetch(:polymorph_if_empty, false)
18
19
  @uri = options[:uri] || @parent_schema.try(:uri)
19
20
  @strategy = nil
20
21
  end
@@ -64,7 +65,7 @@ module Lurker
64
65
 
65
66
  def schema_options
66
67
  {
67
- uri: @uri, root_schema: @root_schema,
68
+ uri: @uri, root_schema: @root_schema, polymorph_if_empty: @polymorph_if_empty,
68
69
  parent_schema: @parent_schema, parent_property: @parent_property
69
70
  }
70
71
  end
@@ -4,6 +4,12 @@ module Lurker
4
4
  module Expertise
5
5
  module_function
6
6
 
7
+ def type_polymorph?(array_or_hash)
8
+ return false unless array_or_hash.is_a?(Hash) || array_or_hash.is_a?(Array)
9
+
10
+ array_or_hash.empty?
11
+ end
12
+
7
13
  def type_defined?(hash)
8
14
  return false unless hash.is_a?(Hash)
9
15
 
@@ -7,7 +7,10 @@ module Lurker
7
7
  attr_reader :schema_options
8
8
 
9
9
  def initialize(options)
10
- @schema_options = options.dup
10
+ options = options.dup
11
+
12
+ @polymorph_if_empty = options.delete(:polymorph_if_empty)
13
+ @schema_options = options
11
14
  end
12
15
 
13
16
  def parse(payload)
@@ -17,9 +20,12 @@ module Lurker
17
20
  when Hash
18
21
  return create_by_type(payload) if type_defined?(payload)
19
22
  return create_by_supposition(payload) if type_supposed?(payload)
23
+ return create_polymorph(payload) if polymorph_if_empty? && type_polymorph?(payload)
20
24
 
21
25
  Lurker::Json::Object.new(payload, schema_options)
22
26
  when Array
27
+ return create_polymorph(payload) if polymorph_if_empty? && type_polymorph?(payload)
28
+
23
29
  Lurker::Json::List.new(payload, schema_options)
24
30
  else
25
31
  Lurker::Json::Attribute.new(payload, schema_options)
@@ -56,6 +62,14 @@ module Lurker
56
62
  Lurker::Json::Attribute.new(payload, schema_options)
57
63
  end
58
64
  end
65
+
66
+ def polymorph_if_empty?
67
+ @polymorph_if_empty
68
+ end
69
+
70
+ def create_polymorph(payload)
71
+ Lurker::Json::Polymorph.new(payload, schema_options)
72
+ end
59
73
  end
60
74
  end
61
75
  end
@@ -107,7 +107,7 @@ module Lurker
107
107
  when RESPONSE_CODES
108
108
  Lurker::Json::ResponseCodes.new(property_schema, subschema_options)
109
109
  when REQUEST_PARAMETERS, RESPONSE_PARAMETERS
110
- @parser.typed.parse_property(property, property_schema)
110
+ @parser.typed(polymorph_if_empty: true).parse_property(property, property_schema)
111
111
  else
112
112
  @parser.plain.parse_property(property, property_schema)
113
113
  end
@@ -44,15 +44,22 @@ module Lurker
44
44
 
45
45
  private
46
46
 
47
+ def initialize_default_properties
48
+ @schema[Json::DESCRIPTION] ||= ''
49
+ @schema[Json::TYPE] ||= ''
50
+ @schema[Json::EXAMPLE] = '' if @schema[Json::EXAMPLE].nil?
51
+ end
52
+
47
53
  def parse_schema(schema)
48
54
  @schema = {}
49
- initialize_properties
50
55
 
51
56
  if schema.is_a?(Hash)
52
57
  @schema.merge!(schema)
53
58
  else
54
59
  @schema = attributify(schema)
55
60
  end
61
+
62
+ initialize_default_properties
56
63
  end
57
64
 
58
65
  def attributify(schema)
@@ -71,12 +78,6 @@ module Lurker
71
78
  attribute
72
79
  end
73
80
 
74
- def initialize_properties
75
- @schema[Json::DESCRIPTION] ||= ''
76
- @schema[Json::TYPE] ||= ''
77
- @schema[Json::EXAMPLE] ||= ''
78
- end
79
-
80
81
  def serialize_example(data)
81
82
  if data.is_a?(ActionDispatch::Http::UploadedFile)
82
83
  data.headers
@@ -19,28 +19,35 @@ module Lurker
19
19
 
20
20
  private
21
21
 
22
+ def initialize_default_properties(empty_items = {})
23
+ @schema[Json::TYPE] ||= Json::ARRAY
24
+ @schema[Json::ITEMS] ||= polymorph_items(empty_items)
25
+ end
26
+
22
27
  def parse_schema(schema)
23
28
  @schema = {}
24
- initialize_properties
29
+ schema.is_a?(Array) ? parse_array(schema.dup) : parse_hash(schema.dup)
30
+ end
25
31
 
32
+ def parse_array(schema)
33
+ initialize_default_properties([])
26
34
  return if schema.empty?
27
35
 
28
- schema = schema.dup
29
- if schema.is_a?(Array)
30
- @schema[Json::ITEMS] = @parser.typed.parse(schema.shift)
36
+ @schema[Json::ITEMS] = @parser.typed.parse(schema.shift)
37
+ schema.each { |payload| @schema[Json::ITEMS].merge!(payload) }
38
+ end
31
39
 
32
- schema.each { |payload| @schema[Json::ITEMS].merge!(payload) }
33
- else
34
- @schema[Json::ITEMS] = @parser.typed.parse(schema.delete Json::ITEMS) if schema.key?(Json::ITEMS)
35
- @schema.merge!(schema)
36
- end
40
+ def parse_hash(schema)
41
+ @schema.merge!(schema)
42
+ @schema[Json::ITEMS] = @parser.typed(polymorph_if_empty: true)
43
+ .parse(schema.delete(Json::ITEMS) || schema)
37
44
 
38
- @schema
45
+ initialize_default_properties
39
46
  end
40
47
 
41
- def initialize_properties
42
- @schema[Json::TYPE] ||= Json::ARRAY
43
- @schema[Json::ITEMS] ||= []
48
+ def polymorph_items(schema)
49
+ options = subschema_options.merge!(parent_property: Json::ITEMS)
50
+ Lurker::Json::Polymorph.new(schema, options)
44
51
  end
45
52
  end
46
53
  end
@@ -3,8 +3,6 @@ module Lurker
3
3
  class Object < Schema
4
4
  def merge!(schema)
5
5
  unless schema.is_a?(Hash)
6
- return replace_with_new_type(schema) if @schema[Json::PROPERTIES].blank?
7
-
8
6
  raise TypeError, "Unable to merge #{schema.class} into JSON object"
9
7
  end
10
8
 
@@ -25,35 +23,28 @@ module Lurker
25
23
 
26
24
  private
27
25
 
26
+ def initialize_default_properties
27
+ @schema[Json::DESCRIPTION] ||= ''
28
+ @schema[Json::TYPE] ||= Json::OBJECT
29
+ @schema[Json::ADDITIONAL_PROPERTIES] = !!@schema[Json::ADDITIONAL_PROPERTIES]
30
+ @schema[Json::REQUIRED] ||= []
31
+ @schema[Json::PROPERTIES] ||= {}
32
+ end
33
+
28
34
  def parse_schema(schema)
29
35
  @schema = {}
30
- initialize_properties
31
36
 
32
37
  schema = schema.dup
33
- merge_required = schema.key?(Json::PROPERTIES)
38
+ if schema.key?(Json::PROPERTIES)
39
+ @schema.merge!(schema)
40
+ end
41
+
42
+ initialize_default_properties
34
43
 
35
44
  (schema.delete(Json::PROPERTIES) || schema).each do |property, property_schema|
36
45
  @schema[Json::PROPERTIES][property] = @parser.typed.parse_property(
37
46
  property, property_schema)
38
47
  end
39
-
40
- @schema.merge!(schema) if merge_required
41
- end
42
-
43
- def replace_with_new_type(schema)
44
- replace_options = {root_schema: root_schema, parent_schema: parent_schema,
45
- parent_property: parent_property}
46
-
47
- new_schema = Lurker::Json::Parser.typed(replace_options).parse(schema)
48
- parent_schema.replace!(parent_property, new_schema)
49
- end
50
-
51
- def initialize_properties
52
- @schema[Json::DESCRIPTION] ||= ''
53
- @schema[Json::TYPE] ||= Json::OBJECT
54
- @schema[Json::ADDITIONAL_PROPERTIES] = !!@schema[Json::ADDITIONAL_PROPERTIES]
55
- @schema[Json::REQUIRED] ||= []
56
- @schema[Json::PROPERTIES] ||= {}
57
48
  end
58
49
  end
59
50
  end
@@ -0,0 +1,54 @@
1
+ module Lurker
2
+ module Json
3
+ class Polymorph < Schema
4
+ def merge!(schema)
5
+ case parent_schema
6
+ when Lurker::Json::Object
7
+ parent_schema[Json::PROPERTIES][parent_property] = @parser.typed.parse(schema)
8
+ when Lurker::Json::List
9
+ if schema.is_a?(Array)
10
+ return if schema.empty?
11
+
12
+ schema = schema.dup
13
+ parent_schema[Json::ITEMS] = @parser.typed.parse(schema.shift)
14
+ parent_schema.merge!(schema)
15
+ else
16
+ parent_schema[Json::ITEMS] = @parser.typed.parse(schema)
17
+ end
18
+ else
19
+ parent_schema[parent_property] = @parser.typed.parse(schema)
20
+ end
21
+ end
22
+
23
+ def replace!(property, schema)
24
+ morph = Lurker::Json::Object.new({}, subschema_options)
25
+
26
+ case parent_schema
27
+ when Lurker::Json::Object
28
+ parent_schema[Json::PROPERTIES][parent_property] = morph
29
+ parent_schema.replace!(property, schema)
30
+ when Lurker::Json::List
31
+ parent_schema[Json::ITEMS] = morph
32
+ parent_schema.replace!(property, schema)
33
+ else
34
+ parent_schema[parent_property] = morph
35
+ parent_schema.replace!(property, schema)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def parse_schema(schema)
42
+ @schema = schema
43
+ end
44
+
45
+ # NOTE : The parser will ref to parent_schema instead
46
+ def subschema_options
47
+ {uri: parent_schema.uri,
48
+ root_schema: parent_schema.root? ? parent_schema : parent_schema.root_schema,
49
+ parent_schema: parent_schema,
50
+ parent_property: parent_property}
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Lurker
2
- VERSION = "0.6.4"
2
+ VERSION = "0.6.5"
3
3
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lurker::Json::Attribute do
4
+ let(:klass) { described_class }
5
+
6
+ describe '#parse_schema' do
7
+ context 'when schema is boolean attribute' do
8
+ let(:attribute) do
9
+ klass.new(
10
+ 'description' => '',
11
+ 'type' => 'boolean',
12
+ 'example' => false
13
+ )
14
+ end
15
+ let(:expected) do
16
+ {
17
+ 'description' => '',
18
+ 'type' => 'boolean',
19
+ 'example' => false
20
+ }
21
+ end
22
+
23
+ it { expect(attribute.to_hash).to eq expected }
24
+ end
25
+
26
+ context 'when default attributes order are broken by user' do
27
+ let(:attribute) do
28
+ klass.new(
29
+ 'example' => 'razum2um',
30
+ 'description' => '',
31
+ 'type' => 'string'
32
+ )
33
+ end
34
+ let(:expected) do
35
+ {
36
+ 'example' => 'razum2um',
37
+ 'description' => '',
38
+ 'type' => 'string'
39
+ }.to_json
40
+ end
41
+
42
+ it { expect(attribute.to_json).to eq expected }
43
+ end
44
+ end
45
+ end
@@ -3,7 +3,146 @@ require 'spec_helper'
3
3
  describe Lurker::Json::List do
4
4
  let(:klass) { described_class }
5
5
 
6
+ describe '#parse_schema' do
7
+ context 'when schema is empty array' do
8
+ let(:list) { klass.new([]) }
9
+ let(:expected) do
10
+ {
11
+ 'type' => 'array',
12
+ 'items' => []
13
+ }
14
+ end
15
+
16
+ it { expect(list.to_hash).to eq expected }
17
+ end
18
+
19
+ context 'when schema is empty hash' do
20
+ let(:list) { klass.new({}) }
21
+ let(:expected) do
22
+ {
23
+ 'type' => 'array',
24
+ 'items' => {}
25
+ }
26
+ end
27
+
28
+ it { expect(list.to_hash).to eq expected }
29
+ end
30
+
31
+ context 'when default attributes order are broken by user' do
32
+ let(:list) { klass.new('items' => {}, 'type' => 'array') }
33
+ let(:expected) do
34
+ {
35
+ 'items' => {},
36
+ 'type' => 'array'
37
+ }.to_json
38
+ end
39
+
40
+ it { expect(list.to_json).to eq expected }
41
+ end
42
+ end
43
+
6
44
  describe '#merge!' do
45
+ context 'when list is not specify concrete type' do
46
+ let(:list) { klass.new([]) }
47
+
48
+ context 'when merge an array' do
49
+ let(:expected) do
50
+ {
51
+ 'type' => 'array',
52
+ 'items' => {
53
+ 'description' => '',
54
+ 'type' => 'integer',
55
+ 'example' => 42
56
+ }
57
+ }
58
+ end
59
+ before { list.merge!([42]) }
60
+
61
+ it { expect(list.to_hash).to eq expected }
62
+ end
63
+
64
+ context 'when merge an array of different types' do
65
+ let(:expected) do
66
+ {
67
+ 'type' => 'array',
68
+ 'items' => {
69
+ 'anyOf' => [
70
+ {
71
+ 'description' => '',
72
+ 'type' => 'integer',
73
+ 'example' => 42
74
+ },
75
+ {
76
+ 'description' => '',
77
+ 'type' => 'string',
78
+ 'example' => 'razum2um'
79
+ }
80
+ ]
81
+ }
82
+ }
83
+ end
84
+ before { list.merge!([42, 'razum2um']) }
85
+
86
+ it { expect(list.to_hash).to eq expected }
87
+ end
88
+
89
+ context 'when merge a fixnum' do
90
+ let(:expected) do
91
+ {
92
+ 'type' => 'array',
93
+ 'items' => {
94
+ 'description' => '',
95
+ 'type' => 'integer',
96
+ 'example' => 999
97
+ }
98
+ }
99
+ end
100
+ before { list.merge!(999) }
101
+
102
+ it { expect(list.to_hash).to eq expected }
103
+ end
104
+
105
+ context 'when merge a string' do
106
+ let(:expected) do
107
+ {
108
+ 'type' => 'array',
109
+ 'items' => {
110
+ 'description' => '',
111
+ 'type' => 'string',
112
+ 'example' => 'razum2um'
113
+ }
114
+ }
115
+ end
116
+ before { list.merge!('razum2um') }
117
+
118
+ it { expect(list.to_hash).to eq expected }
119
+ end
120
+
121
+ context 'when merge a hash' do
122
+ let(:expected) do
123
+ {
124
+ 'type' => 'array',
125
+ 'items' => {
126
+ 'description' => '',
127
+ 'type' => 'object',
128
+ 'additionalProperties' => false,
129
+ 'required' => [],
130
+ 'properties' => {
131
+ 'name' => {
132
+ 'description' => '',
133
+ 'type' => 'string',
134
+ 'example' => 'razum2um'
135
+ }
136
+ }
137
+ }
138
+ }
139
+ end
140
+ before { list.merge!('name' => 'razum2um') }
141
+
142
+ it { expect(list.to_hash).to eq expected }
143
+ end
144
+ end
145
+
7
146
  context 'when list is an array of attributes' do
8
147
  let(:list) { klass.new([1, 2, 3]) }
9
148
 
@@ -3,7 +3,76 @@ require 'spec_helper'
3
3
  describe Lurker::Json::Object do
4
4
  let(:klass) { described_class }
5
5
 
6
+ describe '#parse_schema' do
7
+ context 'when schema is empty hash' do
8
+ let(:object) { klass.new({}) }
9
+ let(:expected) do
10
+ {
11
+ 'description' => '',
12
+ 'type' => 'object',
13
+ 'additionalProperties' => false,
14
+ 'required' => [],
15
+ 'properties' => {}
16
+ }
17
+ end
18
+
19
+ it { expect(object.to_hash).to eq expected }
20
+ end
21
+
22
+ context 'when default attributes order are broken by user' do
23
+ let(:object) do
24
+ klass.new(
25
+ 'type' => 'object',
26
+ 'additionalProperties' => true,
27
+ 'description' => '',
28
+ 'properties' => {},
29
+ 'required' => []
30
+ )
31
+ end
32
+ let(:expected) do
33
+ {
34
+ 'type' => 'object',
35
+ 'additionalProperties' => true,
36
+ 'description' => '',
37
+ 'properties' => {},
38
+ 'required' => []
39
+ }.to_json
40
+ end
41
+
42
+ it { expect(object.to_json).to eq expected }
43
+ end
44
+ end
45
+
6
46
  describe '#merge!' do
47
+ context 'when merge a hash with properties containing empty hash' do
48
+ let(:object) { klass.new({}) }
49
+ let(:expected) do
50
+ {
51
+ 'description' => '',
52
+ 'type' => 'object',
53
+ 'additionalProperties' => false,
54
+ 'required' => [],
55
+ 'properties' => {
56
+ 'name' => {
57
+ 'description' => '',
58
+ 'type' => 'string',
59
+ 'example' => 'razum2um'
60
+ },
61
+ 'repo' => {
62
+ 'description' => '',
63
+ 'type' => 'object',
64
+ 'additionalProperties' => false,
65
+ 'required' => [],
66
+ 'properties' => {}
67
+ }
68
+ }
69
+ }
70
+ end
71
+
72
+ before { object.merge!('name' => 'razum2um', 'repo' => {}) }
73
+
74
+ it { expect(object.to_hash).to eq expected }
75
+ end
7
76
  context 'when merge a hash with keywords' do
8
77
  let(:object) { klass.new('name' => 'razum2um') }
9
78
  let(:expected) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lurker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vlad Bokov
@@ -30,7 +30,7 @@ cert_chain:
30
30
  vzKbYclpJ7gENr/xiTjGqA/Md3zJMzmsFrzUXt4RVmo5SaCyZjC6gFfhSr+PODc7
31
31
  ZaSbckvH/+m4boAsg0JkGGFcS3j5fgNmdwgA1A==
32
32
  -----END CERTIFICATE-----
33
- date: 2014-08-18 00:00:00.000000000 Z
33
+ date: 2014-08-28 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: json
@@ -500,6 +500,7 @@ files:
500
500
  - lib/lurker/json/schema/extensions.rb
501
501
  - lib/lurker/json/schema/list.rb
502
502
  - lib/lurker/json/schema/object.rb
503
+ - lib/lurker/json/schema/polymorph.rb
503
504
  - lib/lurker/json/schema/reference.rb
504
505
  - lib/lurker/json/schema/response_codes.rb
505
506
  - lib/lurker/json/schema/tuple.rb
@@ -574,6 +575,7 @@ files:
574
575
  - lib/lurker/version.rb
575
576
  - lurker.gemspec
576
577
  - spec/lurker/endpoint_spec.rb
578
+ - spec/lurker/json/attribute_spec.rb
577
579
  - spec/lurker/json/list_spec.rb
578
580
  - spec/lurker/json/object_spec.rb
579
581
  - spec/lurker/json/schema_spec.rb
@@ -631,6 +633,7 @@ test_files:
631
633
  - features/support/files_helper.rb
632
634
  - features/test_endpoint.feature
633
635
  - spec/lurker/endpoint_spec.rb
636
+ - spec/lurker/json/attribute_spec.rb
634
637
  - spec/lurker/json/list_spec.rb
635
638
  - spec/lurker/json/object_spec.rb
636
639
  - spec/lurker/json/schema_spec.rb
@@ -638,4 +641,3 @@ test_files:
638
641
  - spec/spec_helper.rb
639
642
  - spec/support/matchers/json_attribute.rb
640
643
  - spec/support/matchers/json_object.rb
641
- has_rdoc:
metadata.gz.sig CHANGED
Binary file