BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

Layouts and Rendering 1 (yield, content_for, content_for?)

RubyOnRails_logo




Bookmark and Share





bogotobogo.com site search:




Introduction

I was puzzled when I looked at the following code (views/pages/home.html.haml) and the rendered page:

%h1= I18n.t('brand.name')

%p
  Rails 4 PyGoogle app with social authentication and other goodies!

%p
  = I18n.t 'brand.name'
  uses best practices and code extracted from several production projects.

%p
  = link_to 'Github', 'https://github.com/PyGoogle/Rails4-PyGoogle.git'

It rendered to a page like this:

PyGoogleHomePage.png

Well, the code is written in haml, and in erb, it looks like this:

<h1>
  <%= I18n.t('brand.name') %>
</h1>
<p>
  Rails 4 PyGoogle app with social authentication and other goodies!
</p>
<p>
  <%= I18n.t 'brand.name' %>
  uses best practices and code extracted from several production projects.
</p>
<p>
  <%= link_to 'Github', 'https://github.com/PyGoogle/Rails4-PyGoogle.git' %>
</p>

Where is the css, header, and footer?

I realized there are still lots of things to learn. So, I looked up resources on rendering and page layouts.

The next sections (or probably subsequent chapters) are my logs of learning.

I followed this one: Layouts and Rendering in Rails.






Creating Responses

Why do start off with "creating responses" when we want to learn about layouts and rendering?

Well, web server needs to respond back to a request, and the form of response is a page, rendered one, most likely, with some good looking layouts.

Controller is responsible for orchestrating the whole process of handling a request in Rails, and when it's time to send a response back to the user, the Controller hands things off to View.

This involves the processes of deciding what should be sent as the response and calling an appropriate method to create that response.

From the controller's point of view, there are three ways to create an HTTP response:

  1. Call render to create a full response to send back to the browser.
  2. Call redirect_to to send an HTTP redirect status code to the browser.
  3. Call head to create a response consisting solely of HTTP headers to send back to the browser.




Layouts

When Rails renders a view as a response, it does so by combining the view with the current layout, using the rules for finding the current layout.

Within a layout, we have access to three tools for combining different bits of output to form the overall response:

  1. yield and content_for
  2. Asset tags
  3. Partials

In the following example for yield and content_for, we'll use the layout below (views/layouts/application.html.erb):

<title><%= content_for?(:title) ? yield(:title) : I18n.t('brand.name') %></title>
<meta name="description" 
          content="<%= content_for?(:description) ? yield(:description) : I18n.t('brand.name') %>">

The first line is for title and the second one is for description which is using the Ruby ternary operator.

Basically, it says, "if content_for?(:title) is present in the view file, use yield(:title) to include it, otherwise just display 'brand.name' which is 'PyGoogle'.





yield

Within the context of a layout, yield identifies a section where content from the view should be inserted. The simplest way to use this is to have a single yield, into which the entire contents of the view currently being rendered is inserted:

<html>
  <head>
  </head>
  <body>
  <%= yield %>
  </body>
</html>

We can also create a layout with multiple yielding regions:

<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>

The main body of the view will always render into the unnamed yield. To render content into a named yield, we use the content_for method.

The following examples, in the title, we use the notation <%= ... %> to insert the title into the template using Ruby's yield function.

Note: the distinction between the two types of embedded Ruby is that <% ... %> executes the code inside, while <%= ... %> executes it and inserts the result into the template. The resulting page is exactly the same as before, only now the variable part of the title is generated dynamically by erb.

views/visitors/index.html.erb:

<title><%= yield(:title) %> | PyGoogle
</title>

<h3>Welcome!</h3>
<p>
This web application was created by
<%= link_to('PyGoogle', 'http://pygoogle.com/') %>.
</p>

This is rendered like the page below:

Welcome-index-page.png

Another page, views/pages/about.html.erb, the yield enables us to replace just the page title:

<title><%= yield(:title) %> | PyGoogle
</title>

<h3>About the yield and content_for</h3>
<p>
This web application was created by
<%= link_to('PyGoogle', 'http://pygoogle.com/') %>.
</p>
yield-about-page.png

Also note that since we've replaced the variable part of the page titles with erb, each of our pages has identical structure, including the contents of the title tag, with the sole exception of the material inside the body tag.

When we look into more deeper, we have a layout file in views/layouts/application.html.erb like this:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= content_for?(:title) ? yield(:title) : "PyGoogle Demo" %></title>
    <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "PyGoogle Demo" %>">
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
    <%= csrf_meta_tags %>
  </head>
  <body>
    <header>
      <%= render 'layouts/navigation' %>
    </header>
    <main role="main">
       <%= render 'layouts/messages' %>
       <%= yield %>
    </main>
  </body>
</html>

As we can see that the default Rails layout includes several additional lines:

<%= stylesheet_link_tag ... %>
<%= javascript_include_tag "application", ... %>
<%= csrf_meta_tags %>

This code arranges to include the application stylesheet and JavaScript, which are part of the asset pipeline, together with the Rails method csrf_meta_tags, which prevents cross-site request forgery (CSRF), a type of malicious web attack.

To see more clearly how it works, we creates dummy controller and view like this:

$ rails generate controller posts index
      ...
      create  app/controllers/posts_controller.rb
       route  get 'posts/index'
      create    app/views/posts/index.html.erb
      ...

The views/posts/index.html.erb has dumb page:

posts-index-page.png

Note that we do not have the appropriate title for the page such as "Posts Pygoogle". The new index page does not have any yield just dumb htmls:

<h1>Posts#index</h1>
<p>Find me in app/views/posts/index.html.erb</p>

Actually, it is expected considering this file, views/layout/application.html.erb:

<title><%= content_for?(:title) ? yield(:title) : "PyGoogle Demo" %></title>

It tells rails just use "PyGoogle Demo" as a title if not yield nor content_for.





Content_for

The content_for method allows us to insert content into a named yield block in our layout. For example, this view would work with the layout that we just saw:

<% content_for :head do %>
  <title>A simple page</title>
<% end %>
 
<p>Hello, Rails!</p>

the result of rendering this page into the supplied layout would be this HTML:

<html>
  <head>
  <title>A simple page</title>
  </head>
  <body>
  <p>Hello, Rails!</p>
  </body>
</html>

The same example used for yield, we're now using content_for instead of yield:

<% content_for :title, "About|PyGoogle" %>

<h3>About the yield and content_for</h3>
<p>
This web application was created by
<%= link_to('PyGoogle', 'http://pygoogle.com/') %>.
</p>

This will be rendered into this page:

About-page-with-content_for.png

Please note that the view file should work with the layout file.

To be fair, there are still other hidden elements such as collapse navbar and stylesheets are working behind the curtain.






Ruby on Rails

  • Ruby On Rails Home
  • Ruby - Input/Output, Objects, Load
  • Ruby - Condition (if), Operators (comparison/logical) & case statement
  • Ruby - loop, while, until, for, each, (..)
  • Ruby - Functions
  • Ruby - Exceptions (raise/rescue)
  • Ruby - Strings (single quote vs double quote, multiline string - EOM, concatenation, substring, include, index, strip, justification, chop, chomp, split)
  • Ruby - Class and Instance Variables
  • Ruby - Class and Instance Variables II
  • Ruby - Modules
  • Ruby - Iterator : each
  • Ruby - Symbols (:)
  • Ruby - Hashes (aka associative arrays, maps, or dictionaries)
  • Ruby - Arrays
  • Ruby - Enumerables
  • Ruby - Filess
  • Ruby - code blocks and yield
  • Rails - Embedded Ruby (ERb) and Rails html
  • Rails - Partial template
  • Rails - HTML Helpers (link_to, imag_tag, and form_for)
  • Layouts and Rendering I - yield, content_for, content_for?
  • Layouts and Rendering II - asset tag helpers, stylesheet_link_tag, javascript_include_tag
  • Rails Project
  • Rails - Hello World
  • Rails - MVC and ActionController
  • Rails - Parameters (hash, array, JSON, routing, and strong parameter)
  • Filters and controller actions - before_action, skip_before_action
  • The simplest app - Rails default page on a Shared Host
  • Redmine Install on a Shared Host
  • Git and BitBucket
  • Deploying Rails 4 to Heroku
  • Scaffold: A quickest way of building a blog with posts and comments
  • Databases and migration
  • Active Record
  • Microblog 1
  • Microblog 2
  • Microblog 3 (Users resource)
  • Microblog 4 (Microposts resource I)
  • Microblog 5 (Microposts resource II)
  • Simple_app I - rails html pages
  • Simple_app II - TDD (Home/Help page)
  • Simple_app III - TDD (About page)
  • Simple_app IV - TDD (Dynamic Pages)
  • Simple_app V - TDD (Dynamic Pages - Embedded Ruby)
  • Simple_app VI - TDD (Dynamic Pages - Embedded Ruby, Layouts)
  • App : Facebook and Twitter Authentication using Omniauth oauth2
  • Authentication and sending confirmation email using Devise
  • Adding custom fields to Devise User model and Customization
  • Devise Customization 2. views/users
  • Rails Heroku Deploy - Authentication and sending confirmation email using Devise
  • Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger I
  • Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger II
  • OOPS! Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger (Trouble shooting)







Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong







Ruby on Rails



Ruby On Rails Home

Ruby - Input/Output, Objects, Load

Ruby - Condition (if), Operators (comparison/logical) & case statement

Ruby - loop, while, until, for, each, (..)

Ruby - Functions

Ruby - Exceptions (raise/rescue)

Ruby - Strings (single quote vs double quote, multiline string - EOM, concatenation, substring, include, index, strip, justification, chop, chomp, split)

Ruby - Class and Instance Variables

Ruby - Class and Instance Variables II

Ruby - Modules

Ruby - Iterator : each

Ruby - Symbols (:)

Ruby - Hashes (aka associative arrays, maps, or dictionaries)

Ruby - Arrays

Ruby - Enumerables

Ruby - Filess

Ruby - code blocks and yield

Rails - Embedded Ruby (ERb) and Rails html

Rails - Partial template

Rails - HTML Helpers (link_to, imag_tag, and form_for)

Layouts and Rendering I - yield, content_for, content_for?

Layouts and Rendering II - asset tag helpers, stylesheet_link_tag, javascript_include_tag

Rails Project

Rails - Hello World

Rails - MVC and ActionController

Rails - Parameters (hash, array, JSON, routing, and strong parameter)

Filters and controller actions - before_action, skip_before_action

The simplest app - Rails default page on a Shared Host

Redmine Install on a Shared Host

Git and BitBucket

Deploying Rails 4 to Heroku

Scaffold: A quickest way of building a blog with posts and comments

Databases and migration

Active Record

Microblog 1

Microblog 2

Microblog 3 (Users resource)

Microblog 4 (Microposts resource I)

Microblog 5 (Microposts resource II)

Simple_app I - rails html pages

Simple_app II - TDD (Home/Help page)

Simple_app III - TDD (About page)

Simple_app IV - TDD (Dynamic Pages)

Simple_app V - TDD (Dynamic Pages - Embedded Ruby)

Simple_app VI - TDD (Dynamic Pages - Embedded Ruby, Layouts)

App : Facebook and Twitter Authentication using Omniauth oauth2

Authentication and sending confirmation email using Devise

Adding custom fields to Devise User model and Customization

Devise Customization 2. views/users

Rails Heroku Deploy - Authentication and sending confirmation email using Devise

Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger I

Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger II

OOPS! Deploying a Rails 4 app on CentOS 7 production server with Apache and Passenger (Trouble shooting)











Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master