Class: Blocks::Base
- Inherits:
-
Object
- Object
- Blocks::Base
- Includes:
- CallWithParams
- Defined in:
- lib/blocks/base.rb
Instance Attribute Summary collapse
-
#anonymous_block_number ⇒ Object
counter, used to give unnamed blocks a unique name.
-
#blocks ⇒ Object
Hash of block names to Blocks::Container objects.
-
#global_options ⇒ Object
These are the options that are passed into the initalize method.
-
#skipped_blocks ⇒ Object
Hash of block names that have been explicitely skipped.
-
#view ⇒ Object
a pointer to the ActionView that called Blocks.
Instance Method Summary collapse
-
#after(name, options = {}, &block) ⇒ Object
(also: #append, #for)
Add a block to render after another block.
-
#around(name, options = {}, &block) ⇒ Object
Add a block to render around another block.
-
#before(name, options = {}, &block) ⇒ Object
(also: #prepend)
Add a block to render before another block.
- #content_tag_with_block(tag, tag_html, *args, &block) ⇒ Object
-
#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.
-
#initialize(view, options = {}) ⇒ Base
constructor
A new instance of Base.
-
#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_with_partials(name_or_container, *args, &block) ⇒ Object
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks.
-
#render_without_partials(name_or_container, *args, &block) ⇒ Object
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks.
-
#replace(name, options = {}, &block) ⇒ Object
Define a block, replacing an existing block by the same name if it is already defined.
-
#skip(name) ⇒ Object
Skip the rendering of a particular block when blocks.render is called for the a particular block name <%= blocks.define :some_block_name do %> My output <% end %>.
Constructor Details
#initialize(view, options = {}) ⇒ Base
Returns a new instance of Base.
424 425 426 427 428 429 430 |
# File 'lib/blocks/base.rb', line 424 def initialize(view, ={}) self.view = view self. = Blocks.config.merge() self.skipped_blocks = HashWithIndifferentAccess.new self.blocks = HashWithIndifferentAccess.new self.anonymous_block_number = 0 end |
Instance Attribute Details
#anonymous_block_number ⇒ Object
counter, used to give unnamed blocks a unique name
14 15 16 |
# File 'lib/blocks/base.rb', line 14 def anonymous_block_number @anonymous_block_number end |
#blocks ⇒ Object
Hash of block names to Blocks::Container objects
11 12 13 |
# File 'lib/blocks/base.rb', line 11 def blocks @blocks end |
#global_options ⇒ Object
These are the options that are passed into the initalize method
17 18 19 |
# File 'lib/blocks/base.rb', line 17 def end |
#skipped_blocks ⇒ Object
Hash of block names that have been explicitely skipped
20 21 22 |
# File 'lib/blocks/base.rb', line 20 def skipped_blocks @skipped_blocks end |
#view ⇒ Object
a pointer to the ActionView that called Blocks
8 9 10 |
# File 'lib/blocks/base.rb', line 8 def view @view end |
Instance Method Details
#after(name, options = {}, &block) ⇒ Object Also known as: append, for
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 specified to the after block will override any
specified in the block definition.
<% blocks.define :wizard, :option1 => 1, :option2 => 2 do || %>
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.render :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
364 365 366 367 |
# File 'lib/blocks/base.rb', line 364 def after(name, ={}, &block) self.add_block_container_to_list("after_#{name.to_s}", , &block) nil end |
#around(name, options = {}, &block) ⇒ Object
Add a block to render around another block. This around block will be put into an array so that multiple
around blocks may be queued. They will render in the order in which they are declared when the
"blocks#render" method is called, with the last declared around block being rendered as the outer-most code, and
the first declared around block rendered as the inner-most code. Any specified to the after block will override any
specified in the block definition. The user of an around block must declare a block with at least one parameter and
should invoke the #call method on that argument.
<% blocks.define :my_block do %>
test
<% end %>
<% blocks.around :my_block do |content_block| %>
<h1>
<%= content_block.call %>
</h1>
<% end %>
<% blocks.around :my_block do |content_block| %>
<span style="color:red">
<%= content_block.call %>
</span>
<% end %>
<%= blocks.render :my_block %>
<!-- Will render:
<h1>
<span style="color:red">
test
</span>
</h1>
Options:
name-
The name of the block to render this code around when that block is rendered
options-
Any options to specify to the around 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
411 412 413 414 |
# File 'lib/blocks/base.rb', line 411 def around(name, ={}, &block) self.add_block_container_to_list("around_#{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 specified to the before block will override any
specified in the block definition.
<% blocks.define :wizard, :option1 => 1, :option2 => 2 do || %>
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.render :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
325 326 327 328 |
# File 'lib/blocks/base.rb', line 325 def before(name, ={}, &block) self.add_block_container_to_list("before_#{name.to_s}", , &block) nil end |
#content_tag_with_block(tag, tag_html, *args, &block) ⇒ Object
416 417 418 419 420 421 422 |
# File 'lib/blocks/base.rb', line 416 def content_tag_with_block(tag, tag_html, *args, &block) if tag view.content_tag(tag, view.capture(&block), call_each_hash_value_with_params(tag_html, *args)) else view.capture(&block) end 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[:parameter1] %> and <%= options[:parameter2] %>
<% end %>
Options:
name-
The name of the block being defined (either a string or a symbol or a Proc)
options-
The default options for the block definition. Any or all of these options may be overridden by whomever calls “blocks.render” on this block. If :collection => some_array, Blocks will assume that the first argument is a Proc and define a block for each object in the collection
block-
The block that is to be rendered when “blocks.render” is called for this block.
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/blocks/base.rb', line 46 def define(name, ={}, &block) collection = .delete(:collection) if collection collection.each do |object| define(call_with_params(name, object, ), , &block) end else self.define_block_container(name, , &block) end 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
27 28 29 |
# File 'lib/blocks/base.rb', line 27 def defined?(name) !blocks[name].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. Additionally, a collection may also be passed in, and Blocks will render an the block, along with corresponding before and after blocks for each element of the collection. Blocks will make either two or four different attempts to render the block, depending on how use_partials is globally set, or an option is passed in to the render call to either use partials or skip partials:
1) Look for a block that has been defined inline elsewhere, using the blocks.define method:
<% blocks.define :wizard do || %>
Inline Block Step#<%= options[:step] %>.
<% end %>
<%= blocks.render :wizard, :step => @step %>
2) [IF use_partials is globally set to true or passed in as a runtime option,
and skip_partials is not passed in as a runtime option]
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) [IF use_partials is globally set to true or passed in as a runtime option,
and skip_partials is not passed in as a runtime option]
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_or_container-
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). The last argument in the list can be a hash and can include the following special options:
[:collection] The collection of elements to render blocks for [:as] The variable name to assign the current element in the collection being rendered over [:wrap_with] The content tag to render around this block (For example: :wrap_with => {:tag => TAG_TYPE, :class => "my-class", :style => "border: 1px solid black"}) [:wrap_each] The content tag to render around each item in a collection (For example: :wrap_each { :class => lambda { cycle("even", "odd") }}) [:use_partials] Overrides the globally defined use_partials and tells Blocks to render partials in to render a block [:skip_partials] Overrides the globally defined use_partials and tells Blocks to not render any partials in to render a block block-
The default block to render if no such block block that is to be rendered when “blocks.render” is called for this block.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/blocks/base.rb', line 151 def render(name_or_container, *args, &block) = args. collection = .delete(:collection) name = extract_block_name name_or_container if skipped_blocks[name] && .skip_applies_to_surrounding_blocks return end buffer = ActiveSupport::SafeBuffer.new wrap_with = .delete(:wrap_with) || {} if collection as = .delete(:as) wrap_each = .delete(:wrap_each) || {} buffer = content_tag_with_block(wrap_with[:tag], wrap_with.except(:tag), *args) do collection.each_with_index do |object, index| cloned_args = args.clone cloned_args.unshift(object) = .clone [:current_index] = index = .merge(object.) if object.is_a?(Blocks::Container) cloned_args.push() block_name = call_with_params(name_or_container, *cloned_args) as_name = (as.presence || block_name).to_sym [as_name] = object [:wrap_with] = wrap_each buffer << render(block_name, *cloned_args, &block) end buffer end else args.push() if .merge()[:wrap_before_and_after_blocks] buffer << content_tag_with_block(wrap_with[:tag], wrap_with.except(:tag), *args) do temp_buffer = ActiveSupport::SafeBuffer.new temp_buffer << render_before_blocks(name_or_container, *args) temp_buffer << render_block_with_around_blocks(name_or_container, *args, &block) temp_buffer << render_after_blocks(name_or_container, *args) end else buffer << render_before_blocks(name_or_container, *args) buffer << content_tag_with_block(wrap_with[:tag], wrap_with.except(:tag), *args) do render_block_with_around_blocks(name_or_container, *args, &block) end buffer << render_after_blocks(name_or_container, *args) end end buffer end |
#render_with_partials(name_or_container, *args, &block) ⇒ Object
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks. Additionally, a collection may also be passed in, and Blocks will render an the block, along with corresponding before and after blocks for each element of the collection. Blocks 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 || %>
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_or_container-
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). The last argument in the list can be a hash and can include the following special options:
[:collection] The collection of elements to render blocks for [:as] The variable name to assign the current element in the collection being rendered over [:wrap_with] The content tag to render around this block (For example: :wrap_with => {:tag => TAG_TYPE, :class => "my-class", :style => "border: 1px solid black"}) [:wrap_each] The content tag to render around each item in a collection (For example: :wrap_each { :class => lambda { cycle("even", "odd") }}) block-
The default block to render if no such block block that is to be rendered when “blocks.render” is called for this block.
285 286 287 288 289 290 |
# File 'lib/blocks/base.rb', line 285 def render_with_partials(name_or_container, *args, &block) = args. [:use_partials] = true args.push() render(name_or_container, *args, &block) end |
#render_without_partials(name_or_container, *args, &block) ⇒ Object
Render a block, first rendering any “before” blocks, then rendering the block itself, then rendering any “after” blocks. Additionally, a collection may also be passed in, and Blocks will render an the block, along with corresponding before and after blocks for each element of the collection. Blocks will make two 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 || %>
Inline Block Step#<%= options[:step] %>.
<% end %>
<%= blocks.render :wizard, :step => @step %>
2) Render the default implementation for the block if provided to the blocks.render call:
<%= blocks.render :wizard, :step => @step do || do %>
Default Implementation Block Step#<%= options %>.
<% end %>
Options:
name_or_container-
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). The last argument in the list can be a hash and can include the following special options:
[:collection] The collection of elements to render blocks for [:as] The variable name to assign the current element in the collection being rendered over [:wrap_with] The content tag to render around this block (For example: :wrap_with => {:tag => TAG_TYPE, :class => "my-class", :style => "border: 1px solid black"}) [:wrap_each] The content tag to render around each item in a collection (For example: :wrap_each { :class => lambda { cycle("even", "odd") }}) block-
The default block to render if no such block block that is to be rendered when “blocks.render” is called for this block.
238 239 240 241 242 243 |
# File 'lib/blocks/base.rb', line 238 def render_without_partials(name_or_container, *args, &block) = args. [:skip_partials] = true args.push() render(name_or_container, *args, &block) 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[:parameter1] %> and <%= options[:parameter2] %>
<% end %>
<%= blocks.replace :some_block_name, :parameter3 => "3", :parameter4 => "4" do || %>
<%= 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 overridden by whomever calls “blocks.render” on this block.
block-
The block that is to be rendered when “blocks.render” is called for this block.
76 77 78 79 80 |
# File 'lib/blocks/base.rb', line 76 def replace(name, ={}, &block) blocks[name] = nil self.define_block_container(name, , &block) nil end |
#skip(name) ⇒ Object
Skip the rendering of a particular block when blocks.render is called for the a particular block name
<%= blocks.define :some_block_name do %>
My output
<% end %>
<%= blocks.skip :some_block_name %>
<%= blocks.render :some_block_name %>
<%# will not render anything %>
Options:
name-
The name of the block to skip rendering for
94 95 96 97 98 99 100 |
# File 'lib/blocks/base.rb', line 94 def skip(name) blocks[name] = nil skipped_blocks[name] = true self.define_block_container(name) do end nil end |