lib/hanami/view.rb in hanami-view-0.0.0 vs lib/hanami/view.rb in hanami-view-0.6.0
- old
+ new
@@ -1,7 +1,264 @@
-require "hanami/view/version"
+require 'set'
+require 'pathname'
+require 'hanami/utils/class_attribute'
+require 'hanami/view/version'
+require 'hanami/view/configuration'
+require 'hanami/view/inheritable'
+require 'hanami/view/rendering'
+require 'hanami/view/escape'
+require 'hanami/view/dsl'
+require 'hanami/view/errors'
+require 'hanami/layout'
+require 'hanami/presenter'
module Hanami
+ # View
+ #
+ # @since 0.1.0
module View
- # Your code goes here...
+ include Utils::ClassAttribute
+ # Framework configuration
+ #
+ # @since 0.2.0
+ # @api private
+ class_attribute :configuration
+ self.configuration = Configuration.new
+
+ # Configure the framework.
+ # It yields the given block in the context of the configuration
+ #
+ # @param blk [Proc] the configuration block
+ #
+ # @since 0.2.0
+ #
+ # @see Hanami::View::Configuration
+ #
+ # @example
+ # require 'hanami/view'
+ #
+ # Hanami::View.configure do
+ # root '/path/to/root'
+ # end
+ def self.configure(&blk)
+ configuration.instance_eval(&blk)
+ end
+
+ # Duplicate Hanami::View in order to create a new separated instance
+ # of the framework.
+ #
+ # The new instance of the framework will be completely decoupled from the
+ # original. It will inherit the configuration, but all the changes that
+ # happen after the duplication, won't be reflected on the other copies.
+ #
+ # @return [Module] a copy of Hanami::View
+ #
+ # @since 0.2.0
+ # @api private
+ #
+ # @example Basic usage
+ # require 'hanami/view'
+ #
+ # module MyApp
+ # View = Hanami::View.dupe
+ # end
+ #
+ # MyApp::View == Hanami::View # => false
+ #
+ # MyApp::View.configuration ==
+ # Hanami::View.configuration # => false
+ #
+ # @example Inheriting configuration
+ # require 'hanami/view'
+ #
+ # Hanami::View.configure do
+ # root '/path/to/root'
+ # end
+ #
+ # module MyApp
+ # View = Hanami::View.dupe
+ # end
+ #
+ # module MyApi
+ # View = Hanami::View.dupe
+ # View.configure do
+ # root '/another/root'
+ # end
+ # end
+ #
+ # Hanami::View.configuration.root # => #<Pathname:/path/to/root>
+ # MyApp::View.configuration.root # => #<Pathname:/path/to/root>
+ # MyApi::View.configuration.root # => #<Pathname:/another/root>
+ def self.dupe
+ dup.tap do |duplicated|
+ duplicated.configuration = configuration.duplicate
+ end
+ end
+
+ # Duplicate the framework and generate modules for the target application
+ #
+ # @param mod [Module] the Ruby namespace of the application
+ # @param views [String] the optional namespace where the application's
+ # views will live
+ # @param blk [Proc] an optional block to configure the framework
+ #
+ # @return [Module] a copy of Hanami::View
+ #
+ # @since 0.2.0
+ #
+ # @see Hanami::View#dupe
+ # @see Hanami::View::Configuration
+ # @see Hanami::View::Configuration#namespace
+ #
+ # @example Basic usage
+ # require 'hanami/view'
+ #
+ # module MyApp
+ # View = Hanami::View.duplicate(self)
+ # end
+ #
+ # # It will:
+ # #
+ # # 1. Generate MyApp::View
+ # # 2. Generate MyApp::Layout
+ # # 3. Generate MyApp::Presenter
+ # # 4. Generate MyApp::Views
+ # # 5. Configure MyApp::Views as the default namespace for views
+ #
+ # module MyApp::Views::Dashboard
+ # class Index
+ # include MyApp::View
+ # end
+ # end
+ #
+ # @example Compare code
+ # require 'hanami/view'
+ #
+ # module MyApp
+ # View = Hanami::View.duplicate(self) do
+ # # ...
+ # end
+ # end
+ #
+ # # it's equivalent to:
+ #
+ # module MyApp
+ # View = Hanami::View.dupe
+ # Layout = Hanami::Layout.dup
+ #
+ # module Views
+ # end
+ #
+ # View.configure do
+ # namespace 'MyApp::Views'
+ # end
+ #
+ # View.configure do
+ # # ...
+ # end
+ # end
+ #
+ # @example Custom views module
+ # require 'hanami/view
+ #
+ # module MyApp
+ # View = Hanami::View.duplicate(self, 'Vs')
+ # end
+ #
+ # defined?(MyApp::Views) # => nil
+ # defined?(MyApp::Vs) # => "constant"
+ #
+ # # Developers can namespace views under Vs
+ # module MyApp::Vs::Dashboard
+ # # ...
+ # end
+ #
+ # @example Nil views module
+ # require 'hanami/view'
+ #
+ # module MyApp
+ # View = Hanami::View.duplicate(self, nil)
+ # end
+ #
+ # defined?(MyApp::Views) # => nil
+ #
+ # # Developers can namespace views under MyApp
+ # module MyApp
+ # # ...
+ # end
+ #
+ # @example Block usage
+ # require 'hanami/view'
+ #
+ # module MyApp
+ # View = Hanami::View.duplicate(self) do
+ # root '/path/to/root'
+ # end
+ # end
+ #
+ # Hanami::View.configuration.root # => #<Pathname:.>
+ # MyApp::View.configuration.root # => #<Pathname:/path/to/root>
+ def self.duplicate(mod, views = 'Views', &blk)
+ dupe.tap do |duplicated|
+ mod.module_eval %{ module #{ views }; end } if views
+ mod.module_eval %{
+ Layout = Hanami::Layout.dup
+ Presenter = Hanami::Presenter.dup
+ }
+
+ duplicated.configure do
+ namespace [mod, views].compact.join '::'
+ end
+
+ duplicated.configure(&blk) if block_given?
+ end
+ end
+
+ # Override Ruby's hook for modules.
+ # It includes basic Hanami::View modules to the given Class.
+ # It sets a copy of the framework configuration
+ #
+ # @param base [Class] the target view
+ #
+ # @since 0.1.0
+ # @api private
+ #
+ # @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included
+ #
+ # @see Hanami::View::Dsl
+ # @see Hanami::View::Inheritable
+ # @see Hanami::View::Rendering
+ #
+ # @example
+ # require 'hanami/view'
+ #
+ # class IndexView
+ # include Hanami::View
+ # end
+ def self.included(base)
+ conf = self.configuration
+ conf.add_view(base)
+
+ base.class_eval do
+ extend Inheritable
+ extend Dsl
+ extend Rendering
+ extend Escape
+
+ include Utils::ClassAttribute
+ class_attribute :configuration
+
+ self.configuration = conf.duplicate
+ end
+
+ conf.copy!(base)
+ end
+
+ # Load the framework
+ #
+ # @since 0.1.0
+ # @api private
+ def self.load!
+ configuration.load!
+ end
end
end