lib/hanami/controller/configuration.rb in hanami-controller-1.3.3 vs lib/hanami/controller/configuration.rb in hanami-controller-2.0.0.alpha1

- old
+ new

@@ -42,143 +42,41 @@ 'application/octet-stream' => :all, '*/*' => :all, 'text/html' => :html }.freeze - # 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 - 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 - def initialize - reset! + def initialize(&blk) + @handled_exceptions = {} + @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 + instance_eval(&blk) unless blk.nil? + freeze end - # @attr_writer handle_exceptions [TrueClass,FalseClass] Handle exceptions - # with an HTTP status or leave them uncaught - # - # @since 0.2.0 - # - # @return void - # - # @see Hanami::Controller::Configuration#handle_exceptions - attr_writer :handle_exceptions - - # 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 http://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 - def handle_exceptions(value = nil) - if value.nil? - @handle_exceptions - else - @handle_exceptions = value - end - 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' @@ -186,184 +84,12 @@ # Hanami::Controller.configure do # handle_exception ArgumentError => 400 # end def handle_exception(exception) @handled_exceptions.merge!(exception) - _sort_handled_exceptions! 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 - def exception_handler(exception) - exception_handler_for(exception) || DEFAULT_ERROR_CODE - 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 - def handled_exception?(exception) - handled_exceptions && - !exception_handler_for(exception).nil? - 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 - def exception_handler_for(exception) - @handled_exceptions.each do |exception_class, handler| - return handler if exception.kind_of?(exception_class) - end - - nil - end - - # 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 - def action_module(value = nil) - if value.nil? - @action_module - else - @action_module = value - 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 - def prepare(&blk) - if block_given? - @modules.push(blk) - else - raise ArgumentError.new('Please provide a block') - end - 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 # @@ -416,156 +142,77 @@ # action.format # => :custom def format(hash) symbol, mime_type = *Utils::Kernel.Array(hash) @formats[Utils::Kernel.String(mime_type)] = Utils::Kernel.Symbol(symbol) - @mime_types = nil 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 def mime_types - @mime_types ||= begin - ((@formats.keys - DEFAULT_FORMATS.keys) + - Hanami::Action::Mime::MIME_TYPES.values).freeze - end + # FIXME: this isn't efficient. speed it up! + ((@formats.keys - DEFAULT_FORMATS.keys) + + Hanami::Action::Mime::TYPES.values).freeze 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 - def restrict_mime_types!(mime_types) - @mime_types = self.mime_types & mime_types - 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 - def default_request_format(format = nil) - if format - @default_request_format = Utils::Kernel.Symbol(format) - else - @default_request_format - end + # FIXME: new API docs + def default_request_format=(value) + @default_request_format = Utils::Kernel.Symbol(value) unless value.nil? end + attr_reader :default_request_format + # 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 - def default_response_format(format = nil) - if format - @default_response_format = Utils::Kernel.Symbol(format) - else - @default_response_format - end + # FIXME: new API docs + def default_response_format=(value) + @default_response_format = Utils::Kernel.Symbol(value) unless value.nil? end + attr_reader :default_response_format + # 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 - def default_charset(charset = nil) - if charset - @default_charset = charset - else - @default_charset - end - end + # FIXME: new API docs + attr_accessor :default_charset + attr_reader :default_headers + # Set default headers for all responses # # By default this value is an empty hash. # # @since 0.4.0 @@ -576,25 +223,23 @@ # Hanami::Controller.configuration.default_headers # => {} # # @example Setting the value # require 'hanami/controller' # - # Hanami::Controller.configure do - # default_headers({ + # Hanami::Controller::Configuration.new do |config| + # config.default_headers = { # 'X-Frame-Options' => 'DENY' - # }) + # } # end - def default_headers(headers = nil) - if headers - @default_headers.merge!( - headers.reject {|_,v| v.nil? } - ) - else - @default_headers - end + def default_headers=(headers) + @default_headers.merge!( + headers.reject { |_, v| v.nil? } + ) end + attr_reader :cookies + # Set default cookies options for all responses # # By default this value is an empty hash. # # @since 0.4.0 @@ -605,26 +250,22 @@ # Hanami::Controller.configuration.cookies # => {} # # @example Setting the value # require 'hanami/controller' # - # Hanami::Controller.configure do - # cookies({ + # Hanami::Controller::Configuration.new do |config| + # config.cookies = { # domain: 'hanamirb.org', # path: '/controller', # secure: true, # httponly: true - # }) + # } # end - def cookies(options = nil) - if options - @cookies.merge!( - options.reject { |_, v| v.nil? } - ) - else - @cookies - end + def cookies=(options) + @cookies.merge!( + options.reject { |_, v| v.nil? } + ) end # Returns a format for the given mime type # # @param mime_type [#to_s,#to_str] A mime type @@ -653,111 +294,15 @@ # @api private # @since 1.0.0 attr_reader :root_directory - def public_directory(value = nil) - if value.nil? - @public_directory - else - @public_directory = root_directory.join(value).to_s - end + # FIXME: API docs + def public_directory=(value) + @public_directory = root_directory.join(value).to_s 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 - 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 included modules - # - # @return [Array<Proc>] array of included blocks - # - # @since 0.2.0 - # @api private - # - # @see Hanami::Controller::Configuration#prepare - attr_reader :modules - - # Reset all the values to the defaults - # - # @since 0.2.0 - # @api private - 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 - - # 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 - def copy!(base) - modules.each do |mod| - base.class_eval(&mod) - end - end - - # Load the framework - # - # @since 0.3.0 - # @api private - def load! - freeze - end - - protected - # @since 0.5.0 - # @api private - def _sort_handled_exceptions! - @handled_exceptions = Hash[ - @handled_exceptions.sort{|(ex1,_),(ex2,_)| ex1.ancestors.include?(ex2) ? -1 : 1 } - ] - end - - attr_accessor :handled_exceptions - attr_accessor :formats - attr_writer :action_module - attr_writer :modules - attr_writer :default_request_format - attr_writer :default_response_format - attr_writer :default_charset - attr_writer :default_headers - attr_writer :cookies - attr_writer :public_directory + attr_reader :public_directory + attr_reader :handled_exceptions end end end