Class: BuildingBlocks::Base
- Inherits:
-
Object
- Object
- BuildingBlocks::Base
- Defined in:
- lib/building_blocks/base.rb
Instance Attribute Summary collapse
-
#anonymous_block_number ⇒ Object
counter, used to give unnamed blocks a unique name.
-
#block_groups ⇒ Object
A Hash of queued_blocks arrays; a new array is started when method_missing is invoked.
-
#blocks ⇒ Object
Hash of block names to BuildingBlocks::Container objects.
-
#global_options ⇒ Object
These are the options that are passed into the initalize method.
-
#queued_blocks ⇒ Object
Array of BuildingBlocks::Container objects, storing the order of blocks as they were queued.
-
#templates_folder ⇒ Object
The default folder to look in for global partials.
-
#use_partials ⇒ Object
Boolean variable for whether BuildingBlocks should attempt to render blocks as partials if a defined block cannot be found.
-
#use_partials_for_before_and_after_hooks ⇒ Object
Boolean variable for whether BuildingBlocks should attempt to render blocks before and after blocks as partials if no before or after blocks exist.
-
#variable ⇒ Object
The variable to use when rendering the partial for the templating feature (by default, “blocks”).
-
#view ⇒ Object
a pointer to the ActionView that called BuildingBlocks.
Instance Method Summary collapse
-
#after(name, options = {}, &block) ⇒ Object
(also: #append)
Add a block to render after another block.
-
#before(name, options = {}, &block) ⇒ Object
(also: #prepend)
Add a block to render before another block.
-
#define(name, options = {}, &block) ⇒ Object
Define a block, unless a block by the same name is already defined.
-
#defined?(name) ⇒ Boolean
Checks if a particular block has been defined within the current block scope.
- #evaluated_proc(*args) ⇒ Object
- #evaluated_procs(*args) ⇒ Object
-
#queue(*args, &block) ⇒ Object
Queue a block for later rendering, such as within a template.
-
#render(name_or_container, *args, &block) ⇒ Object
(also: #use)
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks.
-
#render_template(partial, &block) ⇒ Object
Render a partial, treating it as a template, and any code in the block argument will impact how the template renders <%= BuildingBlocks::Base.new(self).render_template(“shared/wizard”) do |blocks| %> <% blocks.queue :step1 %> <% blocks.queue :step2 do %> My overridden Step 2 | <% end %> <% blocks.queue :step3 %> <% blocks.queue do %> | Anonymous Step 4 <% end %> <% end %>.
-
#replace(name, options = {}, &block) ⇒ Object
Define a block, replacing an existing block by the same name if it is already defined.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *args, &block) ⇒ Object (protected)
If a method is missing, we’ll assume the user is starting a new block group by that missing method name
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/building_blocks/base.rb', line 301 def method_missing(m, *args, &block) = args. # If the specified block group has already been defined, it is simply returned here for iteration. # It will consist of all the blocks used in this block group that have yet to be rendered, # as the call for their use occurred before the template was rendered (where their definitions likely occurred) return self.block_groups[m] unless self.block_groups[m].nil? # Allows for nested block groups, store the current block positions array and start a new one original_queued_blocks = self.queued_blocks self.queued_blocks = [] self.block_groups[m] = self.queued_blocks # Capture the contents of the block group (this will only capture block definitions and block renders; it will ignore anything else) view.capture(.merge(), &block) if block_given? # restore the original block positions array self.queued_blocks = original_queued_blocks nil end |
Instance Attribute Details
#anonymous_block_number ⇒ Object
counter, used to give unnamed blocks a unique name
17 18 19 |
# File 'lib/building_blocks/base.rb', line 17 def anonymous_block_number @anonymous_block_number end |
#block_groups ⇒ Object
A Hash of queued_blocks arrays; a new array is started when method_missing is invoked
20 21 22 |
# File 'lib/building_blocks/base.rb', line 20 def block_groups @block_groups end |
#blocks ⇒ Object
Hash of block names to BuildingBlocks::Container objects
11 12 13 |
# File 'lib/building_blocks/base.rb', line 11 def blocks @blocks end |
#global_options ⇒ Object
These are the options that are passed into the initalize method
23 24 25 |
# File 'lib/building_blocks/base.rb', line 23 def @global_options end |
#queued_blocks ⇒ Object
Array of BuildingBlocks::Container objects, storing the order of blocks as they were queued
14 15 16 |
# File 'lib/building_blocks/base.rb', line 14 def queued_blocks @queued_blocks end |
#templates_folder ⇒ Object
The default folder to look in for global partials
26 27 28 |
# File 'lib/building_blocks/base.rb', line 26 def templates_folder @templates_folder end |
#use_partials ⇒ Object
Boolean variable for whether BuildingBlocks should attempt to render blocks as partials if a defined block cannot be found
32 33 34 |
# File 'lib/building_blocks/base.rb', line 32 def use_partials @use_partials end |
#use_partials_for_before_and_after_hooks ⇒ Object
Boolean variable for whether BuildingBlocks should attempt to render blocks before and after blocks as partials if no before or after blocks exist
35 36 37 |
# File 'lib/building_blocks/base.rb', line 35 def use_partials_for_before_and_after_hooks @use_partials_for_before_and_after_hooks end |
#variable ⇒ Object
The variable to use when rendering the partial for the templating feature (by default, “blocks”)
29 30 31 |
# File 'lib/building_blocks/base.rb', line 29 def variable @variable end |
#view ⇒ Object
a pointer to the ActionView that called BuildingBlocks
8 9 10 |
# File 'lib/building_blocks/base.rb', line 8 def view @view end |
Instance Method Details
#after(name, options = {}, &block) ⇒ Object Also known as: append
Add a block to render after another block. This after block will be put into an array so that multiple
after blocks may be queued. They will render in the order in which they are declared when the
"blocks#render" method is called. Any options specified to the after block will override any options
specified in the block definition.
<% blocks.define :wizard, :option1 => 1, :option2 => 2 do |options| %>
Step 2 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<% blocks.after :wizard, :option1 => 3 do
Step 3 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<% blocks.after :wizard, :option2 => 4 do
Step 4 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<%= blocks.use :wizard %>
<!-- Will render:
Step 2 (:option1 => 1, :option2 => 2)<br />
Step 3 (:option1 => 3, :option2 => 2)<br />
Step 4 (:option1 => 1, :option2 => 4)<br />
-->
<%= blocks.render :wizard, :step => @step %>
Options:
name
-
The name of the block to render this code after when that block is rendered
options
-
Any options to specify to the after block when it renders. These will override any options specified when the block was defined.
block
-
The block of code to render after another block
281 282 283 284 |
# File 'lib/building_blocks/base.rb', line 281 def after(name, ={}, &block) self.queue_block_container("after_#{name.to_s}", , &block) nil end |
#before(name, options = {}, &block) ⇒ Object Also known as: prepend
Add a block to render before another block. This before block will be put into an array so that multiple
before blocks may be queued. They will render in the order in which they are declared when the
"blocks#render" method is called. Any options specified to the before block will override any options
specified in the block definition.
<% blocks.define :wizard, :option1 => 1, :option2 => 2 do |options| %>
Step 2 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<% blocks.before :wizard, :option1 => 3 do
Step 0 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<% blocks.before :wizard, :option2 => 4 do
Step 1 (:option1 => <%= options[option1] %>, :option2 => <%= options[option2] %>)<br />
<% end %>
<%= blocks.use :wizard %>
<!-- Will render:
Step 0 (:option1 => 3, :option2 => 2)<br />
Step 1 (:option1 => 1, :option2 => 4)<br />
Step 2 (:option1 => 1, :option2 => 2)<br />
-->
<%= blocks.render :wizard, :step => @step %>
Options:
name
-
The name of the block to render this code before when that block is rendered
options
-
Any options to specify to the before block when it renders. These will override any options specified when the block was defined.
block
-
The block of code to render before another block
242 243 244 245 |
# File 'lib/building_blocks/base.rb', line 242 def before(name, ={}, &block) self.queue_block_container("before_#{name.to_s}", , &block) nil end |
#define(name, options = {}, &block) ⇒ Object
Define a block, unless a block by the same name is already defined.
<%= blocks.define :some_block_name, :parameter1 => "1", :parameter2 => "2" do |options| %>
<%= options[:parameter1] %> and <%= options[:parameter2] %>
<% end %>
Options:
name
-
The name of the block being defined (either a string or a symbol)
options
-
The default options for the block definition. Any or all of these options may be overrideen by whomever calls “blocks.render” on this block.
block
-
The block that is to be rendered when “blocks.render” is called for this block.
59 60 61 62 |
# File 'lib/building_blocks/base.rb', line 59 def define(name, ={}, &block) self.define_block_container(name, , &block) nil end |
#defined?(name) ⇒ Boolean
Checks if a particular block has been defined within the current block scope.
<%= blocks.defined? :some_block_name %>
Options:
name
-
The name of the block to check
42 43 44 |
# File 'lib/building_blocks/base.rb', line 42 def defined?(name) !blocks[name.to_sym].nil? end |
#evaluated_proc(*args) ⇒ Object
292 293 294 295 296 |
# File 'lib/building_blocks/base.rb', line 292 def evaluated_proc(*args) return nil unless args.present? v = args.pop v.is_a?(Proc) ? v.call(*args) : v end |
#evaluated_procs(*args) ⇒ Object
287 288 289 290 |
# File 'lib/building_blocks/base.rb', line 287 def evaluated_procs(*args) = args. .inject({}) { |hash, (k, v)| hash[k] = (v.is_a?(Proc) ? v.call(*args) : v); hash} unless .nil? end |
#queue(*args, &block) ⇒ Object
Queue a block for later rendering, such as within a template.
<%= BuildingBlocks::Base.new(self).render_template("shared/wizard") do |blocks| %>
<% blocks.queue :step1 %>
<% blocks.queue :step2 do %>
My overridden Step 2 |
<% end %>
<% blocks.queue :step3 %>
<% blocks.queue do %>
| Anonymous Step 4
<% end %>
<% end %>
<!-- In /app/views/shared/wizard -->
<% blocks.define :step1 do %>
Step 1 |
<% end %>
<% blocks.define :step2 do %>
Step 2 |
<% end %>
<% blocks.define :step3 do %>
Step 3
<% end %>
<% blocks.queued_blocks.each do |block| %>
<%= blocks.render block %>
<% end %>
<!-- Will render: Step 1 | My overridden Step 2 | Step 3 | Anonymous Step 4-->
Options:
- *args
-
The options to pass in when this block is rendered. These will override any options provided to the actual block definition. Any or all of these options may be overriden by whoever calls “blocks.render” on this block. Usually the first of these args will be the name of the block being queued (either a string or a symbol)
block
-
The optional block definition to render when the queued block is rendered
161 162 163 164 |
# File 'lib/building_blocks/base.rb', line 161 def queue(*args, &block) self.queued_blocks << self.define_block_container(*args, &block) nil end |
#render(name_or_container, *args, &block) ⇒ Object Also known as: use
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks. BuildingBlocks will make four different attempts to render block:
1) Look for a block that has been defined inline elsewhere, using the blocks.define method:
<% blocks.define :wizard do |options| %>
Inline Block Step#<%= options[:step] %>.
<% end %>
<%= blocks.render :wizard, :step => @step %>
2) Look for a partial within the current controller's view directory:
<%= blocks.render :wizard, :step => @step %>
<!-- In /app/views/pages/_wizard.html.erb (assuming it is the pages controller running): -->
Controller-specific Block Step# <%= step %>.
3) Look for a partial with the global blocks view directory (by default /app/views/blocks/):
<%= blocks.render :wizard, :step => @step %>
<!-- In /app/views/blocks/_wizard.html.erb: -->
Global Block Step#<%= step %>.
4) Render the default implementation for the block if provided to the blocks.render call:
<%= blocks.render :wizard, :step => @step do |options| do %>
Default Implementation Block Step#<%= options %>.
<% end %>
Options:
name
-
The name of the block to render (either a string or a symbol)
- *args
-
Any arguments to pass to the block to be rendered (and also to be passed to any “before” and “after” blocks).
block
-
The default block to render if no such block block that is to be rendered when “blocks.render” is called for this block.
115 116 117 118 119 120 121 |
# File 'lib/building_blocks/base.rb', line 115 def render(name_or_container, *args, &block) buffer = ActiveSupport::SafeBuffer.new buffer << render_before_blocks(name_or_container, *args) buffer << render_block(name_or_container, *args, &block) buffer << render_after_blocks(name_or_container, *args) buffer end |
#render_template(partial, &block) ⇒ Object
Render a partial, treating it as a template, and any code in the block argument will impact how the template renders
<%= BuildingBlocks::Base.new(self).render_template("shared/wizard") do |blocks| %>
<% blocks.queue :step1 %>
<% blocks.queue :step2 do %>
My overridden Step 2 |
<% end %>
<% blocks.queue :step3 %>
<% blocks.queue do %>
| Anonymous Step 4
<% end %>
<% end %>
<!-- In /app/views/shared/wizard -->
<% blocks.define :step1 do %>
Step 1 |
<% end %>
<% blocks.define :step2 do %>
Step 2 |
<% end %>
<% blocks.define :step3 do %>
Step 3
<% end %>
<% blocks.queued_blocks.each do |block| %>
<%= blocks.render block %>
<% end %>
<!-- Will render: Step 1 | My overridden Step 2 | Step 3 | Anonymous Step 4-->
Options:
partial
-
The partial to render as a template
block
-
An optional block with code that affects how the template renders
201 202 203 204 205 206 207 |
# File 'lib/building_blocks/base.rb', line 201 def render_template(partial, &block) = .clone [self.variable] = self [:captured_block] = view.capture(self, &block) if block_given? view.render partial, end |
#replace(name, options = {}, &block) ⇒ Object
Define a block, replacing an existing block by the same name if it is already defined.
<%= blocks.define :some_block_name, :parameter1 => "1", :parameter2 => "2" do |options| %>
<%= options[:parameter1] %> and <%= options[:parameter2] %>
<% end %>
<%= blocks.replace :some_block_name, :parameter3 => "3", :parameter4 => "4" do |options| %>
<%= options[:parameter3] %> and <%= options[:parameter4] %>
<% end %>
Options:
name
-
The name of the block being defined (either a string or a symbol)
options
-
The default options for the block definition. Any or all of these options may be overrideen by whomever calls “blocks.render” on this block.
block
-
The block that is to be rendered when “blocks.render” is called for this block.
80 81 82 83 84 |
# File 'lib/building_blocks/base.rb', line 80 def replace(name, ={}, &block) blocks[name.to_sym] = nil self.define_block_container(name, , &block) nil end |