Class: Skyline::Rendering::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/skyline/rendering/renderer.rb

Overview

The skyline renderer renders all Articles, Sections and basically anything that’s renderable or previewable in Skyline.

Direct Known Subclasses

Skyline::Renderer

Defined Under Namespace

Modules: Helpers

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Renderer

Creates a new renderer instance.

Parameters:

  • options (Hash) (defaults to: {})

    Options

Options Hash (options):

  • :assigns (Hash) — default: {}

    Assigns to pass to the template, all assigns are accessible by their instance variable. ‘:test` becomes @test in the template.

  • :controller (Controller) — default: nil

    The controller that is serving the current request.

  • :paths (Array<String,Pathname>) — default: ["app/templates", Skyline.root + "app/templates/skyline"]

    Paths that will be searched for templates.

  • :site (Site)

    The currently active site object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/skyline/rendering/renderer.rb', line 80

def initialize(options = {})
  options.reverse_merge!(:assigns => {}, 
                         :controller => nil, 
                         :paths => ["app/templates", Skyline.root + "app/templates/skyline"],
                         :site => nil)

  @assigns = options[:assigns].update(:_controller => options[:controller], 
                                      :_site => options[:site])

  @template_paths = options[:paths].collect{|p| (Rails.root + p).to_s if File.exist?(Rails.root + p)}.compact
  @template_assigns = {}
end

Instance Attribute Details

#_configObject

Returns the value of attribute _config.



5
6
7
# File 'lib/skyline/rendering/renderer.rb', line 5

def _config
  @_config
end

#assignsObject (readonly)

Returns the value of attribute assigns.



4
5
6
# File 'lib/skyline/rendering/renderer.rb', line 4

def assigns
  @assigns
end

#template_pathsObject (readonly)

Returns the value of attribute template_paths.



4
5
6
# File 'lib/skyline/rendering/renderer.rb', line 4

def template_paths
  @template_paths
end

Class Method Details

.helper(module_name) ⇒ Object

Add a helper to the standard renderer

Parameters:

  • module_name (~to_s, Module)

    ] Module/module name to include in the helper for renderer.



55
56
57
# File 'lib/skyline/rendering/renderer.rb', line 55

def helper(module_name)
  Helpers.helper(module_name)
end

.register_renderables(type, renderables) ⇒ Object

Add your own renderables

Parameters:

  • type (Symbol)

    The type (for instance ‘:sections` or `:articles`) to register your renderables under

  • renderables (Array<String,Symbol,Class>)

    Your own renderables



41
42
43
# File 'lib/skyline/rendering/renderer.rb', line 41

def register_renderables(type, renderables)
  @@renderables[type] = renderables
end

.renderable_typesArray<Symbol>

All availables renderable types

Returns:

  • (Array<Symbol>)

    All available types



48
49
50
# File 'lib/skyline/rendering/renderer.rb', line 48

def renderable_types
  @@renderables.keys
end

.renderables(type, sub = :all) ⇒ Array<Class>

The list of renderable classes by type

Parameters:

  • type (Symbol)

    The type to get the renderable classes for

  • sub (Symbol, Class) (defaults to: :all)

    The sub class ie. :news_item or Skyline::Page when @@renderables is an Hash]

Returns:

  • (Array<Class>)

    Array of renderable classes



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/skyline/rendering/renderer.rb', line 20

def renderables(type, sub = :all)
  @@renderables ||= {}
  
  if @@renderables[type].kind_of?(Hash)
    @@renderables[type] ||= {}
    if sub == :all
      @@renderables[type][:all] = renderables_to_class(type, @@renderables[type].values.flatten.uniq)
    else
      sub = sub.name.downcase.underscore.to_sym if sub.kind_of?(Class)
      classes = @@renderables[type][sub] || @@renderables[type][:default]
      @@renderables[type][sub] = renderables_to_class(type, classes)
    end
  else
    @@renderables[type] = renderables_to_class(type, @@renderables[type])
  end
end

Instance Method Details

#config(options = {}) ⇒ Hash

TODO:

Check the exact syntax of options and what happens with the parameters of the :proxy. blocks.

The current rendering configuration

Parameters:

  • options (Hash) (defaults to: {})

    Options

Options Hash (options):

  • :additional_config (Hash) — default: {}

    An additional config to use just for this instance of the renderer. Setting :additional_config updates the config!

Returns:

  • (Hash)

    the current config



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/skyline/rendering/renderer.rb', line 253

def config(options = {})
  return self._config if self._config && Rails.env == "production"
  options.reverse_merge!(:additional_config => {})
  
  delegate_proc = Proc.new do |object| 
    {
      :class_name => "Skyline::ArticleVersion", 
      :path => object.article.class.name.sub(/^Skyline::/, '').underscore,
      :templates => self._config[object.article.class.name].andand[:templates] || []
    }
  end
  
  config = {"Skyline::Variant"      => delegate_proc,
            "Skyline::Publication"  => delegate_proc,
            "Skyline::Section"      => {:proxy => Proc.new{|renderer, section, options| renderer.render(section.sectionable, options)}},
           }.merge(options[:additional_config])
  
  self.class.renderable_types.each do |type|
    self.class.renderables(type).each do |renderable|
      name = renderable.name
      config[name] = {:class_name => name }
    end
  end

  config.each do |object, object_config|
    if object_config.kind_of?(Hash) && !object_config[:proxy]
      object_config[:path] ||= object_config[:class_name].sub(/^Skyline::/, '').underscore
      object_config[:templates] = templates_in_path(object_config[:path])
      object_config[:templates].sort!
    end
  end
  
  self._config = config
end

#file_path(object, filename) ⇒ Object



303
304
305
306
307
308
309
# File 'lib/skyline/rendering/renderer.rb', line 303

def file_path(object, filename)
  paths = object_template_paths(object)
  paths.each do |path|
    return File.join(path, filename) if File.exists?(File.join(path, filename))
  end
  nil
end

#objectrenderable

The current object that’s being rendered

Returns:

  • (renderable)

    The renderable object.



158
159
160
# File 'lib/skyline/rendering/renderer.rb', line 158

def object
  @_local_object
end

#object_template_paths(object) ⇒ Object



288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/skyline/rendering/renderer.rb', line 288

def object_template_paths(object)
  object_config = self.object_config(object)
  template = self.object_template(object)
  
  template_path = object_config[:path]
  path = "#{template_path}/#{template}"
  default_path = "#{template_path}/default"

  load_paths = []
  load_paths += @template_paths.collect{|p| File.join(p, path)}
  load_paths += @template_paths.collect{|p| File.join(p, template_path)}
  load_paths += @template_paths.collect{|p| File.join(p, default_path)} unless template == "default"
  load_paths
end

#peek(n = 1) ⇒ Array<renderable>

Peek looks forward N position in the current renderable collection. Peek does not modify the renderable collection.

Can only be used within a render_collection call.

Parameters:

  • n (Integer) (defaults to: 1)

    Number of items to look ahead

Returns:

  • (Array<renderable>)

    N renderable items (or less if the collection end has been reached)



170
171
172
173
# File 'lib/skyline/rendering/renderer.rb', line 170

def peek(n = 1)
  return [] if @_current_collection.blank?
  @_current_collection[@_current_collection_index + @_collection_skip + 1, n]
end

#peek_until {|i| ... } ⇒ Array<renderable>

Peek until the conditions in the passed block return true. Peek_until does not modify the renderable collection.

Can only be used within a render_collection call.

Yields:

  • (i)

    A block that must evaluate to true/false

Yield Parameters:

  • i (renderable)

    The current renderable item

Yield Returns:

  • (true, false)

    If true the collection from the entry point up until the moment the block returns true is returned as an array. If false the loop continues until the end of the collection is reached or the conditions in the block are met.

Returns:

  • (Array<renderable>)

    Renderable items.



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/skyline/rendering/renderer.rb', line 187

def peek_until(&block)
  return [] if @_current_collection.blank?
  peeking = []
  items = @_current_collection[@_current_collection_index + @_collection_skip + 1 .. -1]
  return [] unless items
  items.each do |i|
    return peeking if yield i
    peeking << i
  end
  peeking
end

#render(object, options = {}) ⇒ String

Render one renderable object

Parameters:

  • object (renderable)

    A renderable object

  • options (Hash) (defaults to: {})

    Options

Options Hash (options):

  • :locals (Hash) — default: {}

    Locals to make available to the template

  • :assigns (Hash) — default: {}

    Assigns merged with the global assigns of this renderer

Returns:

  • (String)

    The rendered template



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/skyline/rendering/renderer.rb', line 102

def render(object, options = {})
  options.reverse_merge!(:locals => {}, :assigns => {})
  
  object_config = self.object_config(object)

  if object_config[:proxy]
    object_config[:proxy].call(self, object, options)
  else
    template = self.object_template(object)
    load_paths = self.object_template_paths(object)

    Rails.logger.debug "Rendering index template from paths: #{load_paths.join(', ')} (object.template = #{template})"

    av = ActionView::Base.new(load_paths.map(&:to_s))

    self.assigns.merge(options[:assigns]).each do |k, v|
      av.assigns[k.to_sym] = v
    end

    av.assigns[:_template_assigns] = @template_assigns
    av.assigns[:_renderer] = self
    av.assigns[:_local_object_name] = object_config[:class_name].demodulize.underscore.to_sym
    av.assigns[:_local_object] = object
    @_local_object = object   # for object function
    
    av.extend Skyline::Rendering::Helpers::RendererHelper
    av.extend Helpers
    
    av.render(:file => "index", :locals => options[:locals])
  end
end

#render_collection(objects, options = {}, &block) ⇒ String

Render a collection of objects (array), this gives support for peek() and skip!() in the templates. A template can decide too look n items forward and skip n items because the template itself rendered the next n items.

By default each object is rendered with the default rendering options. If you pass a block, this block is called for every item in the collection. The return value of the block will be added to the output. No automatic rendering will be done.

All assigns and template_assigns will be available to all (cloned) renderers. (This is because clone only makes a shallow clone, attributes (like assigns) which are Hashes aren’t copied: a clone uses the same memory address of the attribute.)

Parameters:

  • objects (Array<renderable>)

    An array of renderable objects.

  • options (Hash) (defaults to: {})

    Options will be passed to each consequent #render call.

Returns:

  • (String)

    The rendererd templates



151
152
153
# File 'lib/skyline/rendering/renderer.rb', line 151

def render_collection(objects, options = {}, &block)
  self.clone.send(:_render_collection, objects, options, &block)
end

#render_until(&block) ⇒ Object

Render_until does the same as peek_until but it also renders the objects and advances the collection pointer until the conditions in the block are met.

See Also:



203
204
205
# File 'lib/skyline/rendering/renderer.rb', line 203

def render_until(&block)
  peek_until(&block).collect{|i| self.skip!; self.render(i)}.join
end

#skip!(n = 1) ⇒ Object

Advances the collection pointer by one

Can only be used within a render_collection call.

Parameters:

  • n (Integer) (defaults to: 1)

    Number of items to skip



212
213
214
215
# File 'lib/skyline/rendering/renderer.rb', line 212

def skip!(n = 1)
  return 0 if @_current_collection.blank?    
  @_collection_skip += n
end

#skip_until!(&block) ⇒ Object

Skip_until! works like peek_until except it skips until the conditions in the passed block are met.

See Also:



221
222
223
224
225
226
227
228
229
# File 'lib/skyline/rendering/renderer.rb', line 221

def skip_until!(&block)
  return [] if @_current_collection.blank?
  items = @_current_collection[@_current_collection_index + @_collection_skip + 1 .. -1]
  return [] unless items
  item.each do |i|
    return if yield i
    skip!    
  end
end

#templates_for(klass_or_obj) ⇒ Array

Returns a list of templates for a certain object or class. Raises an exception if the class can’t be found in the config.

Parameters:

  • klass_or_obj (Class, Object)

    The instance / class to get the templates for.

Returns:

  • (Array)

    An array with template names



237
238
239
240
# File 'lib/skyline/rendering/renderer.rb', line 237

def templates_for(klass_or_obj)
  klass = klass_or_obj.kind_of?(Class) ? klass_or_obj : klass_or_obj.class
  self.config[klass.name].andand[:templates] || []
end