Module: Apiwork::Controller
- Extended by:
- ActiveSupport::Concern
- Included in:
- ErrorsController
- Defined in:
- lib/apiwork/controller.rb
Overview
Mixin for API controllers that provides request validation and response helpers.
Include in controllers to access #contract, #expose, and #expose_error. Automatically validates requests against the contract before actions run.
Class Method Summary collapse
-
.skip_contract_validation!(only: nil, except: nil) ⇒ Object
Skips contract validation for specified actions.
Instance Method Summary collapse
-
#context ⇒ Hash
The context for this controller.
-
#contract ⇒ Contract::Base
The contract for this controller.
-
#expose(data, meta: {}, status: nil) ⇒ Object
Exposes data as an API response.
-
#expose_error(code_key, detail: nil, path: nil, meta: {}) ⇒ Object
Exposes an error response using a registered error code.
Class Method Details
.skip_contract_validation!(only: nil, except: nil) ⇒ Object
Skips contract validation for specified actions.
55 56 57 58 59 |
# File 'lib/apiwork/controller.rb', line 55 class_methods do def skip_contract_validation!(except: nil, only: nil) skip_before_action :validate_contract, except:, only: end end |
Instance Method Details
#context ⇒ Hash
The context for this controller.
Passed to representations during serialization. Override to provide current user, permissions, locale, or feature flags.
220 221 222 |
# File 'lib/apiwork/controller.rb', line 220 def context {} end |
#contract ⇒ Contract::Base
The contract for this controller.
Contains parsed query parameters and request body with type coercion applied. Access parameters via Apiwork::Contract::Base#query and Apiwork::Contract::Base#body.
82 83 84 85 86 87 88 89 90 |
# File 'lib/apiwork/controller.rb', line 82 def contract @contract ||= begin api_request = Request.new( body: request.request_parameters, query: request.query_parameters, ).transform(&:deep_symbolize_keys) contract_class.new(action_name, api_request, coerce: true) end end |
#expose(data, meta: {}, status: nil) ⇒ Object
Exposes data as an API response.
When a representation is linked via Apiwork::Contract::Base.representation, data is serialized through the representation. Otherwise, data is rendered as-is. Key transformation is applied according to the API’s API::Base.key_format.
124 125 126 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 |
# File 'lib/apiwork/controller.rb', line 124 def expose(data, meta: {}, status: nil) if contract_class.actions[action_name.to_sym]&.response&.no_content? head :no_content return end representation_class = contract_class.representation_class body = if representation_class action = resource.actions[action_name.to_sym] if action.collection? adapter.process_collection(data, representation_class, contract.request, context:, meta:) else adapter.process_member(data, representation_class, contract.request, context:, meta:) end else data[:meta] = if .present? data.deep_symbolize_keys end response = Response.new(body: deep_as_json(body)) if Rails.env.development? result = contract_class.parse_response(response, action_name) result.issues.each { |issue| Rails.logger.warn(issue.to_s) } end response = api_class.prepare_response(response) render json: response.body, status: status || (action_name.to_sym == :create ? :created : :ok) end |
#expose_error(code_key, detail: nil, path: nil, meta: {}) ⇒ Object
Exposes an error response using a registered error code.
Defaults to I18n lookup when detail is not provided.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/apiwork/controller.rb', line 181 def expose_error( code_key, detail: nil, path: nil, meta: {} ) error_code = ErrorCode.find!(code_key) issue = Issue.new( error_code.key, detail || error_code.description(locale_key: api_class.locale_key), meta:, path: path || (error_code.attach_path? ? relative_path.split('/').reject(&:blank?) : []), ) render_error HttpError.new([issue], error_code) end |