class Hanami::Controller::Configuration
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
Constants
- DEFAULT_ERROR_CODE
Default HTTP code for server side errors
@since 0.2.0 @api private
- DEFAULT_FORMATS
Default Mime type to format mapping
@since 0.2.0 @api private
- DEFAULT_PUBLIC_DIRECTORY
Default public directory
It serves as base root for file downloads
@since 1.0.0 @api private
Attributes
@attr_writer handle_exceptions
[TrueClass,FalseClass] Handle exceptions
with an HTTP status or leave them uncaught
@since 0.2.0
@return void
Return included modules
@return [Array<Proc>] array of included blocks
@since 0.2.0 @api private
@api private @since 1.0.0
Public Class Methods
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.
@param base [Class, Module] a controller or an action
@return [Hanami::Controller::Configuration] the configuration associated
to the given class.
@since 0.2.0 @api private
@example Direct usage of the framework
require 'hanami/controller' class Show include Hanami::Action end Hanami::Controller::Configuration.for(Show) # => will duplicate from Hanami::Controller
@example 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
# File lib/hanami/controller/configuration.rb, line 98 def self.for(base) namespace = Utils::String.namespace(base.name) framework = Utils::Class.load("#{namespace}::Controller") || Utils::Class.load!('Hanami::Controller') framework.configuration.duplicate end
Initialize a configuration instance
@return [Hanami::Controller::Configuration] a new configuration's
instance
@since 0.2.0
# File lib/hanami/controller/configuration.rb, line 110 def initialize reset! end
Public Instance Methods
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.
@overload action_module
(value)
Sets the given value @param value [Module] the module to be included in all the actions
@overload action_module
Gets the value @return [Module]
@since 0.2.0
@see Hanami::Controller::Dsl#action @see Hanami::Controller#duplicate
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.action_module # => Hanami::Action
@example 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
@example 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
# File lib/hanami/controller/configuration.rb, line 306 def action_module(value = nil) if value.nil? @action_module else @action_module = value end end
Copy the configuration for the given action
@param base [Class] the target action
@return void
@since 0.3.0 @api private
@see Hanami::Controller::Configurable.included
# File lib/hanami/controller/configuration.rb, line 728 def copy!(base) modules.each do |mod| base.class_eval(&mod) end end
Set a charset as default fallback for all the requests without a strict requirement for the charset.
By default this value is nil.
@since 0.3.0
@see Hanami::Action::Mime
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.default_charset # => nil
@example Setting the value
require 'hanami/controller' Hanami::Controller.configure do default_charset 'koi8-r' end
# File lib/hanami/controller/configuration.rb, line 559 def default_charset(charset = nil) if charset @default_charset = charset else @default_charset end end
Set default headers for all responses
By default this value is an empty hash.
@since 0.4.0
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.default_headers # => {}
@example Setting the value
require 'hanami/controller' Hanami::Controller.configure do default_headers({ 'X-Frame-Options' => 'DENY' }) end
# 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
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.
@overload default_request_format
(format)
Sets the given value @param format [#to_sym] the symbol format @raise [TypeError] if it cannot be coerced to a symbol
@overload default_request_format
Gets the value @return [Symbol,nil]
@since 0.5.0
@see Hanami::Action::Mime
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.default_request_format # => nil
@example Setting the value
require 'hanami/controller' Hanami::Controller.configure do default_request_format :html end
# 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
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.
@overload default_response_format
(format)
Sets the given value @param format [#to_sym] the symbol format @raise [TypeError] if it cannot be coerced to a symbol
@overload default_response_format
Gets the value @return [Symbol,nil]
@since 0.5.0
@see Hanami::Action::Mime
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.default_response_format # => nil
@example Setting the value
require 'hanami/controller' Hanami::Controller.configure do default_response_format :json end
# 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
Duplicate by copying the settings in a new instance.
@return [Hanami::Controller::Configuration] a copy of the configuration
@since 0.2.0 @api private
# 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
Return a callable handler for the given exception
@param exception [Exception] an exception
@since 0.3.0 @api private
@see Hanami::Controller::Configuration#handle_exception
# File lib/hanami/controller/configuration.rb, line 202 def exception_handler(exception) exception_handler_for(exception) || DEFAULT_ERROR_CODE end
Finds configured handler for given exception, or nil if not found.
@param exception [Exception] an exception
@since 1.0.0 @api private
@see Hanami::Controller::Configuration#handle_exception
# 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
Register a format
@param hash [Hash] the symbol format must be the key and the mime type
string must be the value of the hash
@since 0.2.0
@see Hanami::Action::Mime
@example
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
# 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
Returns a format for the given mime type
@param mime_type [#to_s,#to_str] A mime type
@return [Symbol,nil] the corresponding format, if present
@see Hanami::Controller::Configuration#format
@since 0.2.0 @api private
# File lib/hanami/controller/configuration.rb, line 638 def format_for(mime_type) @formats[mime_type] end
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`.
@param exception [Hash] the exception class must be the key and the HTTP
status the value
@since 0.2.0
@see Hanami::Controller::Configuration#handle_exceptions
@see Hanami::Controller#configure @see Hanami::Action::Throwable
@example
require 'hanami/controller' Hanami::Controller.configure do handle_exception ArgumentError => 400 end
# File lib/hanami/controller/configuration.rb, line 189 def handle_exception(exception) @handled_exceptions.merge!(exception) _sort_handled_exceptions! end
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.
@overload handle_exceptions
(value)
Sets the given value @param value [TrueClass, FalseClass] true or false, default to true
@overload handle_exceptions
Gets the value @return [TrueClass, FalseClass]
@since 0.2.0
@see Hanami::Controller::Configuration#handle_exception
@see Hanami::Controller#configure @see Hanami::Action::Throwable
@see httpstatus.es/500
@example Getting the value
require 'hanami/controller' Hanami::Controller.configuration.handle_exceptions # => true
@example Setting the value
require 'hanami/controller' Hanami::Controller.configure do handle_exceptions false end
# File lib/hanami/controller/configuration.rb, line 161 def handle_exceptions(value = nil) if value.nil? @handle_exceptions else @handle_exceptions = value end end
Check if the given exception is handled.
@param exception [Exception] an exception
@since 0.3.2 @api private
@see Hanami::Controller::Configuration#handle_exception
# File lib/hanami/controller/configuration.rb, line 214 def handled_exception?(exception) handled_exceptions && !exception_handler_for(exception).nil? end
Load the framework
@since 0.3.0 @api private
# File lib/hanami/controller/configuration.rb, line 738 def load! freeze end
Returns a mime type for the given format
@param format [#to_sym] a format
@return [String,nil] the corresponding mime type, if present
@since 0.2.0 @api private
# File lib/hanami/controller/configuration.rb, line 650 def mime_type_for(format) @formats.key(format) end
Return the configured format's MIME types
@since 0.8.0 @api private
@see Hanami::Controller::Configuration#format
@see Hanami::Action::Mime::MIME_TYPES
# 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
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.
@param blk [Proc] the code block
@return [void]
@raise [ArgumentError] if called without passing a block
@since 0.3.0
@see Hanami::Controller.configure
@see Hanami::Controller.duplicate
@example 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
# 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
# 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
Reset all the values to the defaults
@since 0.2.0 @api private
# 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 the MIME types set only to the given set
@param mime_types
[Array] the set of MIME types
@since 1.0.0 @api private
@see Hanami::Action::Mime::ClassMethods#accept
# File lib/hanami/controller/configuration.rb, line 446 def restrict_mime_types!(mime_types) @mime_types = self.mime_types & mime_types end
Protected Instance Methods
@since 0.5.0 @api private
# File lib/hanami/controller/configuration.rb, line 745 def _sort_handled_exceptions! @handled_exceptions = Hash[ @handled_exceptions.sort{|(ex1,_),(ex2,_)| ex1.ancestors.include?(ex2) ? -1 : 1 } ] end