Class: Hanami::Controller::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/hanami/controller/configuration.rb

Overview

Configuration for the framework, controllers and actions.

Hanami::Controller has its own global configuration that can be manipulated via ‘Hanami::Controller.configure`.

Every time that ‘Hanami::Controller` and `Hanami::Action` are included, that global configuration is being copied to the recipient. The copy will inherit all the settings from the original, but all the subsequent changes aren’t reflected from the parent to the children, and viceversa.

This architecture allows to have a global configuration that capture the most common cases for an application, and let controllers and single actions to specify exceptions.

Since:

  • 0.2.0

Constant Summary collapse

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.

Default HTTP code for server side errors

Since:

  • 0.2.0

500
DEFAULT_PUBLIC_DIRECTORY =

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 public directory

It serves as base root for file downloads

Since:

  • 1.0.0

'public'.freeze
DEFAULT_FORMATS =

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 Mime type to format mapping

Since:

  • 0.2.0

{
  'application/octet-stream' => :all,
  '*/*'                      => :all,
  'text/html'                => :html
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHanami::Controller::Configuration

Initialize a configuration instance

Since:

  • 0.2.0



110
111
112
# File 'lib/hanami/controller/configuration.rb', line 110

def initialize
  reset!
end

Instance Attribute Details

#action_module(value) ⇒ Object #action_moduleModule

Specify which is the default action module to be included when we use the ‘Hanami::Controller.action` method.

This setting is useful when we use multiple instances of the framework in the same process, so we want to ensure that the actions will include ‘MyApp::Action`, rather than `AnotherApp::Action`.

If not set, the default value is ‘Hanami::Action`

This is part of a DSL, for this reason when this method is called with an argument, it will set the corresponding instance variable. When called without, it will return the already set value, or the default.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.action_module # => Hanami::Action

Setting the value

require 'hanami/controller'

module MyAction
end

Hanami::Controller.configure do
  action_module MyAction
end

module Dashboard
  # It includes MyAction, instead of Hanami::Action
  class Index
    include MyAction

    def call(params)
      # ...
    end
  end
end

Duplicated framework

require 'hanami/controller'

module MyApp
  Controller = Hanami::Controller.duplicate(self)

  module Controllers::Dashboard
    include MyApp::Controller

    # It includes MyApp::Action, instead of Hanami::Action
    class Index
      include MyApp::Action

      def call(params)
        # ...
      end
    end
  end
end

Overloads:

  • #action_module(value) ⇒ Object

    Sets the given value

    Parameters:

    • value (Module)

      the module to be included in all the actions

  • #action_moduleModule

    Gets the value

    Returns:

    • (Module)

See Also:

  • Dsl#action
  • Hanami::Controller#duplicate

Since:

  • 0.2.0



306
307
308
309
310
311
312
# File 'lib/hanami/controller/configuration.rb', line 306

def action_module(value = nil)
  if value.nil?
    @action_module
  else
    @action_module = value
  end
end

#cookies(options = nil) ⇒ Object

Set default cookies options for all responses

By default this value is an empty hash.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.cookies # => {}

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  cookies({
    domain: 'hanamirb.org',
    path: '/controller',
    secure: true,
    httponly: true
  })
end

Since:

  • 0.4.0



618
619
620
621
622
623
624
625
626
# File 'lib/hanami/controller/configuration.rb', line 618

def cookies(options = nil)
  if options
    @cookies.merge!(
      options.reject { |_, v| v.nil? }
    )
  else
    @cookies
  end
end

#default_charset(charset = nil) ⇒ Object

Set a charset as default fallback for all the requests without a strict requirement for the charset.

By default this value is nil.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.default_charset # => nil

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  default_charset 'koi8-r'
end

See Also:

Since:

  • 0.3.0



559
560
561
562
563
564
565
# File 'lib/hanami/controller/configuration.rb', line 559

def default_charset(charset = nil)
  if charset
    @default_charset = charset
  else
    @default_charset
  end
end

#default_headers(headers = nil) ⇒ Object

Set default headers for all responses

By default this value is an empty hash.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.default_headers # => {}

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  default_headers({
    'X-Frame-Options' => 'DENY'
  })
end

Since:

  • 0.4.0



586
587
588
589
590
591
592
593
594
# File 'lib/hanami/controller/configuration.rb', line 586

def default_headers(headers = nil)
  if headers
    @default_headers.merge!(
      headers.reject {|_,v| v.nil? }
    )
  else
    @default_headers
  end
end

#default_request_format(format) ⇒ Object #default_request_formatSymbol?

Set a format as default fallback for all the requests without a strict requirement for the mime type.

The given format must be coercible to a symbol, and be a valid mime type alias. If it isn’t, at the runtime the framework will raise a ‘Hanami::Controller::UnknownFormatError`.

By default this value is nil.

This is part of a DSL, for this reason when this method is called with an argument, it will set the corresponding instance variable. When called without, it will return the already set value, or the default.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.default_request_format # => nil

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  default_request_format :html
end

Overloads:

  • #default_request_format(format) ⇒ Object

    Sets the given value

    Parameters:

    • format (#to_sym)

      the symbol format

    Raises:

    • (TypeError)

      if it cannot be coerced to a symbol

  • #default_request_formatSymbol?

    Gets the value

    Returns:

    • (Symbol, nil)

See Also:

Since:

  • 0.5.0



487
488
489
490
491
492
493
# File 'lib/hanami/controller/configuration.rb', line 487

def default_request_format(format = nil)
  if format
    @default_request_format = Utils::Kernel.Symbol(format)
  else
    @default_request_format
  end
end

#default_response_format(format) ⇒ Object #default_response_formatSymbol?

Set a format to be used for all responses regardless of the request type.

The given format must be coercible to a symbol, and be a valid mime type alias. If it isn’t, at the runtime the framework will raise a ‘Hanami::Controller::UnknownFormatError`.

By default this value is nil.

This is part of a DSL, for this reason when this method is called with an argument, it will set the corresponding instance variable. When called without, it will return the already set value, or the default.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.default_response_format # => nil

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  default_response_format :json
end

Overloads:

  • #default_response_format(format) ⇒ Object

    Sets the given value

    Parameters:

    • format (#to_sym)

      the symbol format

    Raises:

    • (TypeError)

      if it cannot be coerced to a symbol

  • #default_response_formatSymbol?

    Gets the value

    Returns:

    • (Symbol, nil)

See Also:

Since:

  • 0.5.0



531
532
533
534
535
536
537
# File 'lib/hanami/controller/configuration.rb', line 531

def default_response_format(format = nil)
  if format
    @default_response_format = Utils::Kernel.Symbol(format)
  else
    @default_response_format
  end
end

#handle_exceptions(value) ⇒ Object #handle_exceptionsTrueClass, FalseClass

Handle exceptions with an HTTP status or let them uncaught

If this value is set to ‘true`, the configured exceptions will return the specified HTTP status, the rest of them with `500`.

If this value is set to ‘false`, the exceptions won’t be caught.

This is part of a DSL, for this reason when this method is called with an argument, it will set the corresponding instance variable. When called without, it will return the already set value, or the default.

Examples:

Getting the value

require 'hanami/controller'

Hanami::Controller.configuration.handle_exceptions # => true

Setting the value

require 'hanami/controller'

Hanami::Controller.configure do
  handle_exceptions false
end

Overloads:

  • #handle_exceptions(value) ⇒ Object

    Sets the given value

    Parameters:

    • value (TrueClass, FalseClass)

      true or false, default to true

  • #handle_exceptionsTrueClass, FalseClass

    Gets the value

    Returns:

    • (TrueClass, FalseClass)

See Also:

Since:

  • 0.2.0



161
162
163
164
165
166
167
# File 'lib/hanami/controller/configuration.rb', line 161

def handle_exceptions(value = nil)
  if value.nil?
    @handle_exceptions
  else
    @handle_exceptions = value
  end
end

#modulesArray<Proc>

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.

Return included modules

Returns:

  • (Array<Proc>)

    array of included blocks

See Also:

Since:

  • 0.2.0



696
697
698
# File 'lib/hanami/controller/configuration.rb', line 696

def modules
  @modules
end

#public_directory(value = nil) ⇒ Object

Since:

  • 0.2.0



658
659
660
661
662
663
664
# File 'lib/hanami/controller/configuration.rb', line 658

def public_directory(value = nil)
  if value.nil?
    @public_directory
  else
    @public_directory = root_directory.join(value).to_s
  end
end

#root_directoryObject (readonly)

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:

  • 1.0.0



656
657
658
# File 'lib/hanami/controller/configuration.rb', line 656

def root_directory
  @root_directory
end

Class Method Details

.for(base) ⇒ Hanami::Controller::Configuration

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.

Return a copy of the configuration of the framework instance associated with the given class.

When multiple instances of Hanami::Controller are used in the same application, we want to make sure that a controller or an action will receive the expected configuration.

Examples:

Direct usage of the framework

require 'hanami/controller'

class Show
  include Hanami::Action
end

Hanami::Controller::Configuration.for(Show)
  # => will duplicate from Hanami::Controller

Multiple instances of the framework

require 'hanami/controller'

module MyApp
  Controller = Hanami::Controller.duplicate(self)

  module Controllers::Dashboard
    class Index
      include MyApp::Action

      def call(params)
        # ...
      end
    end
  end
end

class Show
  include Hanami::Action
end

Hanami::Controller::Configuration.for(Show)
  # => will duplicate from Hanami::Controller

Hanami::Controller::Configuration.for(MyApp::Controllers::Dashboard)
  # => will duplicate from MyApp::Controller

Parameters:

  • base (Class, Module)

    a controller or an action

Returns:

Since:

  • 0.2.0



98
99
100
101
102
# File 'lib/hanami/controller/configuration.rb', line 98

def self.for(base)
  namespace = Utils::String.new(base).namespace
  framework = Utils::Class.load_from_pattern!("(#{namespace}|Hanami)::Controller")
  framework.configuration.duplicate
end

Instance Method Details

#copy!(base) ⇒ 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.

Copy the configuration for the given action

Parameters:

  • base (Class)

    the target action

Returns:

  • void

See Also:

  • Hanami::Controller::Configurable.included

Since:

  • 0.3.0



728
729
730
731
732
# File 'lib/hanami/controller/configuration.rb', line 728

def copy!(base)
  modules.each do |mod|
    base.class_eval(&mod)
  end
end

#duplicateHanami::Controller::Configuration

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.

Duplicate by copying the settings in a new instance.

Returns:

Since:

  • 0.2.0



672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
# File 'lib/hanami/controller/configuration.rb', line 672

def duplicate
  Configuration.new.tap do |c|
    c.handle_exceptions       = handle_exceptions
    c.handled_exceptions      = handled_exceptions.dup
    c.action_module           = action_module
    c.modules                 = modules.dup
    c.formats                 = formats.dup
    c.default_request_format  = default_request_format
    c.default_response_format = default_response_format
    c.default_charset         = default_charset
    c.default_headers         = default_headers.dup
    c.public_directory        = public_directory
    c.cookies = cookies.dup
  end
end

#exception_handler(exception) ⇒ 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.

Return a callable handler for the given exception

Parameters:

  • exception (Exception)

    an exception

See Also:

Since:

  • 0.3.0



202
203
204
# File 'lib/hanami/controller/configuration.rb', line 202

def exception_handler(exception)
  exception_handler_for(exception) || DEFAULT_ERROR_CODE
end

#exception_handler_for(exception) ⇒ 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.

Finds configured handler for given exception, or nil if not found.

Parameters:

  • exception (Exception)

    an exception

See Also:

Since:

  • 1.0.0



227
228
229
230
231
232
233
# File 'lib/hanami/controller/configuration.rb', line 227

def exception_handler_for(exception)
  @handled_exceptions.each do |exception_class, handler|
    return handler if exception.kind_of?(exception_class)
  end

  nil
end

#format(hash) ⇒ Object

Register a format

Examples:

require 'hanami/controller'

Hanami::Controller.configure do
  format custom: 'application/custom'
end

module Articles
  class Index
    include Hanami::Action

    def call(params)
      # ...
    end
  end

  class Show
    include Hanami::Action

    def call(params)
      # ...
      self.format = :custom
    end
  end
end

action = Articles::Index.new

action.call({ 'HTTP_ACCEPT' => 'text/html' })
  # => Content-Type "text/html"
action.format # => :html

action.call({ 'HTTP_ACCEPT' => 'application/custom' })
  # => Content-Type "application/custom"
action.format # => :custom

action = Articles::Show.new

action.call({ 'HTTP_ACCEPT' => 'text/html' })
  # => Content-Type "application/custom"
action.format # => :custom

Parameters:

  • hash (Hash)

    the symbol format must be the key and the mime type string must be the value of the hash

See Also:

Since:

  • 0.2.0



417
418
419
420
421
422
# File 'lib/hanami/controller/configuration.rb', line 417

def format(hash)
  symbol, mime_type = *Utils::Kernel.Array(hash)

  @formats[Utils::Kernel.String(mime_type)] = Utils::Kernel.Symbol(symbol)
  @mime_types = nil
end

#format_for(mime_type) ⇒ Symbol?

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 a format for the given mime type

Parameters:

  • mime_type (#to_s, #to_str)

    A mime type

Returns:

  • (Symbol, nil)

    the corresponding format, if present

See Also:

Since:

  • 0.2.0



638
639
640
# File 'lib/hanami/controller/configuration.rb', line 638

def format_for(mime_type)
  @formats[mime_type]
end

#handle_exception(exception) ⇒ Object

Specify how to handle an exception with an HTTP status

Raised exceptions will return the configured HTTP status, only if

`handled_exceptions` is set on `true`.

Examples:

require 'hanami/controller'

Hanami::Controller.configure do
  handle_exception ArgumentError => 400
end

Parameters:

  • exception (Hash)

    the exception class must be the key and the HTTP status the value

See Also:

Since:

  • 0.2.0



189
190
191
192
# File 'lib/hanami/controller/configuration.rb', line 189

def handle_exception(exception)
  @handled_exceptions.merge!(exception)
  _sort_handled_exceptions!
end

#handled_exception?(exception) ⇒ 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.

Check if the given exception is handled.

Parameters:

  • exception (Exception)

    an exception

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.2



214
215
216
217
# File 'lib/hanami/controller/configuration.rb', line 214

def handled_exception?(exception)
  handled_exceptions &&
    !exception_handler_for(exception).nil?
end

#load!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.

Load the framework

Since:

  • 0.3.0



738
739
740
# File 'lib/hanami/controller/configuration.rb', line 738

def load!
  freeze
end

#mime_type_for(format) ⇒ String?

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 a mime type for the given format

Parameters:

  • format (#to_sym)

    a format

Returns:

  • (String, nil)

    the corresponding mime type, if present

Since:

  • 0.2.0



650
651
652
# File 'lib/hanami/controller/configuration.rb', line 650

def mime_type_for(format)
  @formats.key(format)
end

#mime_typesObject

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.

Return the configured format’s MIME types

See Also:

Since:

  • 0.8.0



431
432
433
434
435
436
# File 'lib/hanami/controller/configuration.rb', line 431

def mime_types
  @mime_types ||= begin
                    ((@formats.keys - DEFAULT_FORMATS.keys) +
                    Hanami::Action::Mime::MIME_TYPES.values).freeze
                  end
end

#prepare(&blk) ⇒ void

This method returns an undefined value.

Configure the logic to be executed when Hanami::Action is included This is useful to DRY code by having a single place where to configure shared behaviors like authentication, sessions, cookies etc.

This method can be called multiple times.

Examples:

Configure shared logic.

require 'hanami/controller'

Hanami::Controller.configure do
  prepare do
    include Hanami::Action::Session
    include MyAuthentication
    use SomeMiddleWare

    before { authenticate! }
  end
end

module Dashboard
  class Index
    # When Hanami::Action is included, it will:
    #   * Include `Hanami::Action::Session` and `MyAuthentication`
    #   * Configure to use `SomeMiddleWare`
    #   * Configure a `before` callback that triggers `#authenticate!`
    include Hanami::Action

    def call(params)
      # ...
    end
  end
end

Parameters:

  • blk (Proc)

    the code block

Raises:

  • (ArgumentError)

    if called without passing a block

See Also:

Since:

  • 0.3.0



357
358
359
360
361
362
363
# File 'lib/hanami/controller/configuration.rb', line 357

def prepare(&blk)
  if block_given?
    @modules.push(blk)
  else
    raise ArgumentError.new('Please provide a block')
  end
end

#reset!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.

Reset all the values to the defaults

Since:

  • 0.2.0



702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/hanami/controller/configuration.rb', line 702

def reset!
  @handle_exceptions       = true
  @handled_exceptions      = {}
  @modules                 = []
  @formats                 = DEFAULT_FORMATS.dup
  @mime_types              = nil
  @default_request_format  = nil
  @default_response_format = nil
  @default_charset         = nil
  @default_headers         = {}
  @cookies                 = {}
  @root_directory          = ::Pathname.new(Dir.pwd).realpath
  @public_directory        = root_directory.join(DEFAULT_PUBLIC_DIRECTORY).to_s
  @action_module           = ::Hanami::Action
end

#restrict_mime_types!(mime_types) ⇒ 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.

Restrict the MIME types set only to the given set

Parameters:

  • mime_types (Array)

    the set of MIME types

See Also:

  • Action::Mime::ClassMethods#accept

Since:

  • 1.0.0



446
447
448
# File 'lib/hanami/controller/configuration.rb', line 446

def restrict_mime_types!(mime_types)
  @mime_types = self.mime_types & mime_types
end