Module: Jsapi::Controller::Methods

Included in:
Base
Defined in:
lib/jsapi/controller/methods.rb

Instance Method Summary collapse

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)


11
12
13
# File 'lib/jsapi/controller/methods.rb', line 11

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 nil if the controller handles one operation only.

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.



119
120
121
122
123
124
125
126
# File 'lib/jsapi/controller/methods.rb', line 119

def api_params(operation_name = nil, strong: false)
  definitions = api_definitions
  _api_params(
    _find_api_operation_model(operation_name, definitions),
    definitions,
    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 nil if the controller handles one operation only.

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.

Raises an ArgumentError when :omit is other than :empty, :nil or nil.



142
143
144
145
146
147
148
# File 'lib/jsapi/controller/methods.rb', line 142

def api_response(result, operation_name = nil, omit: nil, status: nil)
  definitions = api_definitions
  operation_model = _find_api_operation_model(operation_name, definitions)
  response_model = _find_api_response_model(operation_model, status, definitions)

  Response.new(result, response_model, definitions, omit: omit)
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


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/jsapi/controller/methods.rb', line 55

[true, false].each do |bang|
  define_method(bang ? :api_operation! : :api_operation) \
  do |operation_name = nil, omit: nil, status: nil, strong: false, &block|
    definitions = api_definitions
    operation_model = _find_api_operation_model(operation_name, definitions)
    response_model = _find_api_response_model(operation_model, status, definitions)
    head(status) && return unless block

    # Perform operation
    api_params = _api_params(operation_model, definitions, strong: strong)
    api_response = Response.new(
      begin
        raise ParametersInvalid.new(api_params) if bang && api_params.invalid?

        block.call(api_params)
      rescue StandardError => e
        # Lookup a rescue handler
        rescue_handler = definitions.rescue_handler_for(e)
        raise e if rescue_handler.nil?

        # Change the HTTP status code and response model
        status = rescue_handler.status
        response_model = operation_model.response(status)&.resolve(definitions)
        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,
      response_model, definitions, omit: omit
    )
    # Write response
    media_type = response_model.content_type

    if 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
    elsif media_type.json?
      render(json: api_response, status: status, content_type: media_type.to_s)
    end
  end
end