# Rendering Blocks
```erb
<%= blocks.render :my_block %>
<%= blocks.render "my_block" %>
```
```haml
= blocks.render :my_block
#- OR
= blocks.render "my_block"
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.render :my_block
# OR
builder.render "my_block"
```
There is a single method to render a block that has been defined, regardless of that block's rendering strategy (whether it's a Ruby block, Rails partial, or a proxy to another block).
The name of the block being rendered can be a symbol or a string. The underlying system treats symbols and strings the same. Therefore, any block that is defined with a String name can be rendered with its corresponding symbol name and vice-versa.
## With no Corresponding Definition
If a block is rendered without a definition, it doesn't output anything (unless there are hooks or wrappers for the specified block), but it doesn't fail either.
## With a Default Definition
Blocks provides the ability to specify a default definition for the block should no corresponding definition be found.
### With a Ruby Block
```erb
<%= blocks.render :my_block do %>
content
<% end %>
<% my_block = Proc.new { "content" } %>
<%= blocks.render :my_block,
&my_block %>
<% my_block = Proc.new { "content" } %>
<%= blocks.render :my_block,
defaults: { block: my_block } %>
```
```haml
= blocks.render :my_block do
content
-# OR
- my_block = Proc.new { "content" }
= blocks.render :my_block, &my_block
-# OR
- my_block = Proc.new { "content" }
= blocks.render :my_block,
defaults: { block: my_block }
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.render :my_block do
"content"
end
# OR
my_block = Proc.new { "content" }
builder.render :my_block, &my_block
# OR
my_block = Proc.new { "content" }
builder.render :my_block,
defaults: { block: my_block }
```
> After running the above code, the output will be:
```
content
```
The default definition can be specified as a Ruby block:
### With a Rails Partial
```erb
<%= blocks.render :my_block,
defaults: { partial: "my_partial" } %>
```
```haml
= blocks.render :my_block,
defaults: { partial: "my_partial" }
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.render :my_block,
defaults: { partial: "my_partial" }
```
> After running the above code, the output will be whatever the result is of rendering the partial "my_partial"
The default definition can be specified as a Rails partial:
### With a Proxy to Another Block
```erb
<%= blocks.render :my_block,
defaults: { with: :proxy_block } %>
```
```haml
= blocks.render :my_block,
defaults: { with: :proxy_block }
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.render :my_block,
defaults: { with: :proxy_block }
```
> After running the above code, the output will be whatever the result is of rendering the Proxy block or method called "some_other_block"
The default definition can be specified as a proxy to another block:
## With Options
```erb
<%= blocks.render :my_block,
defaults: {
a: "defaults",
b: "defaults"
},
a: "runtime",
c: "runtime" do |options| %>
<%= options.to_json %>
<% end %>
```
```haml
= blocks.render :my_block,
defaults: { a: "defaults",
b: "defaults" },
a: "runtime",
c: "runtime" do |options|
= options.to_json
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.render :my_block,
defaults: {
a: "defaults",
b: "defaults"
},
a: "runtime",
c: "runtime" do |options|
options.to_json
end
```
> The output would be:
```json
{
"a":"runtime",
"c":"runtime",
"b":"defaults"
}
```
Just as options can be set for a block when the block is defined, they can also be applied at render time.
Options provided to the render call can be either runtime options or default options (unlike defining blocks, there is no concept for render standard options).
Default options are specified within a nested hash under the key "defaults".
All other options are considered to be runtime options. Runtime options provided to the render call will take precedence over all other options included runtime options set on the block definition.
### Indifferent Access
```erb
<% blocks.define :my_block,
"a" => "Block String",
b: "Block Symbol" %>
<%= blocks.render :my_block,
a: "Runtime Symbol" do |options| %>
<%= options.to_json %>
<% end %>
```
```haml
- blocks.define :my_block,
"a" => "Block String",
b: "Block Symbol"
= blocks.render :my_block,
a: "Runtime Symbol" do |options|
= options.to_json
```
```ruby
# where builder is an instance of
# Blocks::Builder
builder.define :my_block,
"a" => "Block String",
b: "Block Symbol"
builder.render :my_block,
a: "Runtime Symbol" do |options|
options.to_json
end
```
> The output would be:
```json
{
"a":"Runtime Symbol",
"b":"Block Symbol"
}
```
> Note that the render options took precedence over the block options. This is because render options are treated as runtime options (unless they are wrapper inside of the defaults hash) which take the highest level of precedence when merging options.
Like the name of the block itself, the options hash does not care whether a symbol or a string is provided as a hash key; they are treated the same.
### Deep Merging of Options
```erb
<% blocks.define :my_block,
a: 1,
shared_key: {
a: "a1",
c: "c1"
} %>
<%= blocks.render :my_block,
b: 1,
shared_key: {
a: "a2",
b: "b1"
} do |options| %>
<%= options.to_json %>
<% end %>
```
```haml
- blocks.define :my_block,
a: 1,
shared_key: { a: "a1",
c: "c1"}
= blocks.render :my_block,
b: 1,
shared_key: { a: "a2",
b: "b1" } do |options|
= options.to_json
```
```ruby
# where builder is an instance of
# Blocks::Builder
builder.define :my_block,
a: 1,
shared_key: {
a: "a1",
c: "c1"
}
builder.render :my_block,
b: 1,
shared_key: {
a: "a2",
b: "b1"
} do |options|
options.to_json
end
```
> The output would be:
```json
{
"b":1,
"shared_key": {
"a":"a2",
"c":"c1",
"b":"b1"
},
"a":1
}
```
When the block definition and the render options share a duplicate key with hashes as their values, they are deep merged, giving precedence for duplicate nested keys to the render options.
## With Parameters
```erb
<% blocks.define :my_block do |param_1, param_2, param_3, param_4| %>
Param 1: <%= param_1.inspect %>
Param 2: <%= param_2.inspect %>
Param 3: <%= param_3.inspect %>
Param 4: <%= param_4.inspect %>
<% end %>
Without a Collection:
<%= blocks.render :my_block,
"foo", "bar", a: 1, b: 2 %>
With a Collection:
<%= blocks.render :my_block,
"foo", "bar", a: 1, b: 2,
collection: ["Item1", "Item2"] %>
```
```haml
- blocks.define :my_block do |param_1,
param_2, param_3, param_4|
Param 1:
= param_1.inspect
%br
Param 2:
= param_2.inspect
%br
Param 3:
= param_3.inspect
%br
Param 4:
= param_4.inspect
%br
Without a Collection:
%br
= blocks.render :my_block,
"foo", "bar", a: 1, b: 2
%br
With a Collection:
%br
= blocks.render :my_block,
"foo", "bar", a: 1, b: 2,
collection: ["Item1", "Item2"]
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.define :my_block do |param_1,
param_2, param_3, param_4|
"Param 1: #{param_1.inspect}
".html_safe +
"Param 2: #{param_2.inspect}
".html_safe +
"Param 3: #{param_3.inspect}
".html_safe +
"Param 4: #{param_4.inspect}".html_safe +
end
"Without a Collection:
".html_safe +
builder.render(:my_block,
"foo", "bar", a: 1, b: 2) +
"
With a Collection:
".html_safe +
builder.render(:my_block,
"foo", "bar", a: 1, b: 2,
collection: ["Item1", "Item2"])
```
> This will produce the following output
```
Without a Collection:
Param 1: "foo"
Param 2: "bar"
Param 3: {"a"=>1, "b"=>2}
Param 4: nil
With a Collection:
Param 1: "Item1"
Param 2: "foo"
Param 3: "bar"
Param 4: {"a"=>1, "b"=>2, "object"=>"Item1", "current_index"=>0}
Param 1: "Item2"
Param 2: "foo"
Param 3: "bar"
Param 4: {"a"=>1, "b"=>2, "object"=>"Item2", "current_index"=>1}
```
Blocks are also capable of taking additional parameters besides potentially the options and the item if a collection is being rendered.
Though this concept is still relatively limited in its potential uses at this time (and some additional use cases probably still need to be hammered out), it can be used to pass an arbitrary number of additional parameters to a defined block.
At this time, this will not do anything meaningful if the Block is defined to render a partial. However, if the Block is defined to be a Ruby block or a Proxy to a Block defined with a Ruby block, Blocks will attempt to match up the number of arguments the block expects with the number of arguments that could be sent to it from the render call.
Remember, options will always be the last argument, and if rendering a collection, item will be the first. Any additional params passed to the render call will then be sent as the second argument onward, followed by the options hash. However, if less arguments are expected by the block than are to be sent, Blocks will send the less number of arguments.
See the example to the right to make better sense out of what is being explained here.
## With a Collection
```erb