Class: ActionController::API
- Defined in:
- runtime/action_controller/api.rb,
runtime/action_controller/api.rbs,
runtime/action_controller/current.rbs,
runtime/action_controller/http_authentication.rbs,
runtime/action_controller/current.rb,
runtime/action_controller/http_authentication.rb
Overview
The controller base class: per-request state (params) and response state
(status, body, location). The action dispatch (process_action) and the
before_action filter chain live here; subclasses define their actions and
filter registrations.
Direct Known Subclasses
Constant Summary collapse
- BEFORE_FILTERS =
---- before_action filter chain -------------------------------------- Shaped by spinel's limits: no callback chain, no ancestor propagation of registration (the
inheritedhook is never called). The module-level constant Array below is the registry; a class ivar is not carried. Per-method contracts sit onbefore_actionandrun_before_filters. []
Instance Attribute Summary collapse
-
#accepts_any_format ⇒ Boolean
true when the request's Accept is a bare
*/*, an XMLHttpRequest or fetch that named none, which reads as "any format". -
#action_name ⇒ Symbol?
the current action: the run-time context the
only:/except:gate reads. - #body ⇒ String readonly
-
#cache_control_max_age ⇒ Object
readonly
Cache-Control as two typed readers rather than one mixed Hash: an Integer and a boolean in one container leaves every subscript with a union type for the compiler to infer.
-
#cache_control_public ⇒ Object
readonly
Cache-Control as two typed readers rather than one mixed Hash: an Integer and a boolean in one container leaves every subscript with a union type for the compiler to infer.
- #content_type ⇒ String readonly
- #location ⇒ String? readonly
-
#path_parameters ⇒ Hash{String => String}
the matched route's own segments (
{"length" => "1y"}on/top/1y), not the query string. -
#request ⇒ ActionDispatch::Request?
the request object the dispatcher wires before the action runs.
- #request_format ⇒ Symbol
- #request_method ⇒ String
- #request_path ⇒ String
- #status ⇒ Integer readonly
Class Method Summary collapse
-
.before_action(*names, only: nil, except: nil) ⇒ Object
register before-filters for the receiving controller class.
Instance Method Summary collapse
-
#authenticate_or_request_with_http_basic(realm = "Application", message = nil) ⇒ Object?
yield the presented credentials to the block.
-
#authenticate_or_request_with_http_token(realm = "Application", message = nil) ⇒ Object?
yield the presented token and its options to the block.
-
#authenticate_with_http_basic {|pair[0], pair[1]| ... } ⇒ Object?
yield the presented Basic credentials to the block.
-
#authenticate_with_http_token {|token, token_options(HttpAuthentication.authorization(self))| ... } ⇒ Object?
yield the presented token and its options to the block.
-
#expires_in(seconds, public: false, stale_while_revalidate: 0) ⇒ void
the Cache-Control writer: it stores the two facts and writes no header (see
headers). -
#fresh_when(subject) ⇒ void
the conditional-GET hook: it takes the subject a caller would send validators for and stores nothing, because this runtime never answers a 304 and always renders.
-
#head(status, content_type: nil, location: nil) ⇒ void
empty body, status only.
- #headers ⇒ Hash[String, String]
-
#initialize ⇒ API
constructor
A new instance of API.
-
#params ⇒ Hash{String => untyped}
the request params an action reads (
params["id"]). - #params=(value) ⇒ Hash[String, untyped]
-
#performed? ⇒ Boolean
true once render/redirect_to/head has produced a response.
-
#process_action(action_name) ⇒ void
dispatch one matched action: set the action context, run the controller's registered before-filters, then hand off to
send_action. -
#redirect_to(path, status: :found) ⇒ void
sets location and status.
-
#render(body = nil, status: :ok, content_type: nil, location: nil, json: JSON_NOT_GIVEN) ⇒ void
sets @body, @status, and optionally @content_type / @location.
-
#request_http_basic_authentication(realm = "Application", message = nil) ⇒ void
answer the request with a 401 whose
WWW-Authenticatecarries the Basic challenge. -
#request_http_token_authentication(realm = "Application", message = nil) ⇒ void
answer the request with a 401 whose
WWW-Authenticatecarries the Token challenge. -
#resolve_status(s) ⇒ Integer
a status to its HTTP integer code.
-
#response ⇒ API
the surface app actions write headers through (
response.headers["Expires"] = ...). -
#run_before_filters ⇒ void
run this controller's registered before-filters in registration order, each gated by its
only:/except:lists. -
#send_action(action_name) ⇒ void
call the action by name, then answer 204 No Content when it produced no response.
-
#send_data(data, type: "application/octet-stream", disposition: "attachment") ⇒ void
a binary response body, buffered like
render. -
#stale?(etag: nil) ⇒ Boolean
always true: this controller never answers a 304, so the validator argument is accepted and ignored.
Constructor Details
#initialize ⇒ API
Returns a new instance of API.
25 |
# File 'runtime/action_controller/api.rbs', line 25
def initialize: () -> void
|
Instance Attribute Details
#accepts_any_format ⇒ Boolean
true when the request's Accept is a bare */*, an XMLHttpRequest or fetch
that named none, which reads as "any format". The dispatcher sets it;
false keeps every other request on the html path.
64 |
# File 'runtime/action_controller/api.rb', line 64
def accepts_any_format: () -> bool
|
#action_name ⇒ Symbol?
the current action: the run-time context the only:/except: gate reads.
The action dispatch sets it before run_before_filters. Nil before any
dispatch set it, and a conditional filter run without it raises rather
than silently applying to every action (or none).
58 |
# File 'runtime/action_controller/api.rb', line 58
def action_name: () -> Symbol?
|
#body ⇒ String (readonly)
19 |
# File 'runtime/action_controller/api.rbs', line 19
def body: () -> String
|
#cache_control_max_age ⇒ Object (readonly)
Cache-Control as two typed readers rather than one mixed Hash: an
Integer and a boolean in one container leaves every subscript with a
union type for the compiler to infer. The test harness re-assembles
the Hash shape (ActionResponse#cache_control), the only reader that
wants the subscript spelling.
77 |
# File 'runtime/action_controller/api.rb', line 77
def cache_control_max_age: () -> Integer
|
#cache_control_public ⇒ Object (readonly)
Cache-Control as two typed readers rather than one mixed Hash: an
Integer and a boolean in one container leaves every subscript with a
union type for the compiler to infer. The test harness re-assembles
the Hash shape (ActionResponse#cache_control), the only reader that
wants the subscript spelling.
77 |
# File 'runtime/action_controller/api.rb', line 77
def cache_control_public: () -> bool
|
#content_type ⇒ String (readonly)
21 |
# File 'runtime/action_controller/api.rbs', line 21
def content_type: () -> String
|
#location ⇒ String? (readonly)
20 |
# File 'runtime/action_controller/api.rbs', line 20
def location: () -> String?
|
#path_parameters ⇒ Hash{String => String}
the matched route's own segments ({"length" => "1y"} on /top/1y), not
the query string. The dispatcher assigns it; a caller building a URL from
options reads it back to fill a segment the options leave out.
70 |
# File 'runtime/action_controller/api.rb', line 70
def path_parameters: () -> Hash[String, String]
|
#request ⇒ ActionDispatch::Request?
the request object the dispatcher wires before the action runs.
23 |
# File 'runtime/action_controller/current.rb', line 23
def request: () -> ActionDispatch::Request?
|
#request_format ⇒ Symbol
9 |
# File 'runtime/action_controller/api.rbs', line 9
def request_format: () -> Symbol
|
#request_method ⇒ String
5 |
# File 'runtime/action_controller/api.rbs', line 5
def request_method: () -> String
|
#request_path ⇒ String
7 |
# File 'runtime/action_controller/api.rbs', line 7
def request_path: () -> String
|
#status ⇒ Integer (readonly)
18 |
# File 'runtime/action_controller/api.rbs', line 18
def status: () -> Integer
|
Class Method Details
.before_action(*names, only: nil, except: nil) ⇒ Object
register before-filters for the receiving controller class. Each name is a
Symbol method the chain dispatches with send at run time — the method
may live on the controller or a parent, and private is fine (send
reaches both). Registration records the owner class: a filter runs only on
instances of the class that registered it — the inherited hook is never
called, so the registration itself does not propagate to subclasses
(declare it there again, or share the method on a parent).
140 |
# File 'runtime/action_controller/api.rb', line 140
def self.before_action: (*Symbol names, ?only: (Symbol | Array[Symbol])?, ?except: (Symbol | Array[Symbol])?) -> void
|
Instance Method Details
#authenticate_or_request_with_http_basic(realm = "Application", message = nil) ⇒ Object?
yield the presented credentials to the block. A falsy answer, or no Basic credentials at all, sends a 401 with the Basic challenge and marks the response performed, which halts the filter chain.
87 |
# File 'runtime/action_controller/http_authentication.rb', line 87
def authenticate_or_request_with_http_basic: (?String realm, ?String? message) { (String username, String password) -> untyped } -> untyped
|
#authenticate_or_request_with_http_token(realm = "Application", message = nil) ⇒ Object?
yield the presented token and its options to the block. A falsy answer, or no token at all, sends a 401 with the Token challenge and marks the response performed, which halts the filter chain.
The block is yielded to directly rather than forwarded to
authenticate_with_http_token: an explicit &block parameter is a Proc
value, which the AOT path types far less precisely than a yield it
can see the caller's block for.
45 |
# File 'runtime/action_controller/http_authentication.rb', line 45
def authenticate_or_request_with_http_token: (?String realm, ?String? message) { (String token, Hash[String, String] options) -> untyped } -> untyped
|
#authenticate_with_http_basic {|pair[0], pair[1]| ... } ⇒ Object?
yield the presented Basic credentials to the block. No challenge goes out: a header without Basic credentials answers nil, and the caller decides what to do about it.
72 |
# File 'runtime/action_controller/http_authentication.rb', line 72
def authenticate_with_http_basic: () { (String username, String password) -> untyped } -> untyped
|
#authenticate_with_http_token {|token, token_options(HttpAuthentication.authorization(self))| ... } ⇒ Object?
yield the presented token and its options to the block. No challenge goes out: a header without a Token or Bearer credential answers nil, and the caller decides what to do about it.
27 |
# File 'runtime/action_controller/http_authentication.rb', line 27
def authenticate_with_http_token: () { (String token, Hash[String, String] options) -> untyped } -> untyped
|
#expires_in(seconds, public: false, stale_while_revalidate: 0) ⇒ void
the Cache-Control writer: it stores the two facts and writes no header
(see headers).
Seconds, not a Duration: the lowering unwraps 1.year at the call
site, so the signature stays Integer. stale_while_revalidate: 0
means "not stated", which keeps it Integer rather than nullable; the
value itself is not stored.
363 |
# File 'runtime/action_controller/api.rb', line 363
def expires_in: (Integer seconds, ?public: bool, ?stale_while_revalidate: Integer) -> void
|
#fresh_when(subject) ⇒ void
the conditional-GET hook: it takes the subject a caller would send validators for and stores nothing, because this runtime never answers a 304 and always renders.
The body is empty, not a bare nil: a nil-only body gives the
compiler an optional type with nothing to infer its parameter from,
where an empty body is a plain void.
339 |
# File 'runtime/action_controller/api.rb', line 339
def fresh_when: (untyped subject) -> void
|
#head(status, content_type: nil, location: nil) ⇒ void
empty body, status only. content_type is optional: omit it and the
default text/html stands, while an explicit value costs nothing — clients
may still parse the header.
location: records the resource a 201 created
(head :created, location: ...). It is not a redirect — that is a
3xx status — so a location beside a 201 is only a stated URL.
293 |
# File 'runtime/action_controller/api.rb', line 293
def head: (Symbol | Integer status, ?content_type: String?, ?location: String?) -> void
|
#headers ⇒ Hash[String, String]
52 |
# File 'runtime/action_controller/api.rbs', line 52
def headers: () -> Hash[String, String]
|
#params ⇒ Hash{String => untyped}
the request params an action reads (params["id"]). The value lives in
@_params, outside the app-subclass namespace: an app-side @params is a
mistake, not a second handle on request state. The scaffold contract
(verify-scaffold) rejects @params in app code, and reading through the
accessor lets the value change shape later without touching call sites.
The values are the request's scalars, arrays, hashes, and uploaded files; a key carried without a value is nil. The tree is a mutable plain Hash, so the accessor stays untyped.
42 |
# File 'runtime/action_controller/api.rb', line 42
def params: () -> Hash[String, untyped]
|
#params=(value) ⇒ Hash[String, untyped]
4 |
# File 'runtime/action_controller/api.rbs', line 4
def params=: (Hash[String, untyped]) -> Hash[String, untyped]
|
#performed? ⇒ Boolean
true once render/redirect_to/head has produced a response. Two gates read
it: the action dispatch skips the action after a filter that responded
(the halting rule), and send_action skips the implicit 204 once anything
— filter or action — has answered.
107 |
# File 'runtime/action_controller/api.rb', line 107
def performed?: () -> bool
|
#process_action(action_name) ⇒ void
dispatch one matched action: set the action context, run the controller's
registered before-filters, then hand off to send_action.
A filter that responds (render/redirect/head) marks the response
performed and the action is skipped — the halting rule. A name with
no method raises rather than answering a silent empty 200.
Subclasses override only to wrap this preamble (e.g. a locale
around-block); an override that replaces the dispatch entirely
must call send_action (not bare send) in its place or its
actions lose the implicit 204.
189 |
# File 'runtime/action_controller/api.rb', line 189
def process_action: (Symbol action_name) -> void
|
#redirect_to(path, status: :found) ⇒ void
sets location and status. The default is 302 (Found); a PATCH/DELETE
response that must not be replayed passes status: :see_other (303).
275 |
# File 'runtime/action_controller/api.rb', line 275
def redirect_to: (String path, ?status: Symbol | Integer) -> void
|
#render(body = nil, status: :ok, content_type: nil, location: nil, json: JSON_NOT_GIVEN) ⇒ void
sets @body, @status, and optionally @content_type / @location. The
location: kwarg sets @location so the response ships a Location header
alongside the rendered body — the
render :show, status: :created, location: @article idiom for POST 201
responses. Distinct from redirect_to (which uses a 3xx status); main.rb
dispatches on status, not on @location nil-ness.
The json: keyword is the payload form: render json: value
encodes the value with ActionController::JsonRender and answers
JSON_CONTENT_TYPE unless content_type: names another. It takes a
payload, not encoded text — render json: "hi" answers "hi"
with quotes; already-encoded JSON belongs in the positional body,
which is what render(JsonRender.encode(v), content_type: ...)
keeps producing. Exactly one of the two bodies must be given: a
caller that passes neither forgot the argument, and a caller that
passes both left two answerable meanings, so both raise instead
of guessing. json: carries nil fine — it encodes to null, and
the JSON_NOT_GIVEN sentinel is what keeps that apart from an
omitted keyword.
253 |
# File 'runtime/action_controller/api.rb', line 253
def render: (
|
#request_http_basic_authentication(realm = "Application", message = nil) ⇒ void
answer the request with a 401 whose WWW-Authenticate carries the Basic
challenge. The render marks the response performed, so the filter chain
stops here.
105 |
# File 'runtime/action_controller/http_authentication.rb', line 105
def request_http_basic_authentication: (?String realm, ?String? message) -> void
|
#request_http_token_authentication(realm = "Application", message = nil) ⇒ void
answer the request with a 401 whose WWW-Authenticate carries the Token
challenge. The render marks the response performed, so the filter chain
stops here.
60 |
# File 'runtime/action_controller/http_authentication.rb', line 60
def request_http_token_authentication: (?String realm, ?String? message) -> void
|
#resolve_status(s) ⇒ Integer
a status to its HTTP integer code. Both forms are accepted: a Symbol
resolves through Snails::Utils::SYMBOL_TO_STATUS_CODE, and an Integer is
used as given within 100..599. Anything else raises — a value the caller
mistyped (status: 2000, status: :okay) must not fall through to the
200 default and read as a normal success. The message names both accepted
forms so the caller can fix the line from the raise.
395 |
# File 'runtime/action_controller/api.rb', line 395
def resolve_status: (Symbol | Integer s) -> Integer
|
#response ⇒ API
the surface app actions write headers through
(response.headers["Expires"] = ...). The controller is its own buffered
response, so response returns self and headers the extra-header hash.
Those headers are buffered but not sent yet; they tune caching, not
content.
308 |
# File 'runtime/action_controller/api.rb', line 308
def response: () -> API
|
#run_before_filters ⇒ void
run this controller's registered before-filters in registration order,
each gated by its only:/except: lists. The chain stops at the first
filter that has produced a response: a filter that renders/redirects/heads
skips the remaining filters and, at the call site, the action body.
162 |
# File 'runtime/action_controller/api.rb', line 162
def run_before_filters: () -> void
|
#send_action(action_name) ⇒ void
call the action by name, then answer 204 No Content when it produced no
response. The implicit-render half of dispatch: an action with nothing to
return still owes the caller a definite status, and the constructor's
empty 200 says "success with a body" while carrying neither — a failure
class that slips past any :success assertion. 204 is the definite answer
for "done, nothing to return" (DELETE acknowledgements and other
fire-and-forget writes are the common shape).
performed? is the gate on purpose: a response already produced —
by the action body, or by a before-filter that halted the chain —
is the answer and is never overwritten (head would clobber a
rendered status and body). Wrapping callers (a preamble that runs
the filters itself) call this rather than send so their actions
keep the implicit render.
215 |
# File 'runtime/action_controller/api.rb', line 215
def send_action: (Symbol action_name) -> void
|
#send_data(data, type: "application/octet-stream", disposition: "attachment") ⇒ void
a binary response body, buffered like render. disposition is accepted
but not written out: the Content-Disposition header stays buffered like
the ones in headers until the response ships.
379 |
# File 'runtime/action_controller/api.rb', line 379
def send_data: (String data, ?type: String, ?disposition: String) -> void
|
#stale?(etag: nil) ⇒ Boolean
always true: this controller never answers a 304, so the validator argument is accepted and ignored.
347 |
# File 'runtime/action_controller/api.rb', line 347
def stale?: (?etag: untyped) -> bool
|