pakyow-presenter/lib/presenter/presenter.rb in pakyow-presenter-0.7.2 vs pakyow-presenter/lib/presenter/presenter.rb in pakyow-presenter-0.8rc1

- old
+ new

@@ -1,34 +1,79 @@ module Pakyow module Presenter class Presenter < PresenterBase - attr_accessor :current_context + class << self + attr_accessor :proc + end + attr_accessor :current_context, :parser_store, :view_store + def initialize - reset_state() + reset_state + reset_bindings end + def scope(name, set = :default, &block) + @bindings[set] ||= {} + + bs = Bindings.for(block) + @bindings[set][name] = bs + bs + end + + def bindings(scope) + #TODO think about merging on launch instead + @bindings.inject(Bindings.new) { |bs, b| bs.merge(b[1][scope]) } + end + + def reset_bindings(set = :default) + @bindings ||= {} + @bindings[set] = {} + end + + def current_view_lookup_store + @view_stores[self.view_store] + end + # # Methods that are called by core. This is the interface that core expects a Presenter to have # def load load_views + + self.reset_bindings + self.instance_eval(&Presenter.proc) if Presenter.proc end def prepare_for_request(request) reset_state() @request = request + + if @request && @request.route_path && !@request.route_path.is_a?(Regexp) && @request.route_path.index(':') + @view_path = StringUtils.remove_route_vars(@request.route_path) + else + @view_path = @request && @request.working_path + end + @root_path = self.current_view_lookup_store.root_path(@view_path) end + def reset + @request = nil + reset_state + end + def presented? + #TODO the right thing to do? + self.ensure_root_view_built + @presented end def content return unless view - request_container = @request.params[:_container] + request_container = @request.params[:_container] if @request return view.to_html(request_container) if request_container view.to_html(@container_name) end # @@ -38,11 +83,11 @@ # Call these directly # def view_for_path(abstract_path, is_root_view=false, klass=View) - real_path = @view_lookup_store.real_path(abstract_path) + real_path = self.current_view_lookup_store.real_path(abstract_path) klass.new(real_path, is_root_view) end def view_for_class(view_class, path_override=nil) return view_for_path(path_override, view_class.default_is_root_view, view_class) if path_override @@ -52,80 +97,54 @@ def view ensure_root_view_built @root_view end - def set_view(view) - @root_view = View.new(view) + def view=(v) + # TODO: Why is it important to dup here? + @root_view = View.new(v) @root_view_is_built = true @presented = true + + # reset paths @view_path = nil @root_path = nil end - def limit_to_container(id) - @container_name = id + def root + @is_compiled = false + @root ||= View.root_at_path(@root_path) end - def use_view_path(path) - @view_path = path - @root_view_is_built = false + def root=(v) + @is_compiled = false + @root = v end + def limit_to_container(id) + @container_name = id + end + def view_path @view_path end - def use_root_view_file(abstract_view_file) - real_path = @view_lookup_store.real_path(abstract_view_file) - @root_path = real_path - @root_view_is_built = false + def view_path=(path) + @is_compiled = false + @view_path = path end - def use_root_view_at_view_path(abstract_view_dir) - @root_path = @view_lookup_store.view_info(abstract_view_dir)[:root_view] - @root_view_is_built = false + def root_path + @root_path end - - # This is for creating views from within a controller using the route based lookup mechanism - def view_for_view_path(v_p, name, deep = false) - v = nil - view_info = @view_lookup_store.view_info(v_p) - vpath = view_info[:views][name] if view_info - v = View.new(vpath) if vpath - if v && deep - populate_view(v, view_info[:views]) - end - v - end - # This is also for creating views from within a controller using the route based lookup mechanism. - # This method takes either a dir or file path and builds either a root_view or view, respectively. - def view_for_full_view_path(f_v_p, deep = false) - v = nil - real_path_info = @view_lookup_store.real_path_info(f_v_p) - if real_path_info - if real_path_info[:file_or_dir] == :file - v = View.new(real_path_info[:real_path]) - elsif real_path_info[:file_or_dir] == :dir - root_view = @view_lookup_store.view_info(f_v_p)[:root_view] - v = View.new(root_view) - if v && deep - populate_view(v, @view_lookup_store.view_info(f_v_p)[:views]) - end - end - end - v + def root_path=(abstract_path) + @is_compiled = false + @root = nil + @root_path = abstract_path end - def populate_view_for_view_path(view, v_p) - return view unless view_info = @view_lookup_store.view_info(v_p) - views = view_info[:views] - populate_view(view, views) - view - end - # Call as part of View DSL for DOM manipulation # def with_container(container, &block) v = self.view.find("##{container}").first @@ -143,10 +162,11 @@ # protected # def reset_state + @view_store = :default @presented = false @root_path = nil @root_view_is_built = false @root_view = nil @view_path = nil @@ -154,22 +174,13 @@ end def build_root_view @root_view_is_built = true - if @view_path - v_p = @view_path - elsif @request && @request.restful - v_p = restful_view_path(@request.restful) - elsif @request && @request.route_spec && !@request.route_spec.is_a?(Regexp) && @request.route_spec.index(':') - v_p = StringUtils.remove_route_vars(@request.route_spec) - else - v_p = @request && @request.working_path - end - return unless v_p + return unless v_p = @view_path - return unless view_info = @view_lookup_store.view_info(v_p) + return unless view_info = self.current_view_lookup_store.view_info(v_p) @root_path ||= view_info[:root_view] if Configuration::Base.presenter.view_caching r_v = @populated_root_view_cache.get([v_p, @root_path]) { populate_view(LazyView.new(@root_path, true), view_info[:views]) @@ -189,13 +200,17 @@ StringUtils.remove_route_vars(@request.route_spec) end end def load_views - @view_lookup_store = ViewLookupStore.new("#{Configuration::Presenter.view_dir}") + @view_stores = {} + Configuration::Presenter.view_stores.each_pair {|name, path| + @view_stores[name] = ViewLookupStore.new(path) + } + if Configuration::Base.presenter.view_caching then - @populated_root_view_cache = build_root_view_cache(@view_lookup_store.view_info) + @populated_root_view_cache = build_root_view_cache(self.current_view_lookup_store.view_info) end end def build_root_view_cache(view_info) cache = Pakyow::Cache.new @@ -209,20 +224,31 @@ end # populates the top_view using view_store data by recursively building # and substituting in child views named in the structure def populate_view(top_view, views) - containers = top_view.elements_with_ids - containers.each {|e| - name = e.attr("id") - path = views[name] - if path - v = populate_view(View.new(path), views) - top_view.reset_container(name) # TODO revisit how this is implemented; assumes all LazyViews are root views - top_view.add_content_to_container(v, name) - end + top_view.containers.each {|e| + next unless path = views[e[:name]] + + v = populate_view(View.new(path), views) + self.reset_container(e[:doc]) + self.add_content_to_container(v, e[:doc]) } top_view + end + + def parser(format, &block) + @parser_store ||= {} + @parser_store[format.to_sym] = block + end + + def add_content_to_container(content, container) + content = content.doc unless content.class == String || content.class == Nokogiri::HTML::DocumentFragment || content.class == Nokogiri::XML::Element + container.add_child(content) + end + + def reset_container(container) + container.inner_html = '' end end end end