api_sketch 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|