module Lolita::Controllers::ComponentHelpers

Helper that add render_component method. That is shortstand for render :partial for lolita partial files. Also it provide view hooks for Lolita. For any component there may be helper module. Modules are include in current view or controller instance when component is rendered. All components ar placed in “app/helpers/components/[your component path]”. Component should have fallowing module structure Components::::[Component name]Component

Components::Lolita::ListComponent

Example

render_component :"lolita/configuration/list", :dispaly
# try to find /helpers/components/lolita/list_component.rb in every directory in $: that
# ends with /helpers
# require this file if found and extend self with Components::Lolita::ListComponent.

Component helpers is loaded in same order as views or controller.

Public Instance Methods

component_helper_path(component_name) click to toggle source

Find path for given component.

component_helper_path :"lolita/list" #=> [path_to_lolita]/app/helpers/components/lolita/list_component.rb
# File lib/lolita/controllers/component_helpers.rb, line 133
def component_helper_path component_name
   @helper_paths||=$:.reject{|p| !p.match(/\/helpers$/) rescue nil}
   get_path=lambda{|paths|
    extra_path=component_name.to_s.split("/")
    component=extra_path.pop
    paths.each do |path|
      new_path=File.join(path,"components",*extra_path,"#{component}_component.rb")
         if File.exist?(new_path)
           return new_path
         end
      end
    nil
  }
  path=get_path.call(@helper_paths)
  path
end
component_locals() click to toggle source

Return locals for component that will be rendered next. Very useful in hook views, where is no locals.

# File lib/lolita/controllers/component_helpers.rb, line 151
def component_locals
  @component_locals[@current_component_name]
end
get_render_options(*args) click to toggle source
# File lib/lolita/controllers/component_helpers.rb, line 45
def get_render_options *args
  options=args.extract_options!
  if args.first.respond_to?(:build)
    name,state,options=args[0].build("",args[1],options)
  elsif args.first.class.ancestors.include?(Lolita::Configuration)
    raise ArgumentError, "Include Lolita::Builder in #{args.first.class}"
  else
    name,state=args
    name = "/#{name}" unless name.to_s.match(/^\//)
  end
  return name,state,options
end
helpers_for_component(component_name) { |slice.join("/")| ... } click to toggle source
# File lib/lolita/controllers/component_helpers.rb, line 122
def helpers_for_component component_name
  names=component_name.to_s.gsub(/^\//,"").split("/")
  start_index=1 # first is lolita
  start_index.upto(names.size) do |index|
    yield names.slice(0..index).join("/")
  end
end
output_component(partial_name,name,options={}) click to toggle source
# File lib/lolita/controllers/component_helpers.rb, line 58
def output_component(partial_name,name,options={})
  output=""
  if options[:format]
    with_format(options[:format]) do
      output << output_with_callbacks(partial_name,name,options[:locals])
    end
  else
    output << output_with_callbacks(partial_name,name,options[:locals])
  end
  output
end
output_with_callbacks(partial_name,name,locals) click to toggle source
# File lib/lolita/controllers/component_helpers.rb, line 70
def output_with_callbacks(partial_name,name,locals)
  @component_locals ||={}
  @component_locals[name] = locals
  output = Lolita::Hooks.component(name).run(:before,:run_scope => self).to_s
  block_output = Lolita::Hooks.component(name).run(:around, :run_scope => self) do
    if Lolita.rails?
      render(:partial => partial_name, :locals => locals)
    else
      haml :"#{partial_name}.html", :locals => locals
    end
  end
  #FIXME does block_output raises error?
  output << block_output.to_s
  output << Lolita::Hooks.component(name).run(:after,:run_scope => self).to_s
  @component_locals[name] = nil
  output
end
render_component(*args) click to toggle source

Render partial template. Accept: name - name for component in '/components' directory,

can be full name too.
Example 'lolita/list'

state - name for partial. Example 'row'. options - any options to pass as :locals to partial,

also available through <code>@opts</code> variable.
Example
render_component "lolita/list", :display
render_component "lolita/list/display"
# File lib/lolita/controllers/component_helpers.rb, line 28
def render_component *args
  @rendering_components ||= []
  name,state,options=get_render_options(*args)
  format=options.delete(:format)
  raise "Can't render component without name!" unless name
  will_use_component name
  component_name=File.join(name.to_s,state ? "#{!Lolita.rails? && "_" || ""}#{state}" : "")
  partial_name=File.join("/components",component_name)

  @rendering_components.push(component_name)
  @current_component_name = component_name
  output = output_component(partial_name,component_name,:format=>format ,:locals=>options)
  @rendering_components.pop
  @current_component_name = @rendering_components.last
  self.respond_to?(:raw) ? raw(output) : output
end
will_use_component(component_name) click to toggle source

Require component helper file and extend current instance with component helper module.

Example

will_use_component :"lolita/configuration/list"
# File lib/lolita/controllers/component_helpers.rb, line 99
def will_use_component component_name
  helpers_for_component(component_name) do |possible_component_name|
    @used_component_helpers||={}
    unless @used_component_helpers.include?(possible_component_name)
      if path=component_helper_path(possible_component_name)
        self.class.class_eval do
          require path
        end
        class_name=possible_component_name.to_s.camelize
        helper_module = "Components::#{class_name}Component".constantize rescue nil
        if helper_module
          self.extend(helper_module)
        end
      end
      @used_component_helpers[possible_component_name] = helper_module
    else
      if helper_module = @used_component_helpers[possible_component_name]
        self.extend(helper_module)
      end
    end
  end
end
with_format(format, &block) click to toggle source
# File lib/lolita/controllers/component_helpers.rb, line 88
def with_format(format, &block)
  old_formats = formats
  self.formats = [format]
  result=block.call
  self.formats = old_formats
  result
end