Class: Hanami::Action Private

Inherits:
Object
  • Object
show all
Defined in:
lib/hanami/action.rb,
lib/hanami/action/halt.rb,
lib/hanami/action/mime.rb,
lib/hanami/action/cache.rb,
lib/hanami/action/flash.rb,
lib/hanami/action/config.rb,
lib/hanami/action/errors.rb,
lib/hanami/action/params.rb,
lib/hanami/action/cookies.rb,
lib/hanami/action/request.rb,
lib/hanami/action/session.rb,
lib/hanami/action/version.rb,
lib/hanami/action/response.rb,
lib/hanami/action/constants.rb,
lib/hanami/action/rack/file.rb,
lib/hanami/action/cookie_jar.rb,
lib/hanami/action/rack_utils.rb,
lib/hanami/action/body_parser.rb,
lib/hanami/action/validatable.rb,
lib/hanami/action/cache/expires.rb,
lib/hanami/action/config/formats.rb,
lib/hanami/action/csrf_protection.rb,
lib/hanami/action/request/session.rb,
lib/hanami/action/body_parser/json.rb,
lib/hanami/action/cache/directives.rb,
lib/hanami/action/view_name_inferrer.rb,
lib/hanami/action/cache/cache_control.rb,
lib/hanami/action/cache/conditional_get.rb,
lib/hanami/action/mime/request_mime_weight.rb,
lib/hanami/action/body_parser/multipart_form.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Defined Under Namespace

Modules: BodyParser, CSRFProtection, Cache, Cookies, Halt, Mime, Rack, Session, Validatable Classes: BodyParsingError, Config, CookieJar, Error, Flash, InvalidCSRFTokenError, MissingSessionError, Params, Request, Response, UnknownFormatError, UnknownHttpStatusError, ViewNameInferrer

Constant Summary collapse

VERSION =

The current hanami-action version.

Returns:

  • (String)

Since:

  • 3.0.0

"3.0.0.rc1"
RESPONSE_CODE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Rack SPEC response code

Since:

  • 1.0.0

0
RESPONSE_HEADERS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Rack SPEC response headers

Since:

  • 1.0.0

1
RESPONSE_BODY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Rack SPEC response body

Since:

  • 1.0.0

2
DEFAULT_ERROR_CODE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 1.0.0

500
HTTP_STATUSES_WITHOUT_BODY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Status codes that by RFC must not include a message body

Since:

  • 0.3.2

Set.new((100..199).to_a << 204 << 205 << 304).freeze
NOT_FOUND =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Not Found

Since:

  • 1.0.0

404
ENTITY_HEADERS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Entity headers allowed in blank body responses, according to RFC 2616 - Section 10 (HTTP 1.1).

“The response MAY include new or updated metainformation in the form

of entity-headers".
{
  "allow" => true,
  "content-encoding" => true,
  "content-language" => true,
  "content-location" => true,
  "content-md5" => true,
  "content-range" => true,
  "expires" => true,
  "last-modified" => true,
  "extension-header" => true
}.freeze
PATH_INFO =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The request relative path

Since:

  • 2.0.0

::Rack::PATH_INFO
CONTENT_TYPE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The request content type (env key, CGI-style uppercase). Rack exposes a ‘CONTENT_TYPE` constant but it refers to the response header (lowercase in Rack 3), not the env key.

Since:

  • 0.1.0

"CONTENT_TYPE"
REQUEST_METHOD =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The request method

Since:

  • 0.3.2

::Rack::REQUEST_METHOD
CONTENT_LENGTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The Content-Length HTTP header

Since:

  • 1.0.0

::Rack::CONTENT_LENGTH
X_CASCADE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The non-standard HTTP header to pass the control over when a resource cannot be found by the current endpoint

Since:

  • 1.0.0

"X-Cascade"
HEAD =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

HEAD request

Since:

  • 0.3.2

::Rack::HEAD
GET =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

GET request

Since:

  • 2.0.0

::Rack::GET
TRACE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

TRACE request

Since:

  • 2.0.0

::Rack::TRACE
OPTIONS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

OPTIONS request

Since:

  • 2.0.0

::Rack::OPTIONS
HTTP_ACCEPT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns accepted mime types from the Rack env

Since:

  • 0.1.0

"HTTP_ACCEPT"
DEFAULT_ACCEPT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The default mime type for an incoming HTTP request

Since:

  • 0.1.0

"*/*"
DEFAULT_CONTENT_TYPE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The default mime type that is returned in the response

Since:

  • 0.1.0

"application/octet-stream"
RACK_ERRORS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 0.2.0

::Rack::RACK_ERRORS
CACHE_CONTROL =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The HTTP header for Cache-Control

Since:

  • 2.0.0

::Rack::CACHE_CONTROL
IF_NONE_MATCH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0

"HTTP_IF_NONE_MATCH"
ETAG =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The HTTP header for ETag

Since:

  • 2.0.0

::Rack::ETAG
IF_MODIFIED_SINCE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0

"HTTP_IF_MODIFIED_SINCE"
EXPIRES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The HTTP header for Expires

Since:

  • 2.0.0

::Rack::EXPIRES
LAST_MODIFIED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The HTTP header for Last-Modified

Since:

  • 0.3.0

"Last-Modified"
RACK_EXCEPTION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

This isn’t part of Rack SPEC

Exception notifiers use rack.exception instead of rack.errors, so we need to support it.

"rack.exception"
LOCATION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The HTTP header for redirects

Since:

  • 0.2.0

"Location"
RACK_SESSION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns Rack session params from the Rack env Please note that this is used only when an action is unit tested.

Examples:

# action unit test
action.call("rack.session" => { "foo" => "bar" })
action.session[:foo] # => "bar"

Since:

  • 2.0.0

::Rack::RACK_SESSION
REQUEST_ID =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0

"hanami.request_id"
DEFAULT_ID_LENGTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0

16
::Rack::HTTP_COOKIE
::Rack::RACK_REQUEST_COOKIE_HASH
::Rack::RACK_REQUEST_COOKIE_STRING
RACK_INPUT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns raw input from the Rack env

Since:

  • 2.0.0

::Rack::RACK_INPUT
ACTION_PARSED_BODY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns a request body parsed by Hanami Action.

This is the canonical key for body parsing.

Since:

  • x.x.x

"hanami.action.parsed_body"
ACTION_BODY_PARAMS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns params from a parsed body by Hanami Action.

This is the canonical key for parsed body params.

Since:

  • x.x.x

"hanami.action.body_params"
ROUTER_PARSED_BODY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns a request body parsed by Hanami Router.

This is maintained for backward compatibility with Hanami Router.

Since:

  • 0.1.0

"router.parsed_body"
ROUTER_PARAMS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The key that returns router params from the Rack env.

This is maintained for backward compatibility with Hanami Router.

Since:

  • 2.0.0

"router.params"
DEFAULT_REQUEST_METHOD =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Default HTTP request method for Rack env

Since:

  • 2.0.0

GET
DEFAULT_CHARSET =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0

"utf-8"
ACTION_INSTANCE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.2.0

"hanami.action_instance"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config: self.class.config, contract: nil) ⇒ Action

Returns a new action

Since:

  • 2.0.0



315
316
317
318
319
320
321
322
# File 'lib/hanami/action.rb', line 315

def initialize(config: self.class.config, contract: nil)
  @config = config.finalize!.to_data
  @contract = contract || config.contract_class&.new # TODO: tests showing this overridden by a dep
  @default_charset = @config.default_charset || DEFAULT_CHARSET
  @default_response_content_type = Mime.default_response_content_type_with_charset(@config)
  @default_response_format = Mime.format_from_media_type(@default_response_content_type, @config)
  freeze
end

Class Method Details

.self.append_after(*callbacks, &block) ⇒ void Also known as: after

This method returns an undefined value.

Define a callback for an Action. The callback will be executed after the action is called, in the order they are added.

Parameters:

  • callbacks (Symbol, Array<Symbol>)

    a single or multiple symbol(s) each of them is representing a name of a method available in the context of the Action.

  • blk (Proc)

    an anonymous function to be executed

See Also:

  • Hanami::Action::Callbacks::ClassMethods#append_before

Since:

  • 0.3.2

Since:

  • 0.1.0



226
227
228
# File 'lib/hanami/action.rb', line 226

def self.append_after(...)
  config.after_callbacks.append(...)
end

.self.append_before(*callbacks, &block) ⇒ void Also known as: before

This method returns an undefined value.

Define a callback for an Action. The callback will be executed before the action is called, in the order they are added.

Examples:

Method names (symbols)

require "hanami/action"

class Show < Hanami::Action
  before :authenticate, :set_article

  def handle(request, response)
  end

  private
  def authenticate
    # ...
  end

  # `params` in the method signature is optional
  def set_article(params)
    @article = Article.find params[:id]
  end
end

# The order of execution will be:
#
# 1. #authenticate
# 2. #set_article
# 3. #call

Anonymous functions (Procs)

require "hanami/action"

class Show < Hanami::Action
  before { ... } # 1 do some authentication stuff
  before {|request, response| @article = Article.find params[:id] } # 2

  def handle(request, response)
  end
end

# The order of execution will be:
#
# 1. authentication
# 2. set the article
# 3. `#handle`

Parameters:

  • callbacks (Symbol, Array<Symbol>)

    a single or multiple symbol(s) each of them is representing a name of a method available in the context of the Action.

  • blk (Proc)

    an anonymous function to be executed

See Also:

  • Hanami::Action::Callbacks::ClassMethods#append_after

Since:

  • 0.3.2

Since:

  • 0.1.0



201
202
203
# File 'lib/hanami/action.rb', line 201

def self.append_before(...)
  config.before_callbacks.append(...)
end

.configConfig

Returns the action’s config. Use this to configure your action.

Examples:

Access inside class body

class Show < Hanami::Action
  config.format :json
end

Returns:

Since:

  • 2.0.0



# File 'lib/hanami/action.rb', line 86

.contractObject

Placeholder for the ‘.contract` method. Raises an error when the dry-validation gem is not installed.

Raises:

  • (NoMethodError)

Since:

  • 2.2.0



137
138
139
140
# File 'lib/hanami/action.rb', line 137

def self.contract
  message = %(To use `.contract`, please add the "dry-validation" gem to your Gemfile)
  raise NoMethodError, message
end

.gem_loaderObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/hanami/action.rb', line 35

def self.gem_loader
  @gem_loader ||= Zeitwerk::Loader.new.tap do |loader|
    root = File.expand_path("..", __dir__)
    loader.tag = "hanami-action"
    loader.inflector = Zeitwerk::GemInflector.new("#{root}/hanami-action.rb")
    loader.push_dir(root)
    loader.ignore(
      "#{root}/hanami-action.rb",
      "#{root}/hanami-controller.rb",
      "#{root}/hanami/action/version.rb",
      "#{root}/hanami/action/{constants,errors,rack_utils,validatable}.rb"
    )
    loader.inflector.inflect(
      "csrf_protection" => "CSRFProtection",
      "json" => "JSON"
    )
  end
end

.handle_exceptionObject



279
280
281
# File 'lib/hanami/action.rb', line 279

def self.handle_exception(...)
  config.handle_exception(...)
end

.inherited(subclass) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Override Ruby’s hook for modules. It includes basic Hanami::Action modules to the given class.

Parameters:

  • subclass (Class)

    the target action

Since:

  • 0.1.0



108
109
110
111
112
113
114
115
116
# File 'lib/hanami/action.rb', line 108

def self.inherited(subclass)
  super

  if subclass.superclass == Action
    subclass.class_eval do
      include Validatable if defined?(Validatable)
    end
  end
end

.params(_klass = nil) ⇒ Object

Placeholder for the ‘.params` method. Raises an error when the dry-validation gem is not installed.

Raises:

  • (NoMethodError)

Since:

  • 2.0.0



125
126
127
128
# File 'lib/hanami/action.rb', line 125

def self.params(_klass = nil)
  message = %(To use `.params`, please add the "dry-validation" gem to your Gemfile)
  raise NoMethodError, message
end

.self.prepend_after(*callbacks, &block) ⇒ void

This method returns an undefined value.

Define a callback for an Action. The callback will be executed after the action is called. It will add the callback at the beginning of the callbacks’ chain.

Parameters:

  • callbacks (Symbol, Array<Symbol>)

    a single or multiple symbol(s) each of them is representing a name of a method available in the context of the Action.

  • blk (Proc)

    an anonymous function to be executed

See Also:

  • Hanami::Action::Callbacks::ClassMethods#prepend_before

Since:

  • 0.3.2

Since:

  • 0.1.0



271
272
273
# File 'lib/hanami/action.rb', line 271

def self.prepend_after(...)
  config.after_callbacks.prepend(...)
end

.self.prepend_before(*callbacks, &block) ⇒ void

This method returns an undefined value.

Define a callback for an Action. The callback will be executed before the action is called. It will add the callback at the beginning of the callbacks’ chain.

Parameters:

  • callbacks (Symbol, Array<Symbol>)

    a single or multiple symbol(s) each of them is representing a name of a method available in the context of the Action.

  • blk (Proc)

    an anonymous function to be executed

See Also:

  • Hanami::Action::Callbacks::ClassMethods#prepend_after

Since:

  • 0.3.2

Since:

  • 0.1.0



251
252
253
# File 'lib/hanami/action.rb', line 251

def self.prepend_before(...)
  config.before_callbacks.prepend(...)
end

.rack_3?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

Since:

  • 2.2.0



7
8
9
# File 'lib/hanami/action/rack_utils.rb', line 7

def self.rack_3?
  defined?(::Rack::Headers)
end

Instance Method Details

#call(env) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Implements the Rack/Hanami::Action protocol

Since:

  • 0.1.0



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/hanami/action.rb', line 330

def call(env)
  request  = nil
  response = nil

  halted = catch :halt do
    # Catch body parsing errors early, and wait to raise them until _after_ we've built our
    # request and response, to give exception handlers real objects to work with.
    body_parse_error = nil
    begin
      BodyParser.parse env, config
    rescue BodyParsingError => exception
      body_parse_error = exception
    end

    params = Params.new(
      # Create empty params if body parsing failed, to avoid validating corrupted input.
      env: body_parse_error ? {} : env,
      contract: contract
    )

    # Ensure env has REQUEST_METHOD for downstream code (e.g. Response) when actions are called
    # with a direct params hash as a testing convenience.
    env[REQUEST_METHOD] ||= DEFAULT_REQUEST_METHOD

    request = build_request(
      env: env,
      params: params,
      session_enabled: session_enabled?,
      default_tld_length: config.default_tld_length
    )

    content_type =
      if request.accept_header?
        Mime.response_content_type_with_charset(request, config)
      else
        default_response_content_type
      end

    response = build_response(
      request: request,
      config: config,
      content_type: content_type,
      charset: default_charset,
      env: env,
      headers: config.default_headers,
      session_enabled: session_enabled?
    )

    raise body_parse_error if body_parse_error

    enforce_accepted_media_types(request)

    _run_before_callbacks(request, response)
    handle(request, response)
    _run_after_callbacks(request, response)
  rescue StandardError => exception
    _handle_exception(request, response, exception)
  end

  # Before finishing, put ourself into the Rack env for third-party instrumentation tools to
  # integrate with actions
  env[ACTION_INSTANCE] = self

  finish(request, response, halted)
end