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
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
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
# 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
# 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
# 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
# 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 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
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
# 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