sober_swag 0.19.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +1 -1
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +5 -1
  6. data/.yardopts +7 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +8 -0
  9. data/README.md +1 -1
  10. data/docs/serializers.md +3 -0
  11. data/example/Gemfile +1 -1
  12. data/example/config/environments/production.rb +1 -1
  13. data/lib/sober_swag.rb +6 -1
  14. data/lib/sober_swag/compiler.rb +29 -3
  15. data/lib/sober_swag/compiler/path.rb +42 -3
  16. data/lib/sober_swag/compiler/paths.rb +20 -0
  17. data/lib/sober_swag/compiler/primitive.rb +17 -0
  18. data/lib/sober_swag/compiler/type.rb +105 -22
  19. data/lib/sober_swag/controller.rb +39 -12
  20. data/lib/sober_swag/controller/route.rb +103 -20
  21. data/lib/sober_swag/input_object.rb +90 -7
  22. data/lib/sober_swag/nodes/array.rb +19 -0
  23. data/lib/sober_swag/nodes/attribute.rb +45 -4
  24. data/lib/sober_swag/nodes/base.rb +27 -7
  25. data/lib/sober_swag/nodes/binary.rb +30 -13
  26. data/lib/sober_swag/nodes/enum.rb +16 -1
  27. data/lib/sober_swag/nodes/list.rb +20 -0
  28. data/lib/sober_swag/nodes/nullable_primitive.rb +3 -0
  29. data/lib/sober_swag/nodes/object.rb +4 -1
  30. data/lib/sober_swag/nodes/one_of.rb +11 -3
  31. data/lib/sober_swag/nodes/primitive.rb +34 -2
  32. data/lib/sober_swag/nodes/sum.rb +8 -0
  33. data/lib/sober_swag/output_object.rb +35 -4
  34. data/lib/sober_swag/output_object/definition.rb +31 -1
  35. data/lib/sober_swag/output_object/field.rb +31 -11
  36. data/lib/sober_swag/output_object/field_syntax.rb +19 -3
  37. data/lib/sober_swag/output_object/view.rb +46 -1
  38. data/lib/sober_swag/parser.rb +7 -1
  39. data/lib/sober_swag/serializer/array.rb +27 -3
  40. data/lib/sober_swag/serializer/base.rb +75 -25
  41. data/lib/sober_swag/serializer/conditional.rb +33 -1
  42. data/lib/sober_swag/serializer/field_list.rb +18 -2
  43. data/lib/sober_swag/serializer/mapped.rb +10 -1
  44. data/lib/sober_swag/serializer/optional.rb +18 -1
  45. data/lib/sober_swag/serializer/primitive.rb +3 -0
  46. data/lib/sober_swag/server.rb +5 -1
  47. data/lib/sober_swag/type/named.rb +14 -0
  48. data/lib/sober_swag/types/comma_array.rb +4 -0
  49. data/lib/sober_swag/version.rb +1 -1
  50. metadata +3 -2
@@ -1,45 +1,95 @@
1
1
  module SoberSwag
2
2
  class Compiler
3
3
  ##
4
- # A compiler for DRY-Struct data types, essentially.
5
- # It only consumes one type at a time.
4
+ # A compiler for swagger-able types.
5
+ #
6
+ # This class turns Swagger-able types into a *schema*.
7
+ # This Schema may be:
8
+ # - a [schema object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#schemaObject) with {#object_schema}
9
+ # - a [path schema](https://swagger.io/docs/specification/describing-parameters/#path-parameters) with {#path_schema}
10
+ # - a [query schema](https://swagger.io/docs/specification/describing-parameters/#query-parameters) with {#query_schema}
11
+ #
12
+ # As such, it compiles all types to all applicable schemas.
13
+ #
14
+ # While this class compiles *one* type at a time, it *keeps track* of the other types needed to describe this schema.
15
+ # It stores these types in a set, available at {#found_types}.
16
+ #
17
+ # For example, with a schema like:
18
+ #
19
+ # ```ruby
20
+ # class Bar < SoberSwag::InputObject
21
+ # attribute :baz, primitive(:String)
22
+ # end
23
+ #
24
+ # class Foo < SoberSwag::InputObject
25
+ # attribute :bar, Bar
26
+ # end
27
+ # ```
28
+ #
29
+ # If you compile `Foo` with this class, {#found_types} will include `Bar`.
30
+ #
6
31
  class Type # rubocop:disable Metrics/ClassLength
32
+ ##
33
+ # An error raised when a type is too complicated for a given schema.
34
+ # This may be due to containing too many layers of nesting.
7
35
  class TooComplicatedError < ::SoberSwag::Compiler::Error; end
36
+ ##
37
+ # An error raised when a type is too complicated to transform into a *path* schema.
8
38
  class TooComplicatedForPathError < TooComplicatedError; end
39
+ ##
40
+ # An error raised when a type is too complicated to transform into a *query* schema.
9
41
  class TooComplicatedForQueryError < TooComplicatedError; end
10
42
 
43
+ ##
44
+ # A list of acceptable keys to use as metadata for an object schema.
45
+ # All other metadata keys defined on a type with {SoberSwag::InputObject.meta} will be ignored.
46
+ #
47
+ # @return [Array<Symbol>] valid keys.
11
48
  METADATA_KEYS = %i[description deprecated].freeze
12
49
 
50
+ ##
51
+ # Create a new compiler for a swagger-able type.
52
+ # @param type [Class] the type to compile
13
53
  def initialize(type)
14
54
  @type = type
15
55
  end
16
56
 
57
+ ##
58
+ # @return [Class] the type we are compiling.
17
59
  attr_reader :type
18
60
 
19
61
  ##
20
62
  # Is this type standalone, IE, worth serializing on its own
21
63
  # in the schemas section of our schema?
64
+ # @return [true,false]
22
65
  def standalone?
23
66
  type.is_a?(Class)
24
67
  end
25
68
 
69
+ ##
70
+ # Get back the [schema object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#schemaObject)
71
+ # for the type described.
72
+ #
73
+ # @return [Hash]
26
74
  def object_schema
27
75
  @object_schema ||=
28
76
  make_object_schema
29
77
  end
30
78
 
31
- def object_schema_meta
32
- return {} unless standalone? && type <= SoberSwag::Type::Named
33
-
34
- {
35
- description: type.description
36
- }.reject { |_, v| v.nil? }
37
- end
38
-
79
+ ##
80
+ # Give a "stub type" for this schema.
81
+ # This is suitable to use as the schema for attributes of other schemas.
82
+ # Almost always generates a ref object.
83
+ # @return [Hash] the OpenAPI V3 schema stub
39
84
  def schema_stub
40
85
  @schema_stub ||= generate_schema_stub
41
86
  end
42
87
 
88
+ ##
89
+ # The schema for this type when it is path of the path.
90
+ #
91
+ # @raise [TooComplicatedForPathError] when the compiled type is too complicated to use in a path
92
+ # @return [Hash] a [path parameters hash](https://swagger.io/docs/specification/describing-parameters/#path-parameters) for this type.
43
93
  def path_schema
44
94
  path_schema_stub.map do |e|
45
95
  ensure_uncomplicated(e[:name], e[:schema])
@@ -51,16 +101,30 @@ module SoberSwag
51
101
 
52
102
  DEFAULT_QUERY_SCHEMA_ATTRS = { in: :query, style: :deepObject, explode: true }.freeze
53
103
 
104
+ ##
105
+ # The schema for this type when it is part of the query.
106
+ # @raise [TooComplicatedForQueryError] when this type is too complicated to use in a query schema
107
+ # @return [Hash] a [query parameters hash](https://swagger.io/docs/specification/describing-parameters/#query-parameters) for this type.
54
108
  def query_schema
55
109
  path_schema_stub.map { |e| DEFAULT_QUERY_SCHEMA_ATTRS.merge(e) }
56
110
  rescue TooComplicatedError => e
57
111
  raise TooComplicatedForQueryError, e.message
58
112
  end
59
113
 
114
+ ##
115
+ # Get the name of this type if it is to be used in a `$ref` key.
116
+ # This is useful if we are going to use this type compiler to compile an *attribute* of another object.
117
+ #
118
+ # @return [String] a reference specifier for this type
60
119
  def ref_name
61
120
  SoberSwag::Compiler::Primitive.new(type).ref_name
62
121
  end
63
122
 
123
+ ##
124
+ # Get a set of all other types needed to compile this type.
125
+ # This set will *not* include the type being compiled.
126
+ #
127
+ # @return [Set<Class>]
64
128
  def found_types
65
129
  @found_types ||=
66
130
  begin
@@ -69,32 +133,51 @@ module SoberSwag
69
133
  end
70
134
  end
71
135
 
72
- def mapped_type
73
- @mapped_type ||= parsed_type.map { |v| SoberSwag::Compiler::Primitive.new(v).type_hash }
74
- end
75
-
76
- def parsed_type
77
- @parsed_type ||=
78
- begin
79
- (parsed,) = parsed_result
80
- parsed
81
- end
82
- end
83
-
136
+ ##
137
+ # This type, parsed into an AST.
84
138
  def parsed_result
85
139
  @parsed_result ||= Parser.new(type_for_parser).run_parser
86
140
  end
87
141
 
142
+ ##
143
+ # Standard ruby equality.
88
144
  def eql?(other)
89
145
  other.class == self.class && other.type == type
90
146
  end
91
147
 
148
+ ##
149
+ # Standard ruby hashing method.
150
+ # Compilers hash to the same value if they are compiling the same type.
92
151
  def hash
93
152
  [self.class, type].hash
94
153
  end
95
154
 
96
155
  private
97
156
 
157
+ ##
158
+ # Get metadata attributes to be used if compiling an object schema.
159
+ #
160
+ # @return [Hash]
161
+ def object_schema_meta
162
+ return {} unless standalone? && type <= SoberSwag::Type::Named
163
+
164
+ {
165
+ description: type.description
166
+ }.reject { |_, v| v.nil? }
167
+ end
168
+
169
+ def parsed_type
170
+ @parsed_type ||=
171
+ begin
172
+ (parsed,) = parsed_result
173
+ parsed
174
+ end
175
+ end
176
+
177
+ def mapped_type
178
+ @mapped_type ||= parsed_type.map { |v| SoberSwag::Compiler::Primitive.new(v).type_hash }
179
+ end
180
+
98
181
  def generate_schema_stub
99
182
  if type.is_a?(Class)
100
183
  SoberSwag::Compiler::Primitive.new(type).type_hash
@@ -2,7 +2,8 @@ require 'active_support/concern'
2
2
 
3
3
  module SoberSwag
4
4
  ##
5
- # Controller concern
5
+ # This module can be included in any subclass of `ActionController` or `ActionController::API` to make it `SoberSwag`-able.
6
+ # This means that you can use the mechanics of SoberSwag to define a type-safe API, with generated Swagger documentation!
6
7
  module Controller
7
8
  extend ActiveSupport::Concern
8
9
 
@@ -17,14 +18,18 @@ module SoberSwag
17
18
  include ::Dry::Types()
18
19
  end
19
20
 
20
- class_methods do
21
+ ##
22
+ # Module containing class methods.
23
+ # Any class that `include`s {SoberSwag::Controller} will also `extend` {SoberSwag::Controller::ClassMethods}.
24
+ module ClassMethods
21
25
  ##
22
26
  # Define a new action with the given HTTP method, action name, and path.
23
- # This will eventaully delegate to making an actual method on your controller,
27
+ # This will eventually delegate to making an actual method on your controller,
24
28
  # so you can use controllers as you wish with no harm.
25
29
  #
26
30
  # This method takes a block, evaluated in the context of a {SoberSwag::Controller::Route}.
27
31
  # Used like:
32
+ #
28
33
  # define(:get, :show, '/posts/{id}') do
29
34
  # path_params do
30
35
  # attribute :id, Types::Integer
@@ -36,32 +41,46 @@ module SoberSwag
36
41
  # end
37
42
  #
38
43
  # This will define an "action module" on this class to contain the generated types.
39
- # In the above example, the following constants will be deifned on the controller:
40
- # PostsController::Show # the container module for everything in this action
41
- # PostsController::Show::PathParams # the dry-struct type for the path attribute.
44
+ # In the above example, the following constants will be defined on the controller:
45
+ #
46
+ # - `PostsController::Show` - the container module for everything in this action
47
+ # - `PostsController::Show::PathParams` - the dry-struct type for the path attribute.
48
+ #
42
49
  # So, in the same controller, you can refer to Show::PathParams to get the type created by the 'path_params' block above.
50
+ #
51
+ # The block given evaluates in the context of `SoberSwag::Controller::Route`.
52
+ #
53
+ # @todo Explore parsing the `path` parameter from rails routes so we can avoid forcing the duplicate boilerplate.
54
+ #
55
+ # @param method [Symbol] the HTTP method of this route
56
+ # @param action [Symbol] the name of the controller method this maps onto
57
+ # @param path [String] an OpenAPI v3 Path Specifier
43
58
  def define(method, action, path, &block)
44
59
  r = Route.new(method, action, path)
45
60
  r.instance_eval(&block)
46
61
  const_set(r.action_module_name, r.action_module)
47
62
  defined_routes << r
48
- define_method(action, r.action) if r.action
49
63
  end
50
64
 
51
65
  ##
52
66
  # All the routes that this controller knows about.
67
+ # @return [Array<SoberSwag::Controller::Route>
53
68
  def defined_routes
54
69
  @defined_routes ||= []
55
70
  end
56
71
 
57
72
  ##
58
73
  # Find a route with the given name.
74
+ # @param name [Symbol] the name
75
+ # @return [SoberSwag::Controller::Route]
59
76
  def find_route(name)
60
77
  defined_routes.find { |r| r.action_name.to_s == name.to_s }
61
78
  end
62
79
 
63
80
  ##
64
- # A swagger definition for *this controller only*.
81
+ # Get the OpenAPI v3 definition for this controller.
82
+ #
83
+ # @return [Hash]
65
84
  def swagger_info
66
85
  @swagger_info ||=
67
86
  begin
@@ -74,14 +93,19 @@ module SoberSwag
74
93
  end
75
94
  end
76
95
 
96
+ included do |base|
97
+ base.extend ClassMethods
98
+ end
99
+
77
100
  ##
78
- # Action to get the singular swagger for this entire API.
101
+ # ActiveController action to get the swagger definition for this API.
102
+ # It renders a JSON of the OpenAPI v3 schema for this API.
79
103
  def swagger
80
104
  render json: self.class.swagger_info
81
105
  end
82
106
 
83
107
  ##
84
- # Get the path parameters, parsed into the type you defined with {SoberSwag::Controller.define}
108
+ # Get the path parameters, parsed into the type you defined with {SoberSwag::Controller::ClassMethods#define}
85
109
  # @raise [UndefinedPathError] if there's no path params defined for this route
86
110
  # @raise [Dry::Struct::Error] if we cannot convert the path params to the defined type.
87
111
  def parsed_path
@@ -95,7 +119,7 @@ module SoberSwag
95
119
  end
96
120
 
97
121
  ##
98
- # Get the request body, parsed into the type you defined with {SoberSwag::Controller.define}.
122
+ # Get the request body, parsed into the type you defined with {SoberSwag::Controller::ClassMethods#define}.
99
123
  # @raise [UndefinedBodyError] if there's no request body defined for this route
100
124
  # @raise [Dry::Struct::Error] if we cannot convert the path params to the defined type.
101
125
  def parsed_body
@@ -109,7 +133,7 @@ module SoberSwag
109
133
  end
110
134
 
111
135
  ##
112
- # Get the query params, parsed into the type you defined with {SoberSwag::Controller.define}
136
+ # Get the query params, parsed into the type you defined with {SoberSwag::Controller::ClassMethods#define}
113
137
  # @raise [UndefinedQueryError] if there's no query params defined for this route
114
138
  # @raise [Dry::Struct::Error] if we cannot convert the path params to the defined type.
115
139
  def parsed_query
@@ -140,6 +164,8 @@ module SoberSwag
140
164
  # This kinda violates the "be liberal in what you accept" principle,
141
165
  # but it keeps the docs honest: parameters sent in the body *must* be
142
166
  # in the body.
167
+ #
168
+ # @return [Hash]
143
169
  def body_params
144
170
  request.request_parameters
145
171
  end
@@ -147,6 +173,7 @@ module SoberSwag
147
173
  ##
148
174
  # Get the action-definition for the current action.
149
175
  # Under the hood, delegates to the `:action` key of rails params.
176
+ # @return [SoberSwag::Controller::Route]
150
177
  def current_action_def
151
178
  self.class.find_route(params[:action])
152
179
  end
@@ -3,6 +3,12 @@ module SoberSwag
3
3
  ##
4
4
  # Describe a single controller endpoint.
5
5
  class Route
6
+ ##
7
+ # @param method [Symbol] the HTTP method to get
8
+ # @param action_name [Symbol] the name of the rails action
9
+ # (the name of the controller method, usually)
10
+ # @param path [String] an OpenAPI V3 path template,
11
+ # which should [match this format](https://swagger.io/docs/specification/describing-parameters/#path-parameters)
6
12
  def initialize(method, action_name, path)
7
13
  @method = method
8
14
  @path = path
@@ -12,20 +18,56 @@ module SoberSwag
12
18
  @tags = []
13
19
  end
14
20
 
15
- attr_reader :response_serializers, :response_descriptions, :controller, :method, :path, :action_name
21
+ ##
22
+ # A hash of response code -> response serializer
23
+ # @return [Hash{Symbol => SoberSwag::Serializer::Base}]
24
+ # response code to response serializer
25
+ attr_reader :response_serializers
26
+
27
+ ##
28
+ # A hash of response code -> response description
29
+ # @return [Hash{Symbol => String}]
30
+ # response code to response description
31
+ attr_reader :response_descriptions
32
+
33
+ ##
34
+ # The HTTP method of this route.
35
+ # @return [Symbol]
36
+ attr_reader :method
37
+
38
+ ##
39
+ # The swagger path specifier of this route.
40
+ # @return [String]
41
+ attr_reader :path
42
+
43
+ ##
44
+ # The name of the rails action (usually the controller method) of this route.
45
+ # @return [Symbol]
46
+ attr_reader :action_name
16
47
 
17
48
  ##
18
49
  # What to parse the request body into.
50
+ # @return [Class] a swagger-able class type for a request body.
19
51
  attr_reader :request_body_class
20
52
  ##
21
53
  # What to parse the request query_params into.
54
+ # @return [Class] a swagger-able class type for query parameters.
22
55
  attr_reader :query_params_class
23
56
  ##
24
57
  # What to parse the path params into.
58
+ # @return [Class] a swagger-able class type for path parameters.
25
59
  attr_reader :path_params_class
26
60
 
27
61
  ##
28
62
  # Standard swagger tags.
63
+ #
64
+ # @overload tags()
65
+ # Get the tags for this route.
66
+ # @return [Array<String,Symbol>] the tags.
67
+ # @overload tags(*args)
68
+ # Set the tags for this route.
69
+ # @param tags [Array<String,Symbol>] the tags to set
70
+ # @return [Array<String,Symbol>] the tags used
29
71
  def tags(*args)
30
72
  return @tags if args.empty?
31
73
 
@@ -34,8 +76,13 @@ module SoberSwag
34
76
 
35
77
  ##
36
78
  # Define the request body, using SoberSwag's type-definition scheme.
37
- # The block passed will be used to define the body of a new sublcass of `base` (defaulted to {SoberSwag::InputObject}.)
38
- # If you want, you can also define utility methods in here
79
+ # The block passed will be used to define the body of a new subclass of `base` (defaulted to {SoberSwag::InputObject}.)
80
+ # @overload request_body(base)
81
+ # Give a Swagger-able type that will be used to parse the request body, and used in generated docs.
82
+ # @param base [Class] a swagger-able class
83
+ # @overload request_body(base = SoberSwag::InputObject, &block)
84
+ # Define a Swagger-able type inline to use to parse the request body.
85
+ # @see SoberSwag.input_object
39
86
  def request_body(base = SoberSwag::InputObject, &block)
40
87
  @request_body_class = make_input_object!(base, &block)
41
88
  action_module.const_set('RequestBody', @request_body_class)
@@ -48,9 +95,12 @@ module SoberSwag
48
95
  end
49
96
 
50
97
  ##
51
- # Define the shape of the query_params parameters, using SoberSwag's type-definition scheme.
52
- # The block passed is the body of the newly-defined type.
53
- # You can also include a base type.
98
+ # @overload query_params(base)
99
+ # Give a Swagger-able type that will be used to parse the query params, and used in generated docs.
100
+ # @param base [Class] a swagger-able class
101
+ # @overload query_params(base = SoberSwag::InputObject, &block)
102
+ # Define a Swagger-able type inline to use to parse the query params.
103
+ # @see SoberSwag.input_object
54
104
  def query_params(base = SoberSwag::InputObject, &block)
55
105
  @query_params_class = make_input_object!(base, &block)
56
106
  action_module.const_set('QueryParams', @query_params_class)
@@ -63,9 +113,12 @@ module SoberSwag
63
113
  end
64
114
 
65
115
  ##
66
- # Define the shape of the *path* parameters, using SoberSwag's type-definition scheme.
67
- # The block passed will be the body of a new subclass of `base` (defaulted to {SoberSwag::InputObject}).
68
- # Names of this should match the names in the path template originally passed to {SoberSwag::Controller::Route.new}
116
+ # @overload path_params(base)
117
+ # Give a Swagger-able type that will be used to parse the path params, and used in generated docs.
118
+ # @param base [Class] a swagger-able class
119
+ # @overload path_params(base = SoberSwag::InputObject, &block)
120
+ # Define a Swagger-able type inline to use to parse the path params.
121
+ # @see SoberSwag.input_object
69
122
  def path_params(base = SoberSwag::InputObject, &block)
70
123
  @path_params_class = make_input_object!(base, &block)
71
124
  action_module.const_set('PathParams', @path_params_class)
@@ -78,19 +131,27 @@ module SoberSwag
78
131
  end
79
132
 
80
133
  ##
81
- # Define the body of the action method in the controller.
82
- def action(&body)
83
- return @action if body.nil?
84
-
85
- @action ||= body
86
- end
87
-
134
+ # @overload description()
135
+ # Get a description of this route object.
136
+ # @return [String] markdown-formatted description
137
+ # @overload description(desc)
138
+ # Set the description of this route object.
139
+ # @param desc [String] markdown-formatted description
140
+ # @return [String] `desc`.
88
141
  def description(desc = nil)
89
142
  return @description if desc.nil?
90
143
 
91
144
  @description = desc
92
145
  end
93
146
 
147
+ ##
148
+ # @overload summary()
149
+ # Get the summary of this route object, a short string that identifies
150
+ # what it does.
151
+ # @return [String] markdown-formatted summary
152
+ # @overload summary(sum)
153
+ # Set a short, markdown-formatted summary of what this route does.
154
+ # @param sum [String] markdown-formatted summary
94
155
  def summary(sum = nil)
95
156
  return @summary if sum.nil?
96
157
 
@@ -100,14 +161,35 @@ module SoberSwag
100
161
  ##
101
162
  # The container module for all the constants this will eventually define.
102
163
  # Each class generated by this Route will be defined within this module.
164
+ # @return [Module] the module under which constants will be defined.
103
165
  def action_module
104
166
  @action_module ||= Module.new
105
167
  end
106
168
 
107
169
  ##
108
- # Define a serializer for a response with the given status code.
109
- # You may either give a serializer you defined elsewhere, or define one inline as if passed to
110
- # {SoberSwag::OutputObject.define}
170
+ # @overload response(status_code, description, &block)
171
+ # Define a new response from this route, by defining a serializer inline.
172
+ # This serializer will be defined as if with {SoberSwag::OutputObject.define}
173
+ #
174
+ # Generally, you want to define your serializers elsewhere for independent testing and such.
175
+ # However, if you have a really quick thing to serialize, this works.
176
+ # @param status_code [Symbol]
177
+ # the name of the HTTP status of this response.
178
+ # @param description [String]
179
+ # a description of what this response is, markdown-formatted
180
+ # @param block [Proc]
181
+ # passed to {SoberSwag::OutputObject.define}
182
+ #
183
+ # @overload response(status_code, description, serializer)
184
+ # Define a new response from this route, with an existing serializer.
185
+ # The generated swagger will document this response's format using the serializer.
186
+ #
187
+ # @param status_code [Symbol]
188
+ # the name of the HTTP status of this response
189
+ # @param description [String]
190
+ # a description of what this response is, markdown-formatted
191
+ # @param serializer [SoberSwag::Serializer::Base] a serializer to use for the
192
+ # body of this response
111
193
  def response(status_code, description, serializer = nil, &block)
112
194
  status_key = Rack::Utils.status_code(status_code)
113
195
 
@@ -120,7 +202,8 @@ module SoberSwag
120
202
  end
121
203
 
122
204
  ##
123
- # What you should call the module of this action in your controller
205
+ # What you should call the module of this action in your controller.
206
+ # @return [String]
124
207
  def action_module_name
125
208
  action_name.to_s.classify
126
209
  end