# Wrapping Blocks
Wrappers work similarly to hooks with a few notable exceptions:
1. Wrappers are singular in nature. While there are three different wrappers that may be applied to a block, only one of each may be applied.
2. They are defined directly on the block themselves or provided to the render call.
Wrappers may be defined with either the name of another block, method, or a Proc. That block, method, or Proc must be prepared to take at least one argument, which is the content_block to call when the wrapper is ready to yield control to the content it is wrapping.
## "wrap_all" Wrapper
```erb
<% blocks.define :wrap_all do |c, o| %>
Wrap All Start
<%= c.call %>
Wrap All End
<% end %>
<% blocks.define :wrap_each do |c, i, o| %>
<% if o.nil?; o = i; i = nil end %>
Wrap Each Start <%= i %>
<%= c.call %>
Wrap Each End <%= i %>
<% end %>
<% blocks.around_all :my_block do |c, o| %>
Around All Start
<%= c.call %>
Around All End
<% end %>
<% blocks.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do %>
content
<% end %>
With Collection:
<%= blocks.render :my_block,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block %>
With Collection:
<%= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each %>
```
```haml
- blocks.define :wrap_all do |c, o|
Wrap All Start
= c.call
%br
Wrap All End
- blocks.define :wrap_each do |c, i, o|
- if o.nil?; o = i; i = nil end
%br
Wrap Each Start
= i
%br
= c.call
%br
Wrap Each End
= i
- blocks.around_all :my_block do |c, o|
Around All Start
%br
= c.call
%br
Around All End
%br
- blocks.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do
content
With Collection:
%br
= blocks.render :my_block,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block
#- OR
With Collection:
%br
= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.define :wrap_all do |c, o|
"Wrap All Start" +
c.call +
"
Wrap All End".html_safe
end
builder.define :wrap_each do |c, i, o|
if o.nil?
o = i
i = nil
end
"
Wrap Each Start #{i}
".html_safe +
c.call +
"
Wrap Each End #{i}".html_safe
end
builder.around_all :my_block do |c, o|
"Around All Start
".html_safe +
c.call +
"
Around All End
".html_safe
end
builder.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do
"content"
end
"With Collection:
".html_safe +
builder.render(:my_block,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block)
# OR
"With Collection:
".html_safe +
builder.render(:my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each)
```
> The above code will output the following:
```
With Collection:
Around All Start
Wrap All Start
Wrap Each Start a
content
Wrap Each End a
Wrap Each Start b
content
Wrap Each End b
Wrap All End
Around All End
No Collection:
Around All Start
Wrap All Start
Wrap Each Start
content
Wrap Each End
Wrap All End
Around All End
```
"wrap_all" is a wrapper that surrounds content just inside any "around_all" hooks and around a potential "wrap_each" wrapper (or multiple "wrap_each" wrappers if rendering a collection).
## "wrap_each" Wrapper
```erb
<% blocks.define :wrap_all do |c, o| %>
Wrap All Start
<%= c.call %>
Wrap All End
<% end %>
<% blocks.define :wrap_each do |c, i, o| %>
<% if o.nil?; o = i; i = nil end %>
Wrap Each Start <%= i %>
<%= c.call %>
Wrap Each End <%= i %>
<% end %>
<% blocks.around :my_block do |c, o| %>
Around Start
<%= c.call %>
Around End
<% end %>
<% blocks.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do %>
content
<% end %>
With Collection:
<%= blocks.render :my_block,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block %>
With Collection:
<%= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each %>
```
```haml
- blocks.define :wrap_all do |c, o|
Wrap All Start
= c.call
%br
Wrap All End
%br
- blocks.define :wrap_each do |c, i, o|
- if o.nil?; o = i; i = nil end
%br
Wrap Each Start
= i
%br
= c.call
%br
Wrap Each End
= i
- blocks.around :my_block do |c, o|
Around Start
%br
= c.call
%br
Around End
- blocks.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do
content
With Collection:
%br
= blocks.render :my_block,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block
#- OR
With Collection:
%br
= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.define :wrap_all do |c, o|
"Wrap All Start" +
c.call +
"
Wrap All End".html_safe
end
builder.define :wrap_each do |c, i, o|
if o.nil?
o = i
i = nil
end
"
Wrap Each Start #{i}
".html_safe +
c.call +
"
Wrap Each End #{i}
".html_safe
end
builder.around :my_block do |c, o|
"Around Start
".html_safe +
c.call +
"
Around End".html_safe
end
builder.define :my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each do
"content"
end
"With Collection:
".html_safe +
builder.render(:my_block,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block)
# OR
"With Collection:
".html_safe +
builder.render(:my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block,
wrap_all: :wrap_all,
wrap_each: :wrap_each)
```
> The above code will output the following:
```
With Collection:
With Collection:
Wrap All Start
Wrap Each Start a
Around Start
content
Around End
Wrap Each End a
Wrap Each Start b
Around Start
content
Around End
Wrap Each End b
Wrap All End
No Collection:
Wrap All Start
Wrap Each Start
Around Start
content
Around End
Wrap Each End
Wrap All End
```
*Also aliased to "outer_wrapper"*
When a collection is involved, the "wrap_each" wrapper will wrap each item in the collection with this wrapper, and all of these wrappers can be wrapped together using the "wrap_all" wrapper.
When no collection is involved, the "wrap_each" wrapper will simply act as another wrapper that can be wrapped within the "wrap_all" wrapper and just outside any "wrap_each" wrappers.
## "wrap_with" Wrapper
```erb
<% blocks.surround :my_block do |c, i| %>
<% i = nil if i.is_a?(Blocks::RuntimeContext) %>
Surround Start <%= i %>
<%= c.call %>
Surround End <%= i %>
<% end %>
<% blocks.define :wrap_with do |c, i| %>
<% i = nil if i.is_a?(Blocks::RuntimeContext) %>
Wrap With Start <%= i %>
<%= c.call %>
Wrap Wrap End <%= i %>
<% end %>
<% blocks.before :my_block do |i| %>
<% i = nil if i.is_a?(Blocks::RuntimeContext) %>
Before <%= i %>
<% end %>
<% blocks.after :my_block do |i| %>
<% i = nil if i.is_a?(Blocks::RuntimeContext) %>
After <%= i %>
<% end %>
<% blocks.define :my_block,
wrap_with: :wrap_with do %>
content
<% end %>
With Collection:
<%= blocks.render :my_block,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block %>
With Collection:
<%= blocks.render :my_block,
wrap_with: :wrap_with,
collection: ["a", "b"] %>
No Collection:
<%= blocks.render :my_block,
wrap_with: :wrap_with %>
```
```haml
- blocks.surround :my_block do |c, i|
- i = nil if i.is_a?(Blocks::RuntimeContext)
Surround Start
= i
%br
= c.call
%br
Surround End
= i
- blocks.define :wrap_with do |c, i|
- i = nil if i.is_a?(Blocks::RuntimeContext)
Wrap With Start
= i
%br
= c.call
%br
Wrap Wrap End
= i
- blocks.before :my_block do |i|
- i = nil if i.is_a?(Blocks::RuntimeContext)
Before
= i
%br
- blocks.after :my_block do |i|
- i = nil if i.is_a?(Blocks::RuntimeContext)
%br
After
= i
%br
- blocks.define :my_block,
wrap_with: :wrap_with do
content
With Collection:
%br
= blocks.render :my_block,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block
-# OR
With Collection:
%br
= blocks.render :my_block,
wrap_with: :wrap_with,
collection: ["a", "b"]
%br
No Collection:
%br
= blocks.render :my_block,
wrap_with: :wrap_with
```
```ruby
# where builder is an instance
# of Blocks::Builder
builder.surround :my_block do |c, i|
i = nil if i.is_a?(Blocks::RuntimeContext)
"Surround Start #{i}
".html_safe +
c.call +
"
Surround End #{i}".html_safe
end
builder.define :wrap_with do |c, i|
i = nil if i.is_a?(Blocks::RuntimeContext)
"Wrap With Start #{i}
".html_safe +
c.call +
"
Wrap Wrap End #{i}".html_safe
end
builder.before :my_block do |i|
i = nil if i.is_a?(Blocks::RuntimeContext)
"Before #{i}
".html_safe
end
builder.after :my_block do |i|
i = nil if i.is_a?(Blocks::RuntimeContext)
"
After #{i}
".html_safe
end
builder.define :my_block,
wrap_with: :wrap_with do
"content"
end
"With Collection:
".html_safe
builder.render(:my_block,
wrap_with: :wrap_with,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block,
wrap_with: :wrap_with)
# OR
"With Collection:
".html_safe
builder.render(:my_block,
wrap_with: :wrap_with,
collection: ["a", "b"]) +
"
No Collection:
".html_safe +
builder.render(:my_block,
wrap_with: :wrap_with)
```
> The above code will output the following:
```
With Collection:
Before a
Wrap With Start a
Surround Start a
content
Surround End a
Wrap Wrap End a
After a
Before b
Wrap With Start b
Surround Start b
content
Surround End b
Wrap Wrap End b
After b
No Collection:
Before
Wrap With Start
Surround Start
content
Surround End
Wrap Wrap End
After
```
*Also aliased to "wrap", "wrapper", and "inner_wrapper"*
The "wrap_with" wrapper is preceded by "before" hooks, followed by "after" hooks, surrounded by "around" hooks, and wraps around "surround" hooks.
## Defining a wrapper with a Proc
Wrappers can also be defined with Procs. The Proc must take, at a minimum, the content_block that they are wrapping, as the first argument. They may optionally take the options hash as their second argument.
```erb
<% wrapper = Proc.new do |b| %>