api_sketch 0.1.1 → 0.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/.gitignore +2 -0
- data/CHANGELOG.md +7 -2
- data/README.md +63 -9
- data/api_sketch.gemspec +0 -1
- data/examples/api_project/config/initializers/shared_blocks.rb +15 -0
- data/examples/api_project/resources/places.rb +138 -0
- data/examples/api_project/resources/users/points/stats.rb +30 -0
- data/examples/api_project/resources/users/points.rb +32 -0
- data/examples/api_project/resources/users.rb +341 -0
- data/lib/api_sketch/config.rb +1 -1
- data/lib/api_sketch/dsl/attribute_parser.rb +19 -0
- data/lib/api_sketch/dsl/attributes.rb +45 -0
- data/lib/api_sketch/dsl/base.rb +8 -0
- data/lib/api_sketch/dsl/complex_attribute_parser.rb +11 -0
- data/lib/api_sketch/dsl/headers.rb +17 -0
- data/lib/api_sketch/dsl/parameters.rb +31 -0
- data/lib/api_sketch/dsl/responses.rb +22 -0
- data/lib/api_sketch/dsl.rb +27 -165
- data/lib/api_sketch/examples_server.rb +1 -1
- data/lib/api_sketch/generators/base.rb +42 -0
- data/lib/api_sketch/{generators.rb → generators/bootstrap.rb} +2 -46
- data/lib/api_sketch/model/attribute.rb +42 -0
- data/lib/api_sketch/model/base.rb +17 -0
- data/lib/api_sketch/model/header.rb +7 -0
- data/lib/api_sketch/model/parameters.rb +50 -0
- data/lib/api_sketch/model/resource.rb +99 -0
- data/lib/api_sketch/model/response.rb +12 -0
- data/lib/api_sketch/model/shared_block.rb +17 -0
- data/lib/api_sketch/model.rb +0 -242
- data/lib/api_sketch/{renderers.rb → response_renderer.rb} +0 -0
- data/lib/api_sketch/version.rb +1 -1
- data/lib/api_sketch.rb +20 -3
- data/spec/lib/api_sketch/dsl/attribute_parser_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl/attributes_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl/complex_attribute_parser_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl/headers_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl/parameters_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl/responses_spec.rb +14 -0
- data/spec/lib/api_sketch/dsl_spec.rb +5 -3
- data/spec/lib/api_sketch/model/parameters_spec.rb +28 -0
- data/spec/lib/api_sketch/{renderers_spec.rb → response_renderer_spec.rb} +51 -1
- data/spec/spec_helper.rb +3 -1
- data/spec/support/shared_examples.rb +9 -0
- metadata +43 -9
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
data/lib/api_sketch/dsl.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
class ApiSketch::DSL
|
2
2
|
|
3
|
+
attr_reader :definitions_dir
|
4
|
+
|
3
5
|
COMPLEX_ATTRIBUTE_NAMES = [:headers, :parameters, :responses]
|
4
6
|
|
5
7
|
def initialize(definitions_dir=ApiSketch::Config[:definitions_dir])
|
@@ -7,170 +9,18 @@ class ApiSketch::DSL
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def init!
|
10
|
-
|
11
|
-
puts_info("
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class AttributeParser
|
17
|
-
|
18
|
-
def initialize(container_type, &block)
|
19
|
-
@attribute_values = {}
|
20
|
-
@container_type = container_type
|
21
|
-
# INFO: Such long method name is used to ensure that we are would not have such value as key at hash
|
22
|
-
define_singleton_method(:set_attributes_as_hash_value_format, block)
|
23
|
-
set_attributes_as_hash_value_format
|
24
|
-
end
|
25
|
-
|
26
|
-
def method_missing(method_name, *arguments, &block)
|
27
|
-
@attribute_values[method_name] = arguments.first || block
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_h
|
31
|
-
@attribute_values
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
class Attributes
|
38
|
-
|
39
|
-
TYPES = [:integer, :string, :float, :boolean, :datetime, :timestamp, :document, :array]
|
40
|
-
|
41
|
-
def initialize(container_type, &block)
|
42
|
-
@container_type = container_type
|
43
|
-
@params = []
|
44
|
-
define_singleton_method(:initialize_attributes, block)
|
45
|
-
initialize_attributes
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_a
|
49
|
-
@params
|
12
|
+
if File.directory?(config_dir)
|
13
|
+
puts_info("Load configuration")
|
14
|
+
load_dir_files(config_dir)
|
50
15
|
end
|
51
16
|
|
52
|
-
|
53
|
-
|
17
|
+
if File.directory?(resources_dir)
|
18
|
+
puts_info("Load resources")
|
19
|
+
load_dir_files(resources_dir)
|
54
20
|
end
|
55
|
-
|
56
|
-
TYPES.each do |type_name|
|
57
|
-
define_method(type_name) do |*args, &block|
|
58
|
-
name = args.first
|
59
|
-
if @container_type == :document
|
60
|
-
if name.nil? || name.empty? # key name is not provided
|
61
|
-
raise ::ApiSketch::Error.new, "Key inside document should have name"
|
62
|
-
end
|
63
|
-
elsif @container_type == :array
|
64
|
-
if (!name.nil? && !name.empty?) # key name is provided
|
65
|
-
raise ::ApiSketch::Error.new, "Array element can't have name"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
@params << self.class.build_by(type_name, name, &block)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class << self
|
73
|
-
def build_by(data_type, attribute_name, &block)
|
74
|
-
options = {data_type: data_type}
|
75
|
-
options[:name] = attribute_name if attribute_name
|
76
|
-
case data_type
|
77
|
-
when :document, :array
|
78
|
-
::ApiSketch::Model::Attribute.new(::ApiSketch::DSL::ComplexAttributeParser.new(data_type, &block).to_h.merge(options))
|
79
|
-
else
|
80
|
-
::ApiSketch::Model::Attribute.new(::ApiSketch::DSL::AttributeParser.new(data_type, &block).to_h.merge(options))
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
class ComplexAttributeParser < ApiSketch::DSL::AttributeParser
|
88
|
-
|
89
|
-
def method_missing(method_name, *arguments, &block)
|
90
|
-
if method_name == :content
|
91
|
-
@attribute_values[:content] = ApiSketch::DSL::Attributes.new(@container_type, &block).to_a
|
92
|
-
else
|
93
|
-
super(method_name, *arguments, &block)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
21
|
end
|
98
22
|
|
99
|
-
|
100
|
-
class Headers
|
101
|
-
|
102
|
-
def initialize(&block)
|
103
|
-
@list = []
|
104
|
-
define_singleton_method(:initialize_headers_list, block)
|
105
|
-
initialize_headers_list
|
106
|
-
end
|
107
|
-
|
108
|
-
def to_a
|
109
|
-
@list
|
110
|
-
end
|
111
|
-
|
112
|
-
def add(name, &block)
|
113
|
-
@list << ::ApiSketch::Model::Header.new(::ApiSketch::DSL::AttributeParser.new(:document, &block).to_h.merge(name: name))
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
class Parameters
|
119
|
-
|
120
|
-
def initialize(&block)
|
121
|
-
@query = []
|
122
|
-
@body = []
|
123
|
-
@query_container_type = nil
|
124
|
-
@body_container_type = nil
|
125
|
-
define_singleton_method(:initialize_parameters_list, block)
|
126
|
-
initialize_parameters_list
|
127
|
-
end
|
128
|
-
|
129
|
-
def to_h
|
130
|
-
{
|
131
|
-
query: @query,
|
132
|
-
body: @body,
|
133
|
-
query_container_type: @query_container_type,
|
134
|
-
body_container_type: @body_container_type
|
135
|
-
}
|
136
|
-
end
|
137
|
-
|
138
|
-
def query(container_type, &block)
|
139
|
-
@query_container_type = container_type
|
140
|
-
@query += ::ApiSketch::DSL::Attributes.new(container_type, &block).to_a
|
141
|
-
end
|
142
|
-
|
143
|
-
def body(container_type, &block)
|
144
|
-
@body_container_type = container_type
|
145
|
-
@body += ::ApiSketch::DSL::Attributes.new(container_type, &block).to_a
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
class Responses
|
151
|
-
|
152
|
-
def initialize(&block)
|
153
|
-
@list = []
|
154
|
-
define_singleton_method(:initialize_responses_list, block)
|
155
|
-
initialize_responses_list
|
156
|
-
end
|
157
|
-
|
158
|
-
def to_a
|
159
|
-
@list
|
160
|
-
end
|
161
|
-
|
162
|
-
def context(name, &block)
|
163
|
-
attributes = ::ApiSketch::DSL::AttributeParser.new(:root, &block).to_h
|
164
|
-
if attributes[:parameters]
|
165
|
-
params = ::ApiSketch::DSL::Parameters.new(&attributes[:parameters]).to_h
|
166
|
-
attributes[:parameters] = ::ApiSketch::Model::Parameters.new(params)
|
167
|
-
end
|
168
|
-
@list << ::ApiSketch::Model::Response.new(attributes.merge(name: name))
|
169
|
-
end
|
170
|
-
|
171
|
-
end
|
172
|
-
|
173
|
-
def shared_block(name, block)
|
23
|
+
def shared_block(name, &block)
|
174
24
|
::ApiSketch::Model::SharedBlock.add(name, block)
|
175
25
|
end
|
176
26
|
|
@@ -183,16 +33,12 @@ class ApiSketch::DSL
|
|
183
33
|
end
|
184
34
|
|
185
35
|
# Assign resource namespace
|
186
|
-
attributes[:namespace] ||= block.source_location[0].gsub(
|
36
|
+
attributes[:namespace] ||= block.source_location[0].gsub(resources_dir, "").gsub(".rb", "").split("/").reject { |ns| ns.nil? || ns == "" }.join("/")
|
187
37
|
|
188
38
|
::ApiSketch::Model::Resource.create(attributes)
|
189
39
|
end
|
190
40
|
|
191
|
-
|
192
41
|
private
|
193
|
-
def definitions_dir
|
194
|
-
@definitions_dir
|
195
|
-
end
|
196
42
|
|
197
43
|
def get_attrs(name, &block)
|
198
44
|
::ApiSketch::DSL::AttributeParser.new(:root, &block).to_h.merge(name: name)
|
@@ -210,4 +56,20 @@ class ApiSketch::DSL
|
|
210
56
|
end
|
211
57
|
end
|
212
58
|
|
213
|
-
|
59
|
+
# Definitions loading
|
60
|
+
def config_dir
|
61
|
+
"#{definitions_dir}/config"
|
62
|
+
end
|
63
|
+
|
64
|
+
def resources_dir
|
65
|
+
"#{definitions_dir}/resources"
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_dir_files(dir)
|
69
|
+
Dir.glob("#{dir}/**/*.rb").each do |file_path|
|
70
|
+
puts_info("\t read: #{file_path}")
|
71
|
+
binding.eval(File.open(File.expand_path(file_path)).read, file_path)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -25,7 +25,7 @@ class ApiSketch::ExamplesServer
|
|
25
25
|
|
26
26
|
response.status = Rack::Utils.status_code(api_response.http_status)
|
27
27
|
|
28
|
-
response.write(ApiSketch::ResponseRenderer.new(api_response.parameters.
|
28
|
+
response.write(ApiSketch::ResponseRenderer.new([api_response.parameters.wrapped_body], api_response.parameters.body_container_type, get_elements_count).to_json)
|
29
29
|
end
|
30
30
|
else
|
31
31
|
api_sketch_message("No any responses defined for this resource and context", 404)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ApiSketch::Generators
|
2
|
+
class Base
|
3
|
+
|
4
|
+
attr_accessor :definitions_dir, :documentation_dir
|
5
|
+
|
6
|
+
attr_reader :templates_folder
|
7
|
+
|
8
|
+
# TODO: Add here some validations for folders existance, etc
|
9
|
+
def initialize(options = {})
|
10
|
+
self.definitions_dir = options[:definitions_dir]
|
11
|
+
self.documentation_dir = options[:documentation_dir]
|
12
|
+
@templates_folder = File.expand_path("../templates/#{self.class.name.split("::").last.downcase}", File.dirname(__FILE__))
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate!
|
16
|
+
puts_info("Load definitions")
|
17
|
+
load_definitions
|
18
|
+
puts_info("Create documentation directory")
|
19
|
+
puts_info("\t path: #{self.documentation_dir}")
|
20
|
+
create_documentation_directory
|
21
|
+
puts_info("Create documentation files")
|
22
|
+
create_documentation_files
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def create_documentation_directory
|
27
|
+
FileUtils.rm_r(self.documentation_dir, :force => true)
|
28
|
+
FileUtils.mkdir_p(self.documentation_dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: This is unfinished sample file generator it should be more complex at some other generators
|
32
|
+
# Other generors should inherit from this class and implement this method
|
33
|
+
def create_documentation_files
|
34
|
+
raise "This method should be implemented at child class who inherits from ApiSketch::Generators::Base"
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_definitions
|
38
|
+
ApiSketch::Model::Resource.reload!(self.definitions_dir)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -1,52 +1,9 @@
|
|
1
1
|
module ApiSketch::Generators
|
2
|
-
|
3
|
-
class Base
|
4
|
-
|
5
|
-
attr_accessor :definitions_dir, :documentation_dir
|
6
|
-
|
7
|
-
attr_reader :templates_folder
|
8
|
-
|
9
|
-
# TODO: Add here some validations for folders existance, etc
|
10
|
-
def initialize(options = {})
|
11
|
-
self.definitions_dir = options[:definitions_dir]
|
12
|
-
self.documentation_dir = options[:documentation_dir]
|
13
|
-
@templates_folder = File.expand_path("templates/#{self.class.name.split("::").last.downcase}", File.dirname(__FILE__))
|
14
|
-
end
|
15
|
-
|
16
|
-
def generate!
|
17
|
-
puts_info("Load definitions")
|
18
|
-
load_definitions
|
19
|
-
puts_info("Create documentation directory")
|
20
|
-
puts_info("\t path: #{self.documentation_dir}")
|
21
|
-
create_documentation_directory
|
22
|
-
puts_info("Create documentation files")
|
23
|
-
create_documentation_files
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
def create_documentation_directory
|
28
|
-
FileUtils.rm_r(self.documentation_dir, :force => true)
|
29
|
-
FileUtils.mkdir_p(self.documentation_dir)
|
30
|
-
end
|
31
|
-
|
32
|
-
# TODO: This is unfinished sample file generator it should be more complex at some other generators
|
33
|
-
# Other generors should inherit from this class and implement this method
|
34
|
-
def create_documentation_files
|
35
|
-
raise "This method should be implemented at child class who inherits from ApiSketch::Generators::Base"
|
36
|
-
end
|
37
|
-
|
38
|
-
def load_definitions
|
39
|
-
ApiSketch::Model::Resource.reload!(self.definitions_dir)
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
2
|
class Bootstrap < ApiSketch::Generators::Base
|
46
3
|
|
47
4
|
# Generated folders structure is
|
48
|
-
#
|
49
|
-
#
|
5
|
+
# docs - html folders and files
|
6
|
+
# assets - js, css and images. Html styling
|
50
7
|
|
51
8
|
def initialize(options = {})
|
52
9
|
super(options)
|
@@ -93,5 +50,4 @@ module ApiSketch::Generators
|
|
93
50
|
end
|
94
51
|
end
|
95
52
|
end
|
96
|
-
|
97
53
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class ApiSketch::Model::Attribute < ApiSketch::Model::Base
|
2
|
+
attr_accessor :data_type, :value, :example, :required, :default, :content
|
3
|
+
|
4
|
+
def example_value(defaults_allowed=false)
|
5
|
+
value = self.example
|
6
|
+
value ||= example_value_default if defaults_allowed
|
7
|
+
|
8
|
+
value.respond_to?(:call) ? value.call : value
|
9
|
+
end
|
10
|
+
|
11
|
+
# TODO: These default values should be configurable via DSL
|
12
|
+
# Some logic to defer value example from key name, - email from key with email part inside, etc.
|
13
|
+
def example_value_default
|
14
|
+
{
|
15
|
+
integer: lambda { rand(1000) + 1 },
|
16
|
+
string: lambda { "random_string_#{('A'..'Z').to_a.shuffle.first(8).join}" },
|
17
|
+
float: lambda { rand(100) + rand(100) * 0.01 },
|
18
|
+
boolean: lambda { [true, false].sample },
|
19
|
+
datetime: lambda { Time.now.strftime("%d-%m-%Y %H:%M:%S") },
|
20
|
+
timestamp: lambda { Time.now.to_i }
|
21
|
+
}[data_type]
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
{
|
26
|
+
data_type: self.data_type,
|
27
|
+
example_value: self.example_value,
|
28
|
+
required: !!self.required,
|
29
|
+
default: self.default,
|
30
|
+
content: self.content_to_hash
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def content_to_hash
|
35
|
+
if self.content
|
36
|
+
self.content.map do |item|
|
37
|
+
item.to_hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class ApiSketch::Model::Base
|
2
|
+
|
3
|
+
attr_accessor :name, :description
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
attributes = default_values_hash.merge(attributes)
|
7
|
+
attributes.each do |attribute, value|
|
8
|
+
self.send("#{attribute}=", value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def default_values_hash
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class ApiSketch::Model::Parameters < ApiSketch::Model::Base
|
2
|
+
attr_accessor :query, :body, :query_container_type, :body_container_type
|
3
|
+
|
4
|
+
def initialize(attributes = {})
|
5
|
+
super(attributes)
|
6
|
+
self.query ||= []
|
7
|
+
self.body ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def wrapped_query
|
11
|
+
ApiSketch::Model::Attribute.new(data_type: self.query_container_type, content: self.query)
|
12
|
+
end
|
13
|
+
|
14
|
+
def wrapped_body
|
15
|
+
ApiSketch::Model::Attribute.new(data_type: self.body_container_type, content: self.body)
|
16
|
+
end
|
17
|
+
|
18
|
+
def as_full_names
|
19
|
+
fullname_params = self.class.new
|
20
|
+
[:query, :body].each do |param_location|
|
21
|
+
new_params = []
|
22
|
+
self.send(param_location).each do |param|
|
23
|
+
if param.data_type == :document
|
24
|
+
full_names_for(param, param.name, new_params)
|
25
|
+
else
|
26
|
+
new_params << param
|
27
|
+
end
|
28
|
+
end
|
29
|
+
fullname_params.send("#{param_location}=", new_params)
|
30
|
+
end
|
31
|
+
fullname_params
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def full_names_for(param, name = "", new_params)
|
36
|
+
name = name.to_s # ensure that this value is always a string
|
37
|
+
if param.content.kind_of?(Array)
|
38
|
+
param.content.each do |attribute|
|
39
|
+
renamed_attribute = attribute.clone
|
40
|
+
renamed_attribute.name = name.empty? ? attribute.name.to_s : "#{name}[#{attribute.name}]"
|
41
|
+
if renamed_attribute.data_type == :document
|
42
|
+
full_names_for(renamed_attribute, renamed_attribute.name, new_params)
|
43
|
+
else
|
44
|
+
new_params << renamed_attribute
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class ApiSketch::Model::Resource < ApiSketch::Model::Base
|
2
|
+
|
3
|
+
attr_accessor :namespace, :action, :path, :http_method, :format, :headers, :parameters, :responses
|
4
|
+
|
5
|
+
# TODO: update this method to provide better id that is used as part of filename
|
6
|
+
def id
|
7
|
+
[self.namespace, self.action].reject { |v| v.nil? || v == "" }.join("/")
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def create(attributes)
|
13
|
+
res = self.new(attributes)
|
14
|
+
res.send(:run_validations!)
|
15
|
+
self.add(res)
|
16
|
+
res
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(resource)
|
20
|
+
@resources ||= []
|
21
|
+
@resources << resource
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset!
|
25
|
+
@resources = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def reload!(definitions_dir)
|
29
|
+
ApiSketch::Model::SharedBlock.reset!
|
30
|
+
self.reset!
|
31
|
+
ApiSketch::DSL.new(definitions_dir).init!
|
32
|
+
end
|
33
|
+
|
34
|
+
def all
|
35
|
+
@resources ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def find(id)
|
39
|
+
self.all.find { |res| res.id == id }
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_by_http_method_and_path(http_method, path)
|
43
|
+
self.all.find { |res| res.http_method == http_method && res.path == path }
|
44
|
+
end
|
45
|
+
|
46
|
+
def first
|
47
|
+
self.all.first
|
48
|
+
end
|
49
|
+
|
50
|
+
def last
|
51
|
+
self.all.last
|
52
|
+
end
|
53
|
+
|
54
|
+
def count
|
55
|
+
self.all.count
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def default_values_hash
|
62
|
+
{
|
63
|
+
http_method: "GET",
|
64
|
+
format: "json",
|
65
|
+
headers: [],
|
66
|
+
parameters: ::ApiSketch::Model::Parameters.new,
|
67
|
+
responses: []
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def error_message(message)
|
72
|
+
# puts_error(message)
|
73
|
+
raise ::ApiSketch::Error, message
|
74
|
+
end
|
75
|
+
|
76
|
+
def run_validations!
|
77
|
+
unless self.action =~ /\A\w*\z/
|
78
|
+
error_message("'#{self.action}' is invalid action value")
|
79
|
+
end
|
80
|
+
|
81
|
+
if self.class.find(self.id)
|
82
|
+
error_message("'#{self.id}' is not unique id. Change values of 'namespace' and/or 'action' attributes")
|
83
|
+
end
|
84
|
+
|
85
|
+
if self.http_method.nil? || self.http_method.empty?
|
86
|
+
error_message("request http_method can't be blank")
|
87
|
+
end
|
88
|
+
|
89
|
+
if self.path.nil? || self.path.empty?
|
90
|
+
error_message("request path can't be blank")
|
91
|
+
end
|
92
|
+
|
93
|
+
if self.class.find_by_http_method_and_path(self.http_method, self.path)
|
94
|
+
error_message("Route '#{self.http_method} #{self.path}' should be unique")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class ApiSketch::Model::Response < ApiSketch::Model::Base
|
2
|
+
attr_accessor :http_status, :parameters, :format, :headers
|
3
|
+
|
4
|
+
private
|
5
|
+
def default_values_hash
|
6
|
+
{
|
7
|
+
format: "json",
|
8
|
+
headers: [],
|
9
|
+
parameters: ::ApiSketch::Model::Parameters.new
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ApiSketch::Model::SharedBlock
|
2
|
+
@list_hash = {}
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def add(name, block)
|
6
|
+
@list_hash[name] = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def reset!
|
10
|
+
@list_hash = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def find(name)
|
14
|
+
@list_hash[name] || raise(::ApiSketch::Error, "Shared block '#{name}' is not defined")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|