Class: Hanami::View::Rendering::LayoutScope

Inherits:
Utils::BasicObject
Defined in:
lib/hanami/view/rendering/layout_scope.rb

Overview

Scope for layout rendering

Since:

  • 0.1.0

Direct Known Subclasses

Scope

Instance Method Summary collapse

Constructor Details

#initialize(layout, scope) ⇒ LayoutScope

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initialize the scope

Parameters:

Since:

  • 0.1.0



29
30
31
32
33
34
# File 'lib/hanami/view/rendering/layout_scope.rb', line 29

def initialize(layout, scope)
  @layout = layout
  @scope  = scope
  @view   = nil
  @locals = nil
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &blk) ⇒ Object (protected)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Forward all the missing methods to the view scope or to the layout.

Examples:

# In the layout template:
#   templates/application.html.erb
#
# Use like this:
<title><%= article.title %></title>

# `article` will be looked up in the view scope first.
# If not found, it will be searched within the layout.

See Also:

Since:

  • 0.1.0



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/hanami/view/rendering/layout_scope.rb', line 208

def method_missing(m, *args, &blk)
  # FIXME: this isn't compatible with Hanami 2.0, as it extends a view
  # that we want to be frozen in the future
  #
  # See https://github.com/hanami/view/issues/130#issuecomment-319326236
  if @scope.respond_to?(m, true) && @scope.locals.has_key?(m) && layout.respond_to?(m, true)
    layout.__send__(m, *args, &blk)
  elsif @scope.respond_to?(m, true)
    @scope.__send__(m, *args, &blk)
  elsif layout.respond_to?(m, true)
    layout.__send__(m, *args, &blk)
  else
    ::Hanami::View::Escape.html(super)
  end
end

Instance Method Details

#formatSymbol

Returns the requested format.

Returns:

  • (Symbol)

    the requested format (eg. :html, :json, :xml, etc..)

Since:

  • 0.1.0



90
91
92
# File 'lib/hanami/view/rendering/layout_scope.rb', line 90

def format
  @scope.format
end

#local(key) ⇒ Object, Hanami::View::Rendering::NullLocal

It tries to invoke a method for the view or a local for the given key. If the lookup fails, it returns a null object.

Examples:

Safe method navigation

<% if local(:plan).overdue? %>
  <h2>Your plan is overdue.</h2>
<% end %>

Optional Contents

# Given the following layout template

<!doctype HTML>
<html>
  <!-- ... -->
  <body>
    <!-- ... -->
    <%= local :footer %>
  </body>
</html>

# Case 1:
#   Products::Index doesn't respond to #footer, local will return nil
#
# Case 2:
#   Products::Show responds to #footer, local will send back
#     #footer returning value

module Products
  class Index
    include Hanami::View
  end

  class Show
    include Hanami::View

    def footer
      "contents for footer"
    end
  end
end

Returns:

Since:

  • 0.7.0



156
157
158
159
160
161
162
# File 'lib/hanami/view/rendering/layout_scope.rb', line 156

def local(key)
  if respond_to?(key)
    __send__(key)
  else
    locals.fetch(key) { NullLocal.new(key) }
  end
end

#localsHash

The current locals.

Returns:

  • (Hash)

    the current locals

Since:

  • 0.1.0



108
109
110
# File 'lib/hanami/view/rendering/layout_scope.rb', line 108

def locals
  (@locals || @scope.locals).dup
end

#render(options) ⇒ String

Render a partial or a template within a layout template.

Examples:

Rendering partial

# Given a partial under:
#   templates/shared/_sidebar.html.erb
#
# In the layout template:
#   templates/application.html.erb
#
# Use like this:
<%= render partial: 'shared/sidebar' %>

Rendering template

# Given a template under:
#   templates/articles/index.html.erb
#
# In the layout template:
#   templates/application.html.erb
#
# Use like this:
<%= render template: 'articles/index' %>

Rendering partial, using optional :locals

# Given a partial under:
#   templates/shared/_sidebar.html.erb
#
# In the layout template:
#   templates/application.html.erb
#
# Use like this:
<%= render partial: 'shared/sidebar', locals: { user: current_user } %>

#
# `user` will be available in the scope of the sidebar rendering

Parameters:

  • options (Hash)

Options Hash (options):

  • :partial (String)

    the partial template to render

  • :template (String)

    the template to render

Returns:

  • (String)

    the output of the rendering process

Raises:

  • (Hanami::Error::UnknownRenderTypeError)

    if the given type to be rendered is unknown

Since:

  • 0.1.0



81
82
83
# File 'lib/hanami/view/rendering/layout_scope.rb', line 81

def render(options)
  renderer(options).render
end

#respond_to?(m, include_all = false) ⇒ TrueClass, FalseClass

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Implements “respond to” logic

Returns:

  • (TrueClass, FalseClass)

See Also:

Since:

  • 0.3.0



172
173
174
# File 'lib/hanami/view/rendering/layout_scope.rb', line 172

def respond_to?(m, include_all = false)
  respond_to_missing?(m, include_all)
end

#respond_to_missing?(m, include_all) ⇒ TrueClass, FalseClass

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Implements “respond to” logic

Returns:

  • (TrueClass, FalseClass)

See Also:

Since:

  • 0.3.0



184
185
186
187
# File 'lib/hanami/view/rendering/layout_scope.rb', line 184

def respond_to_missing?(m, include_all)
  @layout.respond_to?(m, include_all) ||
    @scope.respond_to?(m, include_all)
end

#viewHanami::View

The current view.

Returns:

Since:

  • 0.1.0



99
100
101
# File 'lib/hanami/view/rendering/layout_scope.rb', line 99

def view
  @view || @scope.view
end