lurker 0.6.4 → 0.6.5

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 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