lib/innate/node.rb in manveru-innate-2009.04 vs lib/innate/node.rb in manveru-innate-2009.04.01
- old
+ new
@@ -26,12 +26,11 @@
# {Action}. There might be future demand for this, but for now you can simply
# use `def index(*args); end` to make a catch-all action.
module Node
include Traited
- attr_reader :method_arities, :layout_templates, :view_templates
-
+ DEFAULT_HELPERS = %w[aspect cgi flash link partial redirect send_file]
NODE_LIST = Set.new
# These traits are inherited into ancestors, changing a trait in an
# ancestor doesn't affect the higher ones.
#
@@ -55,10 +54,12 @@
trait :skip_node_map => false
# Upon inclusion we make ourselves comfortable.
def self.included(into)
into.__send__(:include, Helper)
+ into.helper(*DEFAULT_HELPERS)
+
into.extend(Trinity, self)
NODE_LIST << into
return if into.provide_set?
@@ -362,18 +363,17 @@
# @see Node::find_provide Node::update_method_arities Node::find_action
# @author manveru
def resolve(path)
name, wish, engine = find_provide(path)
node = (respond_to?(:ancestors) && respond_to?(:new)) ? self : self.class
- action = Action.create(:node => node, :wish => wish, :engine => engine, :path => path)
+ action = Action.create(:node => node, :wish => wish, :engine => engine)
if content_type = node.ancestral_trait["#{wish}_content_type"]
action.options = {:content_type => content_type}
end
node.update_method_arities
- node.update_template_mappings
node.fill_action(action, name)
end
# Resolve possible provides for the given +path+ from {provides}.
#
@@ -535,45 +535,47 @@
end
@method_arities
end
+ attr_reader :method_arities
+
# Try to find the best template for the given basename and wish and respect
# aliased views.
#
- # @param [#to_s] action_name
+ # @param [#to_s] file
# @param [#to_s] wish
#
# @return [String, nil] depending whether a template could be found
#
# @api external
# @see Node#to_template Node#find_aliased_view
# @author manveru
- def find_view(action_name, wish)
- aliased = find_aliased_view(action_name, wish)
+ def find_view(file, wish)
+ aliased = find_aliased_view(file, wish)
return aliased if aliased
- to_view(action_name, wish)
+ to_view(file, wish)
end
# Try to find the best template for the given basename and wish.
#
# This method is mostly here for symetry with {to_layout} and to allow you
# overriding the template lookup easily.
#
- # @param [#to_s] action_name
+ # @param [#to_s] file
# @param [#to_s] wish
#
# @return [String, nil] depending whether a template could be found
#
# @api external
# @see {Node#find_view} {Node#to_template} {Node#root_mappings}
# {Node#view_mappings} {Node#to_template}
# @author manveru
- def to_view(action_name, wish)
- return unless files = view_templates[wish.to_s]
- files[action_name.to_s]
+ def to_view(file, wish)
+ path = [root_mappings].concat(view_mappings) << file
+ to_template(path, wish)
end
# Aliasing one view from another.
# The aliases are inherited, and the optional third +node+ parameter
# indicates the Node to take the view from.
@@ -607,45 +609,42 @@
def alias_view(to, from, node = nil)
trait[:alias_view] || trait(:alias_view => {})
trait[:alias_view][to.to_s] = node ? [from.to_s, node] : from.to_s
end
- # Resolve one level of aliasing for the given +action_name+ and +wish+.
+ # Resolve one level of aliasing for the given +file+ and +wish+.
#
- # @param [String] action_name
+ # @param [String] file
# @param [String] wish
#
# @return [nil, String] the absolute path to the aliased template or nil
#
# @api internal
# @see Node::alias_view Node::find_view
# @author manveru
- def find_aliased_view(action_name, wish)
- aliased_name, aliased_node = ancestral_trait[:alias_view][action_name]
- return unless aliased_name
-
+ def find_aliased_view(file, wish)
+ aliased_file, aliased_node = ancestral_trait[:alias_view][file]
aliased_node ||= self
- aliased_node.update_view_mappings
- aliased_node.find_view(aliased_name, wish)
+ aliased_node.find_view(aliased_file, wish) if aliased_file
end
- # Find the best matching action_name for the layout, if any.
+ # Find the best matching file for the layout, if any.
#
# This is mostly an abstract method that you might find handy if you want
# to do vastly different layout lookup.
#
- # @param [String] action_name
+ # @param [String] file
# @param [String] wish
#
# @return [nil, String] the absolute path to the template or nil
#
# @api external
# @see {Node#to_template} {Node#root_mappings} {Node#layout_mappings}
# @author manveru
- def to_layout(action_name, wish)
- return unless files = layout_templates[wish.to_s]
- files[action_name.to_s]
+ def to_layout(file, wish)
+ path = [root_mappings].concat(layout_mappings) << file
+ to_template(path, wish)
end
# Define a layout to use on this Node.
#
# A Node can only have one layout, although the template being chosen can
@@ -726,15 +725,15 @@
atoms = path.split('/')
atoms.delete('')
result = nil
atoms.size.downto(0) do |len|
- action_name = atoms[0...len].join('__')
+ action = atoms[0...len].join('__')
params = atoms[len..-1]
- action_name = 'index' if action_name.empty? and params != ['index']
+ action = 'index' if action.empty? and params != ['index']
- return result if result = yield(action_name, params)
+ return result if result = yield(action, params)
end
return nil
end
@@ -780,63 +779,37 @@
# @api external
# @see Node#find_view Node#to_layout Node#find_aliased_view
# Node#path_glob Node#ext_glob
# @author manveru
def to_template(path, wish)
- to_view(path, wish) || to_layout(path, wish)
- end
+ return unless exts = ext_glob(wish)
+ glob = "#{path_glob(*path)}.#{exts}"
+ found = Dir[glob].uniq
- def update_template_mappings
- update_view_mappings
- update_layout_mappings
- end
+ count = found.size
+ Log.warn("%d views found for %p" % [count, glob]) if count > 1
- def update_view_mappings
- paths = possible_paths_for(view_mappings)
- @view_templates = update_mapping_shared(paths)
+ found.first
end
- def update_layout_mappings
- paths = possible_paths_for(layout_mappings)
- @layout_templates = update_mapping_shared(paths)
+ # Produce a glob that can be processed by Dir::[] matching the possible
+ # paths to the given +elements+.
+ #
+ # The +elements+ are an Array that may be nested one level, take care to
+ # splat if you try to pass an existing Array.
+ #
+ # @return [String] glob matching possible paths to the given +elements+
+ #
+ # @api internal
+ # @see Node#to_template
+ # @author manveru
+ def path_glob(*elements)
+ File.join(elements.map{|element|
+ "{%s}" % [*element].map{|e| e.to_s.gsub('__', '/') }.join(',')
+ }).gsub(/\/\{\/?\}\//, '/')
end
- def update_mapping_shared(paths)
- mapping = {}
-
- provides.each do |wish_key, engine|
- wish = wish_key[/(.*)_handler/, 1]
- ext_glob = ext_glob(wish)
-
- paths.reverse_each do |path|
- ::Dir.glob(::File.join(path, "/**/*.#{ext_glob}")) do |file|
- case file.sub(path, '').gsub('/', '__')
- when /^(.*)\.(.*)\.(.*)$/
- action_name, wish_ext, engine_ext = $1, $2, $3
- when /^(.*)\.(.*)$/
- action_name, wish_ext, engine_ext = $1, wish, $2
- end
-
- mapping[wish_ext] ||= {}
- mapping[wish_ext][action_name] = file
- end
- end
- end
-
- return mapping
- end
-
- def possible_paths_for(mappings)
- root_mappings.map{|root_mapping|
- mappings.first.map{|outer_mapping|
- mappings.last.map{|inner_mapping|
- File.join(root_mapping, outer_mapping, inner_mapping, '/')
- }
- }
- }.flatten
- end
-
# Produce a glob that can be processed by Dir::[] matching the extensions
# associated with the given +wish+.
#
# @param [#to_s] wish the extension (no leading '.')
#
@@ -867,11 +840,11 @@
# @return [Array] list of root directories
#
# @api external
# @author manveru
def root_mappings
- [*options.roots].flatten
+ [*options.roots].dup
end
# Set the paths for lookup below the Innate.options.views paths.
#
# @param [String, Array<String>] locations
@@ -898,11 +871,11 @@
# @author manveru
def view_mappings
paths = [*ancestral_trait[:views]]
paths = [mapping] if paths.empty?
- [[*options.views].flatten, [*paths].flatten]
+ [*options.views] + paths
end
# Set the paths for lookup below the Innate.options.layouts paths.
#
# @param [String, Array<String>] locations
@@ -929,10 +902,10 @@
# @author manveru
def layout_mappings
paths = [*ancestral_trait[:layouts]]
paths = [mapping] if paths.empty?
- [[*options.layouts].flatten, [*paths].flatten]
+ [*options.layouts] + paths
end
def options
Innate.options
end