Module: Lolita::Controllers::ComponentHelpers

Defined in:
lib/lolita/controllers/component_helpers.rb

Overview

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.

Instance Method Summary collapse

Instance Method Details

#component_helper_path(component_name) ⇒ Object

Find path for given component.

component_helper_path :"lolita/list" #=> [path_to_lolita]/app/helpers/components/lolita/list_component.rb


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# 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_localsObject

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



151
152
153
# File 'lib/lolita/controllers/component_helpers.rb', line 151

def component_locals
  @component_locals[@current_component_name]
end

#get_render_options(*args) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
# 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) ⇒ Object



122
123
124
125
126
127
128
# 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 = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
# 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) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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) ⇒ Object

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"


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 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) ⇒ Object

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

Example

will_use_component :"lolita/configuration/list"


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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) ⇒ Object



88
89
90
91
92
93
94
# 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