app/helpers/nestive/layout_helper.rb in nestive-0.1.0 vs app/helpers/nestive/layout_helper.rb in nestive-0.2.0
- old
+ new
@@ -1,11 +1,11 @@
module Nestive
-
+
# The Nestive LayoutHelper provides a handful of helper methods for use in your layouts and views.
#
- # See the documentation for each individual method for detailed information, but at a high level,
- # your parent layouts define `area`s of content. You can define an area and optionally add content
+ # See the documentation for each individual method for detailed information, but at a high level,
+ # your parent layouts define `area`s of content. You can define an area and optionally add content
# to it at the same time using either a String, or a block:
#
# # app/views/layouts/global.html.erb
# <html>
# <head>
@@ -22,15 +22,15 @@
# <% end %>
# </div>
# </body>
# </html>
#
- # Your child layouts (or views) inherit and modify the parent by wrapping in an `extend` block
- # helper. You can then either `append`, `prepend` or `replace` the content that has previously
+ # Your child layouts (or views) inherit and modify the parent by wrapping in an `extends` block
+ # helper. You can then either `append`, `prepend` or `replace` the content that has previously
# been assigned to each area by parent layouts.
#
- # The `append`, `prepend` or `replace` helpers are *similar* to Rails' own `content_for`, which
+ # The `append`, `prepend` or `replace` helpers are *similar* to Rails' own `content_for`, which
# accepts content for the named area with either a String or with a block). They're different to
# `content_for` because they're only used modify the content assigned to the area, not retrieve it:
#
# # app/views/layouts/admin.html.erb
# <%= extends :global do %>
@@ -49,11 +49,11 @@
# <% replace :content do %>
# Normal view stuff goes here.
# <% end %>
# <% end %>
module LayoutHelper
-
+
# Declares that the current layour (or view) is inheriting from and extending another layout.
#
# @param [Symbol] name
# The base name of the file in `layouts/` that you wish to extend (eg `:application` for `layouts/application.html.erb`)
#
@@ -68,27 +68,35 @@
#
# # app/controllers/admin/posts_controller.rb
# class Admin::PostsController < ApplicationController
# # You can disable Rails' layout rendering for all actions
# layout nil
- #
+ #
# # Or disable Rails' layout rendering per-controller
# def index
- # render :layout => nil
+ # render :layout => nil
# end
# end
#
# # app/views/admin/posts/index.html.erb
# <%= extends :admin do %>
# ...
# <% end %>
- def extends(name, &block)
- capture(&block)
- render(:file => "layouts/#{name}")
+ def extends(layout, &block)
+ # Make sure it's a string
+ layout = layout.to_s
+
+ # If there's no directory component, presume a plain layout name
+ layout = layout.include?('/') ? layout : "layouts/#{layout}"
+
+ # Capture the content to be placed inside the extended layout
+ content_for(:layout).replace capture(&block)
+
+ render :file => layout
end
-
- # Defines an area of content in your layout that can be modified or replaced by child layouts
+
+ # Defines an area of content in your layout that can be modified or replaced by child layouts
# that extend it. You can optionally add content to an area using either a String, or a block.
#
# Areas are declared in a parent layout and modified by a child layout, but since Nestive
# allows for multiple levels of inheritance, a child layout can also declare an area for it's
# children to modify.
@@ -119,17 +127,17 @@
def area(name, content=nil, &block)
content = capture(&block) if block_given?
append(name, content)
render_area(name)
end
-
+
def block(name, content=nil, &block)
ActiveSupport::Deprecation.warn("block() is deprecated and will be removed very soon, please use area() instead")
area(name, content, &block)
end
-
- # Appends content to an area previously defined or modified in parent layout(s). You can provide
+
+ # Appends content to an area previously defined or modified in parent layout(s). You can provide
# the content using either a String, or a block.
#
# @example Appending content with a String
# <% append :sidebar, "Some content." %>
#
@@ -144,13 +152,14 @@
# @param [String] content
# Optionally provide a String of content, instead of a block. A block will take precedence.
def append(name, content=nil, &block)
content = capture(&block) if block_given?
add_instruction_to_area(name, :push, content)
+ nil
end
- # Prepends content to an area previously declared or modified in parent layout(s). You can
+ # Prepends content to an area previously declared or modified in parent layout(s). You can
# provide the content using either a String, or a block.
#
# @example Prepending content with a String
# <% prepend :sidebar, "Some content." %>
#
@@ -165,13 +174,14 @@
# @param [String] content
# Optionally provide a String of content, instead of a block. A block will take precedence.
def prepend(name, content=nil, &block)
content = capture(&block) if block_given?
add_instruction_to_area(name, :unshift, content)
+ nil
end
-
- # Replaces the content of an area previously declared or modified in parent layout(s). You can
+
+ # Replaces the content of an area previously declared or modified in parent layout(s). You can
# provide the content using either a String, or a block.
#
# @example Prepending content with a String
# <% replace :sidebar, "New content." %>
#
@@ -186,39 +196,40 @@
# @param [String] content
# Optionally provide a String of content, instead of a block. A block will take precedence.
def replace(name, content=nil, &block)
content = capture(&block) if block_given?
add_instruction_to_area(name, :replace, [content])
+ nil
end
-
+
private
-
+
# We record the instructions (declaring, appending, prepending and replacing) for an area of
# content into an array that we can later retrieve and replay. Instructions are stored in an
- # instance variable Hash `@_area_for`, with each key representing an area name, and each value
- # an Array of instructions. Each instruction is a two element array containing a instruction
+ # instance variable Hash `@_area_for`, with each key representing an area name, and each value
+ # an Array of instructions. Each instruction is a two element array containing a instruction
# method (eg `:push`, `:unshift`, `:replace`) and a value (content String).
#
# @_area_for[:sidebar] # => [ [:push,"World"], [:unshift,"Hello"] ]
#
# Due to the way we extend layouts (render the parent layout after the child), the instructions
- # are captured in reverse order. `render_area` reversed them and plays them back at rendering
+ # are captured in reverse order. `render_area` reversed them and plays them back at rendering
# time.
#
# @example
# add_instruction_to_area(:sidebar, :push, "More content.")
def add_instruction_to_area(name, instruction, value)
@_area_for ||= {}
@_area_for[name] ||= []
@_area_for[name] << [instruction, value]
end
-
+
# Take the instructions we've gathered for the area and replay them one after the other on
# an empty array. These instructions will push, unshift or replace items into our output array,
# which we then join and mark as html_safe.
#
- # These instructions are reversed and replayed when we render the block (rather than as they
+ # These instructions are reversed and replayed when we render the block (rather than as they
# happen) due to the way they are gathered by the layout extension process (in reverse).
#
# @todo is `html_safe` "safe" here?
def render_area(name)
output = []
@@ -227,6 +238,6 @@
end
output.join.html_safe
end
end
-end
\ No newline at end of file
+end