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