lib/lotus/configuration.rb in lotusrb-0.1.0 vs lib/lotus/configuration.rb in lotusrb-0.2.0
- old
+ new
@@ -1,36 +1,58 @@
require 'lotus/utils/kernel'
+require 'lotus/environment'
+require 'lotus/config/framework_configuration'
require 'lotus/config/load_paths'
require 'lotus/config/assets'
require 'lotus/config/routes'
require 'lotus/config/mapping'
+require 'lotus/config/sessions'
+require 'lotus/config/configure'
module Lotus
# Configuration for a Lotus application
#
# @since 0.1.0
class Configuration
+ # @since 0.2.0
+ # @api private
+ #
+ # @see Lotus::Configuration#ssl?
+ SSL_SCHEME = 'https'.freeze
+
# Initialize a new configuration instance
#
# @return [Lotus::Configuration]
#
# @since 0.1.0
# @api private
def initialize
@blk = Proc.new{}
+ @env = Environment.new
+ @configurations = Hash.new { |k, v| k[v] = [] }
end
- # Set a block yield when the configuration will be loaded
+ # Set a block yield when the configuration will be loaded or
+ # set a path for the specific environment.
#
+ # @param environment [Symbol,nil] the configuration environment name
+ # @param environment [String,nil] the configuration path of a specific environment
# @param blk [Proc] the configuration block
#
# @return [self]
#
# @since 0.1.0
# @api private
- def configure(&blk)
- @blk = blk if block_given?
+ def configure(environment = nil, path = nil, &blk)
+ if environment && path
+ @configurations[environment.to_s] << Config::Configure.new(root, path, &blk)
+ elsif environment
+ @configurations[environment.to_s] << blk
+ else
+ @blk = blk
+ end
+
self
end
# Load the configuration
#
@@ -40,11 +62,12 @@
#
# @since 0.1.0
# @api private
def load!(namespace = nil)
@namespace = namespace
- instance_eval(&@blk)
+ evaluate_configurations!
+
self
end
# The root of the application
#
@@ -296,33 +319,24 @@
else
root.join @templates.to_s
end
end
- # Assets root.
- # The application will serve the static assets under this directory.
+ # The application will serve the static assets under these directories.
#
# By default it's equal to the `public/` directory under the application
# `root`.
#
- # Otherwise, you can specify a different relative path under `root`.
+ # Otherwise, you can add differents relatives paths under `root`.
#
- # 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 assets(value)
- # Sets the given value
- # @param value [String] the relative path to the assets dir.
- #
# @overload assets
# Gets the value
# @return [Lotus::Config::Assets] assets root
#
# @since 0.1.0
#
- # @see Lotus::Configuration#root
+ # @see Lotus::Configuration#serve_assets
#
# @example Getting the value
# require 'lotus'
#
# module Bookshelf
@@ -331,31 +345,227 @@
# end
#
# Bookshelf::Application.configuration.assets
# # => #<Pathname:/root/path/public>
#
- # @example Setting the value
+ # @example Adding new assets paths
# require 'lotus'
#
# module Bookshelf
# class Application < Lotus::Application
# configure do
- # assets 'assets'
+ # serve_assets true
+ # assets << [
+ # 'vendor/assets'
+ # ]
# end
# end
# end
#
# Bookshelf::Application.configuration.assets
- # # => #<Pathname:/root/path/assets>
- def assets(value = nil)
- if value
- @assets = value
+ # # => #<Lotus::Config::Assets @root=#<Pathname:/root/path/assets>, @paths=["public"]>
+ #
+ def assets
+ @assets ||= Config::Assets.new(root)
+ end
+
+ # Configure serving of assets
+ # Enable static assets (disabled by default).
+ #
+ # 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.
+ #
+ # @since 0.2.0
+ #
+ # @overload serve_assets(value)
+ # Sets the given value.
+ # @param value [TrueClass, FalseClass]
+ #
+ # @overload serve_assets
+ # Gets the value.
+ # @return [TrueClass, FalseClass]
+ #
+ # @see Lotus::Configuration#assets
+ #
+ # @example Getting serve assets configuration by default
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.serve_assets
+ # # => false
+ #
+ # @example Enabling static assets
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # serve_assets true
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.serve_assets
+ # # => true
+ def serve_assets(value = nil)
+ if value.nil?
+ @serve_assets || false
else
- Config::Assets.new(root, @assets)
+ @serve_assets = value
end
end
+ # Configure cookies
+ # Enable cookies (disabled by default).
+ #
+ # 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 cookies(value)
+ # Sets the given value.
+ # @param value [TrueClass, FalseClass]
+ #
+ # @overload cookies
+ # Gets the value.
+ # @return [TrueClass, FalseClass]
+ #
+ # @example Getting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.cookies
+ # # => false
+ #
+ # @example Setting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # cookies true
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.cookies
+ # # => true
+ #
+ # @example Setting a new value after one is set.
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # cookies false
+ # cookies true
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.cookies
+ # # => true
+ #
+ def cookies(value = nil)
+ if value.nil?
+ @cookies || false
+ else
+ @cookies = value
+ end
+ end
+
+ # Configure sessions
+ # Enable sessions (disabled by default).
+ #
+ # 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.
+ #
+ # Given Class as adapter it will be used as sessions middleware.
+ # Given String as adapter it will be resolved as class name and used as
+ # sessions middleware.
+ # Given Symbol as adapter it is assumed it's name of the class under
+ # Rack::Session namespace that will be used as sessions middleware
+ # (e.g. :cookie for Rack::Session::Cookie).
+ #
+ # By default options include domain inferred from host configuration, and
+ # secure flag inferred from scheme configuration.
+ #
+ # @overload sessions(adapter, options)
+ # Sets the given value.
+ # @param adapter [Class, String, Symbol] Rack middleware for sessions management
+ # @param options [Hash] options to pass to sessions middleware
+ #
+ # @overload sessions(false)
+ # Disables sessions
+ #
+ # @overload sessions
+ # Gets the value.
+ # @return [Lotus::Config::Sessions] sessions configuration
+ #
+ # @since 0.2.0
+ #
+ # @see Lotus::Configuration#host
+ # @see Lotus::Configuration#scheme
+ #
+ # @example Getting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.sessions
+ # # => #<Lotus::Config::Sessions:0x00000001ca0c28 @enabled=false>
+ #
+ # @example Setting the value with symbol
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # sessions :cookie, secret: 'abc123'
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.sessions
+ # # => #<Lotus::Config::Sessions:0x00000001589458 @enabled=true, @adapter=:cookie, @options={:domain=>"localhost", :secure=>false}>
+ #
+ # @example Disabling previusly enabled sessions
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # sessions :cookie
+ # sessions false
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.sessions
+ # # => #<Lotus::Config::Sessions:0x00000002460d78 @enabled=false>
+ #
+ def sessions(adapter = nil, options = {})
+ if adapter.nil?
+ @sessions ||= Config::Sessions.new
+ else
+ @sessions = Config::Sessions.new(adapter, options, self)
+ end
+ end
+
# Application load paths
# The application will recursively load all the Ruby files under these paths.
#
# By default it's empty in order to allow developers to decide their own
# app structure.
@@ -471,25 +681,239 @@
else
@routes
end
end
- # since 0.1.0
- # @api private
+ # Body parsing configuration.
+ #
+ # Specify a set of parsers for specific mime types that your application will use. This method will
+ # return the application's parsers which you can use to add existing and new custom parsers for your
+ # application to use.
+ #
+ # By default it's an empty `Array`
+ #
+ # 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 body_parsers(parsers)
+ # Specify a set of body parsers.
+ # @param parsers [Array] the body parser definitions
+ #
+ # @overload body_parsers
+ # Gets the value
+ # @return [Array] the set of parsers
+ #
+ # @since 0.2.0
+ #
+ # @example Getting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.body_parsers
+ # # => []
+ #
+ # @example Setting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # body_parsers :json, XmlParser.new
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.body_parsers
+ # # => [:json, XmlParser.new]
+ #
+ # @example Setting a new value after one is set.
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # body_parsers :json
+ # body_parsers XmlParser.new
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.body_parsers
+ # # => [XmlParser.new]
+ #
+ def body_parsers(*parsers)
+ if parsers.empty?
+ @body_parsers ||= []
+ else
+ @body_parsers = parsers
+ end
+ end
+
+ # Application middleware.
+ #
+ # Specify middleware that your application will use. This method will return
+ # the application's underlying Middleware stack which you can use to add new
+ # middleware for your application to use. By default, the middleware stack
+ # will contain only `Rack::Static` and `Rack::MethodOverride`. However, if
+ # `assets false` was specified # in the configuration block, the default
+ # `Rack::Static` will be removed.
+ #
+ # @since 0.2.0
+ #
+ # @see http://rdoc.info/gems/rack/Rack/Static
+ # @see Lotus::Middleware#use
+ #
+ # @example
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # middleware.use Rack::MethodOverride, nil, 'max-age=0, private, must-revalidate'
+ # middleware.use Rack::ETag
+ # end
+ # end
+ # end
+ def middleware
+ @middleware ||= Lotus::Middleware.new(self)
+ end
+
+ # Application collection mapping.
+ #
+ # Specify a set of collections for the application, by passing a block, or a
+ # relative path where to find the file that describes them.
+ #
+ # By default it's `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 mapping(blk)
+ # Specify a set of mapping in the given block
+ # @param blk [Proc] the mapping definitions
+ #
+ # @overload mapping(path)
+ # Specify a relative path where to find the mapping file
+ # @param path [String] the relative path
+ #
+ # @overload mapping
+ # Gets the value
+ # @return [Lotus::Config::Mapping] the set of mappings
+ #
+ # @since 0.2.0
+ #
+ # @see http://rdoc.info/gems/lotus-model/Lotus/Mapper
+ #
+ # @example Getting the value
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.mapping
+ # # => nil
+ #
+ # @example Setting the value, by passing a block
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # mapping do
+ # collection :users do
+ # entity User
+ #
+ # attribute :id, Integer
+ # attribute :name, String
+ # end
+ # end
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.mapping
+ # # => #<Lotus::Config::Mapping:0x007ff50a991388 @blk=#<Proc:0x007ff123991338@(irb):4>, @path=#<Pathname:.>>
+ #
+ # @example Setting the value, by passing a relative path
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # mapping 'config/mapping'
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.mapping
+ # # => #<Lotus::Config::Routes:0x007ff50a991388 @blk=nil, @path=#<Pathname:config/mapping.rb>>
def mapping(path = nil, &blk)
if path or block_given?
@mapping = Config::Mapping.new(root, path, &blk)
else
@mapping
end
end
+ # Adapter configuration.
+ # The application will instantiate adapter instance based on this configuration.
+ #
+ # The given options must have key pairs :type and :uri
+ # If it isn't, at the runtime the framework will raise a
+ # `ArgumentError`.
+ #
+ # 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 adapter(options)
+ # Sets the given type and uri
+ # @param options [Hash] a set of options for adapter
+ #
+ # @overload adapter
+ # Gets the value
+ # @return [Hash] adapter options
+ #
+ # @since 0.2.0
+ #
+ # @see Lotus::Configuration#adapter
+ # @see http://rdoc.info/gems/lotus-model/Lotus/Model/Configuration:adapter
+ #
+ # @example
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # adapter type: :sql, uri: 'sqlite3://uri'
+ # end
+ # end
+ # end
+ #
+ # Bookshelf::Application.configuration.adapter
+ # # => {type: :sql, uri: 'sqlite3://uri'}
+ def adapter(options = {})
+ if !options.empty?
+ @adapter = options
+ else
+ @adapter
+ 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
+ # alias. If it isn't, at the runtime the framework will raise a
# `Lotus::Controller::UnknownFormatError`.
#
# By default this value is `:html`.
#
# This is part of a DSL, for this reason when this method is called with
@@ -588,10 +1012,21 @@
else
@scheme ||= 'http'
end
end
+ # Check if the application uses SSL
+ #
+ # @return [FalseClass,TrueClass] the result of the check
+ #
+ # @since 0.2.0
+ #
+ # @see Lotus::Configuration#scheme
+ def ssl?
+ scheme == SSL_SCHEME
+ end
+
# The URI host for this application.
# This is used by the router helpers to generate absolute URLs.
#
# By default this value is `"localhost"`.
#
@@ -635,23 +1070,19 @@
# Bookshelf::Application.configuration.host # => "bookshelf.org"
def host(value = nil)
if value
@host = value
else
- @host ||= 'localhost'
+ @host ||= @env.host
end
end
# The URI port for this application.
# This is used by the router helpers to generate absolute URLs.
#
- # By default this value is `80`, if `scheme` is `"http"`, or `443` if
- # `scheme` is `"https"`.
+ # By default this value is `2300`.
#
- # This is optional, you should set this value only if your application
- # listens on a port not listed above.
- #
# 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 port(value)
@@ -673,33 +1104,29 @@
# module Bookshelf
# class Application < Lotus::Application
# end
# end
#
- # Bookshelf::Application.configuration.port # => 80
+ # Bookshelf::Application.configuration.port # => 2300
#
# @example Setting the value
# require 'lotus'
#
# module Bookshelf
# class Application < Lotus::Application
# configure do
- # port 2323
+ # port 8080
# end
# end
# end
#
- # Bookshelf::Application.configuration.port # => 2323
+ # Bookshelf::Application.configuration.port # => 8080
def port(value = nil)
if value
@port = Integer(value)
else
- @port ||
- case scheme
- when 'http' then 80
- when 'https' then 443
- end
+ @port || @env.port
end
end
# Defines a relative pattern to find controllers.
#
@@ -954,8 +1381,239 @@
if value
@view_pattern = value
else
@view_pattern ||= 'Views::%{controller}::%{action}'
end
+ end
+
+ # Decide if 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 http://rdoc.info/gems/lotus-controller/Lotus/Controller/Configuration:handle_exceptions
+ # @see http://httpstatus.es/500
+ #
+ # @example Enabled (default)
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # routes do
+ # get '/error', to: 'error#index'
+ # end
+ # end
+ #
+ # load!
+ # end
+ #
+ # module Controllers::Error
+ # include Bookshelf::Controller
+ #
+ # action 'Index' do
+ # def call(params)
+ # raise ArgumentError
+ # end
+ # end
+ # end
+ # end
+ #
+ # # GET '/error' # => 500 - Internal Server Error
+ #
+ # @example Disabled
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # handle_exceptions false
+ #
+ # routes do
+ # get '/error', to: 'error#index'
+ # end
+ # end
+ #
+ # load!
+ # end
+ #
+ # module Controllers::Error
+ # include Bookshelf::Controller
+ #
+ # action 'Index' do
+ # def call(params)
+ # raise ArgumentError
+ # end
+ # end
+ # end
+ # end
+ #
+ # # GET '/error' # => raises ArgumentError
+ def handle_exceptions(value = nil)
+ if value.nil?
+ @handle_exceptions
+ else
+ @handle_exceptions = value
+ end
+ end
+
+ # It lazily collects all the low level settings for Lotus::Model's
+ # configuration and applies them when the application is loaded.
+ #
+ # NOTE: This forwards all the configurations to Lotus::Model, without
+ # checking them. Before to use this feature, please have a look at the
+ # current Lotus::Model version installed.
+ #
+ # NOTE: This may override some configurations of your application.
+ #
+ # @return [Lotus::Config::FrameworkConfiguration] the configuration
+ #
+ # @since 0.2.0
+ #
+ # @see http://www.rubydoc.info/gems/lotus-model/Lotus/Model/Configuration
+ #
+ # @example Define a setting
+ # require 'lotus'
+ # require 'lotus/model'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # model.adapter type: :memory, uri: 'memory://localhost/database'
+ # end
+ # end
+ # end
+ #
+ # @example Override a setting
+ # require 'lotus'
+ # require 'lotus/model'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # adapter type: :sql, uri: 'postgres://localhost/database'
+ # model.adapter type: :memory, uri: 'memory://localhost/database'
+ # end
+ # end
+ # end
+ #
+ # # The memory adapter will override the SQL one
+ def model
+ @model ||= Config::FrameworkConfiguration.new
+ end
+
+ # It lazily collects all the low level settings for Lotus::Controller's
+ # configuration and applies them when the application is loaded.
+ #
+ # NOTE: This forwards all the configurations to Lotus::Controller, without
+ # checking them. Before to use this feature, please have a look at the
+ # current Lotus::Controller version installed.
+ #
+ # NOTE: This may override some configurations of your application.
+ #
+ # @return [Lotus::Config::FrameworkConfiguration] the configuration
+ #
+ # @since 0.2.0
+ #
+ # @see http://www.rubydoc.info/gems/lotus-controller/Lotus/Controller/Configuration
+ #
+ # @example Define a setting
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # controller.default_format :json
+ # end
+ # end
+ # end
+ #
+ # @example Override a setting
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # handle_exceptions false
+ # controller.handle_exceptions true
+ # end
+ # end
+ # end
+ #
+ # # Exceptions will be handled
+ def controller
+ @controller ||= Config::FrameworkConfiguration.new
+ end
+
+ # It lazily collects all the low level settings for Lotus::View's
+ # configuration and applies them when the application is loaded.
+ #
+ # NOTE: This forwards all the configurations to Lotus::View, without
+ # checking them. Before to use this feature, please have a look at the
+ # current Lotus::View version installed.
+ #
+ # NOTE: This may override some configurations of your application.
+ #
+ # @return [Lotus::Config::FrameworkConfiguration] the configuration
+ #
+ # @since 0.2.0
+ #
+ # @see http://www.rubydoc.info/gems/lotus-view/Lotus/View/Configuration
+ #
+ # @example Define a setting
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # view.layout :application
+ # end
+ # end
+ # end
+ #
+ # @example Override a setting
+ # require 'lotus'
+ #
+ # module Bookshelf
+ # class Application < Lotus::Application
+ # configure do
+ # layout :application
+ # view.layout :backend
+ # end
+ # end
+ # end
+ #
+ # # It will use `:backend` layout
+ def view
+ @view ||= Config::FrameworkConfiguration.new
+ end
+
+ private
+ # @since 0.2.0
+ # @api private
+ def evaluate_configurations!
+ configurations.each { |c| instance_eval(&c) }
+ end
+
+ # @since 0.2.0
+ # @api private
+ def configurations
+ [ @blk ] + @configurations[@env.environment]
end
end
end