Thursday, November 23, 2017

Ruby on Rails - Scaffolding

While you're developing Rails applications, especially those which are mainly providing you with a simple interface to data in a database, it can often be useful to use the scaffold method.
Scaffolding provides more than cheap demo thrills. Here are some benefits −
  • You can quickly get code in front of your users for feedback.
  • You are motivated by faster success.
  • You can learn how Rails works by looking at the generated code.
  • You can use scaffolding as a foundation to jump start your development.

Scaffolding Example

To understand scaffolding, let's create a database called cookbook and a table called recipes.

Creating an Empty Rails Web Application

Open a command window and navigate to where you want to create this cookbook web application. So, run the following command to create a complete directory structure.
tp> rails new cookbook

Setting up the Database

Here is the way to create a database −
mysql> create database cookbook;
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on cookbook.*
to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
To instruct Rails how to find the database, edit the configuration file cookbook\config\database.yml and change the database name to cookbook. Leave the password empty. When you finish, it should look as follows −
development:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost
 
test:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost
 
production:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost
Rails lets you run in the development mode, test mode, or production mode, using different databases. This application uses the same database for each.

The Generated Scaffold Code

With the scaffold action, Rails generates all the code it needs dynamically. By running scaffold as a script, we can get all the code written to disk, where we can investigate it and then start tailoring it to our requirements.
So now, let's start once again to generate Scaffold code manually by using the scaffold helper script −
cookbook> rails generate scaffold recipe
It generates auto-files as shown below −
Scaffold

The Controller

Let's look at the code behind the controller. This code is generated by the scaffold generator. If you open app/controllers/recipes_controller.rb, then you will find something as follows −
class RecipesController < ApplicationController
   before_action :set_recipe, only: [:show, :edit, :update, :destroy]
   
   # GET /recipes
   # GET /recipes.json
   def index
      @recipes = Recipe.all
   end
   
   # GET /recipes/1
   # GET /recipes/1.json
   def show
   end
   
   # GET /recipes/new
   def new
      @recipe = Recipe.new
   end
   
   # GET /recipes/1/edit
   def edit
   end
   
   # POST /recipes
   # POST /recipes.json
   def create
      @recipe = Recipe.new(recipe_params)
      
      respond_to do |format|
         if @recipe.save
            format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
            format.json { render :show, status: :created, location: @recipe }
         else
            format.html { render :new }
            format.json { render json: @recipe.errors, status: :unprocessable_entity }
         end
      end
      
   end
   
   # PATCH/PUT /recipes/1
   # PATCH/PUT /recipes/1.json
   def update
      respond_to do |format|
         if @recipe.update(recipe_params)
            format.html { redirect_to @recipe, notice: 'Recipe was successfully updated.' }
            format.json { render :show, status: :ok, location: @recipe }
         else
            format.html { render :edit }
            format.json { render json: @recipe.errors, status: :unprocessable_entity }
         end
      end
      
   end
   
   # DELETE /recipes/1
   # DELETE /recipes/1.json
   def destroy
      @recipe.destroy
         respond_to do |format|
         format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
         format.json { head :no_content }
      end
   end
   
   private
   
   # Use callbacks to share common setup or constraints between actions.
   def set_recipe
      @recipe = Recipe.find(params[:id])
   end
   
   # Never trust parameters from the scary internet, only allow the white list through.
   def recipe_params
      params.require(:recipe).permit(:tittle, :instructions)
   end
end
When the user of a Rails application selects an action, e.g. "Show" - the controller will execute any code in the appropriate section - "def show" - and then by default will render a template of the same name - "show.html.erb". This default behavior can be overwritten.
The controller uses ActiveRecord methods such as find, find_all, new, save, update_attributes, and destroy to move data to and from the database tables. Note that you do not have to write any SQL statements, rails will take care of it automatically.
This single line of code will bring the database table to life. It will provide with a simple interface to your data, and ways of −
  • Creating new entries
  • Editing current entries
  • Viewing current entries
  • Destroying current entries
When creating or editing an entry, scaffold will do all the hard work like form generation and handling for you, and will even provide clever form generation, supporting the following types of inputs −
  • Simple text strings
  • Text areas (or large blocks of text)
  • Date selectors
  • Date-time selectors
You can use Rails Migrations to create and maintain tables.
rake db:migrate RAILS_ENV=development
Now, go to the cookbook directory and run the Web Server using the following command −
cookbook> rails server
Now, open a browser and navigate to http://127.0.0.1:3000/recipe/new.This will provide you a screen to create new entries in the recipes table. A screenshot is shown below −
Create Recipe
Once you press the Create button to create a new recipe, your record is added into the recipes table and it shows the following result −
Create Recipe
You can see the option to edit, show, and destroy the records. So, play around with these options.
You can also list down all the recipes available in the recipes table using the URL http://127.0.0.1:3000/recipe/list.

Enhancing the Model

Rails gives you a lot of error handling for free. To understand this, add some validation rules to the empty recipe model −
Modify app/models/recipe.rb as follows and then test your application −
class Recipe < ActiveRecord::Base
   validates_length_of :title, :within => 1..20
   validates_uniqueness_of :title, :message => "already exists"
end
These entries will give automatic checking.
  • validates_length_of − the field is not blank and not too long.
  • validates_uniqueness_of − duplicate values are trapped. Instead of the default Rails error message, we have given a custom message here.

Alternative Way to Create Scaffolding

Create an application as shown above and The Generated Scaffold Code as shown below
rails g scaffold Recipe tittle:string instructions:text
Above code generates the auto files with data base by using with sqlite3 with tittle and instruction column as shown below an image.
Scaffold
we need to migrate the data base by using below syntax.
$ rake db:migrate RAILS_ENV=development
Finally run the application by using the following command line −
rails server
It will generate the result as shown above output images.

The Views

All the views and corresponding all the controller methods are created by scaffold command and they are available in the app/views/recipes directory.

How Scaffolding is Different?

If you have gone through the previous chapters, then you must have seen that we had created methods to list, show, delete and create data etc., but scaffolding does that job automatically.

Tuesday, November 14, 2017

Ruby on Rails - Layouts

A layout defines the surroundings of an HTML page. It's the place to define a common look and feel of your final output. Layout files reside in app/views/layouts.
The process involves defining a layout template and then letting the controller know that it exists and to use it. First, let's create the template.
Add a new file called standard.html.erb to app/views/layouts. You let the controllers know what template to use by the name of the file, so following a same naming scheme is advised.
Add the following code to the new standard.html.erb file and save your changes −
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">

   <head>
      <meta http-equiv = "Content-Type" content = "text/html; charset = iso-8859-1" />
      <meta http-equiv = "Content-Language" content = "en-us" />
      <title>Library Info System</title>
      <%= stylesheet_link_tag "style" %>
   </head>

   <body id = "library">
      <div id = "container">
         
         <div id = "header">
            <h1>Library Info System</h1>
            <h3>Library powered by Ruby on Rails</h3>
         </div>

         <div id = "content">
            <%= yield -%>
         </div>

         <div id = "sidebar"></div>
         
      </div>
   </body>
   
</html>
Everything you just added were standard HTML elements except two lines. The stylesheet_link_tag helper method outputs a stylesheet <link>. In this instance, we are linking style.css style sheet. The yield command lets Rails know that it should put the html.erb for the method called here.
Now open book_controller.rb and add the following line just below the first line −
class BookController < ApplicationController
layout 'standard'
def list
@books = Book.all
end
...................
It instructs the controller that we want to use a layout available in the standard.html.erb file. Now try browsing books that will produce the following screen.
Layout Example

Adding Style Sheet

Till now, we have not created any style sheet, so Rails is using the default style sheet. Now let's create a new file called style.css and save it in /public/stylesheets. Add the following code to this file.
body {
   font-family: Helvetica, Geneva, Arial, sans-serif;
   font-size: small;
   font-color: #000;
   background-color: #fff;
}

a:link, a:active, a:visited {
   color: #CD0000;
}

input { 
   margin-bottom: 5px;
}

p { 
   line-height: 150%;
}

div#container {
   width: 760px;
   margin: 0 auto;
}

div#header {
   text-align: center;
   padding-bottom: 15px;
}

div#content {
   float: left;
   width: 450px;
   padding: 10px;
}

div#content h3 {
   margin-top: 15px;
}

ul#books {
   list-style-type: none;
}

ul#books li {
   line-height: 140%;
}

div#sidebar {
   width: 200px;
   margin-left: 480px;
}

ul#subjects {
   width: 700px;
   text-align: center;
   padding: 5px;
   background-color: #ececec;
   border: 1px solid #ccc;
   margin-bottom: 20px;
}

ul#subjects li {
   display: inline;
   padding-left: 5px;
}
Now refresh your browser and see the difference −

Ruby on Rails - Views

A Rails View is an ERb program that shares data with controllers through mutually accessible variables.
If you look in the app/views directory of the library application, you will see one subdirectory for each of the controllers, we have created: book. Each of these subdirectories was created automatically when the same-named controller was created with the generate script.
Rails let's you know that you need to create the view file for each new method. Each method you define in the controller needs to have a corresponding erb file, with the same name as the method, to display the data that the method is collecting.
So let's create view files for all the methods we have defined in the book_controller.rb. While executing these views, simultaneously check these actions are applicable into the database or not.

Creating View File for list Method

Create a file called list.html.erb using your favourite text editor and save it to app/views/book. After creating and saving the file, refresh your web browser. You should see a blank page; if you don't, check the spelling of your file and make sure that it is exactly the same as your controller's method.
Now, display the actual content. Let us put the following code into list.html.erb.
<% if @books.blank? %>
<p>There are not any books currently in the system.</p>
<% else %>
<p>These are the current books in our system</p>

<ul id = "books">
   <% @books.each do |c| %>
   <li><%= link_to c.title, {:action => 'show', :id => c.id} -%></li>
   <% end %>
</ul>

<% end %>
<p><%= link_to "Add new Book", {:action => 'new' }%></p>
The code to be executed is to check whether the @books array has any objects in it. The .blank? method returns true if the array is empty, and false if it contains any objects. This @books object was created in controller inside the list method.
The code between the <%= %> tags is a link_to method call. The first parameter of link_to is the text to be displayed between the <a> tags. The second parameter is what action is called when the link is clicked. In this case, it is the show method. The final parameter is the id of the book that is passed via the params object.
Now, try refreshing your browser and you should get the following screen because we don't have any book in our library.
No Book Message

Creating View File for new Method

Till now, we don't have any book in our library. We have to create few books in the system. So, let us design a view corresponding to the new method defined in the book_controller.rb.
Create a file called new.html.erb using your favorite text editor and save it to app/views/book. Add the following code to the new.html.erb file.
<h1>Add new book</h1>

<%= form_tag :action => 'create' do %>
<p><label for = "book_title">Title</label>:

<%= text_field 'books', 'title' %></p>
<p><label for = "book_price">Price</label>:

<%= text_field 'books', 'price' %></p>
<p><label for = "book_subject_id">Subject</label>:

<%= collection_select(:books, :subject_id, @subjects, :id, :name, prompt: true) %></p>
<p><label for = "book_description">Description</label><br/>

<%= text_area 'books', 'description' %></p>
<%= submit_tag "Create" %>

<% end -%>
<%= link_to 'Back', {:action => 'list'} %>
Here form_tag method interprets the Ruby code into a regular HTML <form> tag using all the information supplied to it. This tag, for example, outputs the following HTML −
<form action = "/book/create" method = "post">
Next method is text_field that outputs an <input> text field. The parameters for text_field are object and field name. In this case, the object is book and the name is title.
Rails method called collection_select, creates an HTML select menu built from an array, such as the @books one. There are five parameters, which are as follows −
  • :book − The object you are manipulating. In this case, it's a book object.
  • :subject_id − The field that is populated when the book is saved.
  • @books − The array you are working with.
  • :id − The value that is stored in the database. In terms of HTML, this is the <option> tag's value parameter.
  • :name − The output that the user sees in the pull-down menu. This is the value between the <option> tags.
The next used is submit_tag, which outputs an <input> button that submits the form. Finally, there is the end method that simply translates into </form>.
Go to your browser and visit http://localhost:3000/book/new. This will give you the following screen.
New Book
Enter some data in this form and then click the Create button. Here i have added the following details into the fields −
Title: Advance Physics
Price: 390
Subject: Physics
Description: This is test to create new book
When you click the Create button, it will call the create method, which does not need any view because this method is using either list or new methods to view the results. So, when you click the Create button, the data should submit successfully and redirect you to the list page, in which you now have a single item listed as follows −
Create Book
If you click the link, you should see another Template is missing error, since you haven't created the template file for show method yet.

Creating View File for show Method

This method will display the complete detail about any book available in the library. Create a show.html.erb file under app/views/book and populate it with the following code −
<h1><%= @book.title %></h1>

<p>
   <strong>Price: </strong> $<%= @book.price %><br />
   <strong>Subject :</strong> <%= @book.subject.name %><br />
   <strong>Created Date:</strong> <%= @book.created_at %><br />
</p>

<p><%= @book.description %></p>

<hr />

<%= link_to 'Back', {:action => 'list'} %>
This is the first time you have taken the full advantage of associations, which enable you to easily pull data from related objects.
The format used is @variable.relatedObject.column. In this instance, you can pull the subject's name value through the @book variable using the belongs_to associations. If click on any listed record then it will show you the following screen.
Show Book

Creating View File for edit Method

Create a new file called edit.html.erb and save it in app/views/book. Populate it with the following code −
<h1>Edit Book Detail</h1>

<%= form_for @book, :url =>{:action => "update", :id =>@book} do |f| %>

<p>Title: <%= f.text_field 'title' %></p>
<p>Price: <%= f.text_field  'price' %></p>
<p>Subject: <%= f.collection_select :subject_id, Subject.all, :id, :name %></p>
<p>Description<br/>

<%= f.text_area 'description' %></p>
<%= f.submit "Save changes" %>
<% end %>

<%= link_to 'Back', {:action => 'list' } %>
This code is very similar to the new method except action to be updated instead of creating and defining an id.
In this scenario, we used form_for tag for the form action. It will perform better than form_tag. Why because it will create interaction with the Model easily. Therefore it is better to use form_for tag whenever you need interaction between the model and the form fields.
At this point, we need some modification in the list method's view file. Go to the <li></li> element and modify it to look like the following −
<li>
   <%= link_to c.title, {:action => "show", :id => c.id} -%>
   <b> <%= link_to 'Edit', {:action => "edit",
   :id => c.id} %></b>
</li>
Now, try to browse books using the http://localhost:3000/book/list. It will give you the listing of all the books along with Edit option. When you click the Edit option, then you will have next screen as follows −
Edit Book
Now, you edit this information and then click the Save Changes button. This will result in a call to update method available in the controller file and it will update all the changed attribute. Notice that the update method does not need any view file because it's using either show or edit methods to show its results.

Creating View File for delete Method

Removing information from a database using Ruby on Rails is almost too easy. You do not need to write any view code for the delete method because this method is using list method to display the result. So, let's just modify list.html.erb again and add a delete link.
Go to the <li></li> element and modify it to look like the following −
<li>
   <%= link_to c.title, {:action => 'show', :id => c.id} -%>
   <b> <%= link_to 'Edit', {:action => 'edit', :id => c.id} %></b>
   <b> <%= link_to "Delete", {:action => 'delete', :id => c.id},
      :confirm => "Are you sure you want to delete this item?" %></b>
</li>
The :confirm parameter presents a JavaScript confirmation box asking if you really want to perform the action. If the user clicks OK, the action proceeds, and the item is deleted.
Now, try browsing books using http://localhost:3000/book/list. It will give you listing of all the books along with Edit and Delete options as follows −
Delete Book
Now using the Delete option, you can delete any listed record.

Creating View File for show_subjects Method

Create a new file, show_subjects.html.erb, in the app/views/book directory and add the following code to it −
<h1><%= @subject.name -%></h1>

<ul>
   <% @subject.books.each do |c| %>
   <li><%= link_to c.title, :action => "show", :id => c.id -%></li>
   <% end %>
</ul>
You are taking advantage of associations by iterating through a single subject's many books listings.
Now modify the Subject: line of show.html.erb so that the subject listing shows a link.
<strong>Subject: </strong> <%= link_to @book.subject.name,
:action => "show_subjects", :id => @book.subject.id %><br />
This will output a list of subject on the index page, so that users can access them directly.
Modify list.html.erb to add the following to the top of the file −
<ul id = "subjects">
   <% Subject.find(:all).each do |c| %>
   <li><%= link_to c.name, :action => "show_subjects", :id => c.id %></li>
   <% end %>
</ul>
Now try browsing books using http://localhost:3000/book/list. It will display all subjects with links so that you can browse all the books related to that subject.