Module: Jsapi::Controller::Methods

Included in:
Base
Defined in:
lib/jsapi/controller/methods.rb,
lib/jsapi/controller/methods/callbacks.rb,
lib/jsapi/controller/methods/callbacks/callback.rb,
lib/jsapi/controller/methods/callbacks/class_methods.rb

Defined Under Namespace

Modules: Callbacks

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

:nodoc:



57
58
59
# File 'lib/jsapi/controller/methods.rb', line 57

def self.included(base) # :nodoc:
  base.include(Callbacks)
end

Instance Method Details

#api_definitionsObject

Returns the Meta::Definitions instance associated with the controller class. In particular, this method can be used to create an OpenAPI document, for example:

render(json: api_definitions.openapi_document)


66
67
68
# File 'lib/jsapi/controller/methods.rb', line 66

def api_definitions
  self.class.api_definitions
end

#api_params(operation_name = nil, strong: false) ⇒ Object

Returns the request parameters as an instance of the operation’s model class. Parameter names are converted to snake case.

params = api_params('foo')

operation_name can be omitted if the controller handles one operation only.

If no operation could be found for operation_name, an OperationNotFound exception is raised.

If strong is true, parameters that can be mapped are accepted only. That means that the model returned is invalid if there are any request parameters that can’t be mapped to a parameter or a request body property of the operation.

Note that each call of api_params returns a newly created instance.



228
229
230
# File 'lib/jsapi/controller/methods.rb', line 228

def api_params(operation_name = nil, strong: false)
  _api_params(_api_operation(operation_name), strong: strong)
end

#api_response(result, operation_name = nil, omit: nil, status: nil) ⇒ Object

Returns a Response to serialize the JSON representation of result according to the appropriate response specification.

render(json: api_response(bar, 'foo', status: 200))

operation_name can be omitted if the controller handles one operation only.

If no operation could be found for operation_name, an OperationNotFound exception is raised.

:status specifies the HTTP status code of the response to be produced.

The :omit option specifies on which conditions properties are omitted. Possible values are:

  • :empty - All of the properties whose value is empty are omitted.

  • :nil - All of the properties whose value is nil are omitted.



249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/jsapi/controller/methods.rb', line 249

def api_response(result, operation_name = nil, omit: nil, status: nil)
  status = Status::Code.from(status)
  operation = _api_operation(operation_name)
  response_model = _api_response_model(operation, status)

  Response.new(
    result,
    _api_media_type_and_content_model(response_model).second,
    omit: omit,
    locale: response_model.locale
  )
end

#bangObject

:method: api_operation! :args: operation_name = nil, omit: nil, status: nil, strong: false, &block

Like api_operation, except that a ParametersInvalid exception is raised when request parameters are invalid.

api_operation!('foo') do |api_params|
  # ...
end


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/jsapi/controller/methods.rb', line 127

[true, false].each do |bang|
  define_method(bang ? :api_operation! : :api_operation) \
  do |operation_name = nil, omit: nil, status: nil, strong: false, &block|
    operation = _api_operation(operation_name)
    response_model = nil

    result = begin
      # Authenticate request first if Authentication is included
      if respond_to?(:_api_authenticated?, true)
        raise Unauthorized unless _api_authenticated?(operation)

        _api_callback(:after_authentication, operation_name)
      end

      status = Status::Code.from(status)
      response_model = _api_response_model(operation, status)

      api_params = _api_params(operation, strong: strong)

      if bang
        raise ParametersInvalid.new(api_params) if api_params.invalid?

        _api_callback(:after_validation, operation_name, api_params)
      end

      block&.call(api_params)
    rescue StandardError => e
      definitions = api_definitions

      # Lookup a rescue handler
      rescue_handler = definitions.rescue_handler_for(e)
      raise e if rescue_handler.nil?

      # Replace the status code and response model
      status = rescue_handler.status_code
      response_model = operation.find_response(status)
      raise e if response_model.nil?

      # Call on_rescue callbacks
      definitions.on_rescue_callbacks.each do |callback|
        callback.respond_to?(:call) ? callback.call(e) : send(callback, e)
      end

      Error.new(e, status: status)
    end
    # Return if response body has already been rendered
    return if response_body

    # Produce response
    media_type, content_model = _api_media_type_and_content_model(response_model)
    status = status&.to_i
    return head(status) unless content_model

    result = _api_before_rendering(operation_name, result, api_params)

    api_response = Response.new(
      result,
      content_model,
      omit: omit,
      locale: response_model.locale
    )
    if media_type.json?
      render(
        json: api_response,
        status: status,
        content_type: media_type.to_s
      )
    elsif media_type == Media::Type::TEXT_PLAIN
      render(
        plain: result,
        status: status,
        content_type: media_type.to_s
      )
    elsif media_type == Media::Type::APPLICATION_JSON_SEQ
      self.content_type = media_type.to_s
      response.status = status

      response.stream.tap do |stream|
        api_response.write_json_seq_to(stream)
      ensure
        stream.close
      end
    end
  end
end