sexta-feira, 24 de março de 2017

How to install Java 7 and Java 8 on CentOs 7 - 32bits or 64bits

1. Introduction

This post only gathers information about how to install Java ( version 7 or 8) on CentOs ( version 5, 6 or 7)


2. References


sábado, 18 de março de 2017

RAILS Creating Static Pages in a Rails App

1. Introduction

This post gathers information about how to create Static Pages in RAILS.


2. Step by Step

2.1. Creating controller 'staticpages' for static pages

$ rails generate controller staticpages --skip-assets
Running via Spring preloader in process 3573
      create  app/controllers/staticpages_controller.rb
      invoke  erb
      create    app/views/staticpages
      invoke  test_unit
      create    test/controllers/staticpages_controller_test.rb
      invoke  helper
      create    app/helpers/staticpages_helper.rb
      invoke    test_unit

2.2. Edit Controller 'staticpages' to implement actions

$ vim app/controllers/staticpages_controller.rb
class StaticpagesController < ApplicationController
  def show
    if valid_page?
      render template: "staticpages/#{params[:page]}"
    else
      render file: "public/404.html", status: :not_found
    end
  end

  private
    def valid_page?
      File.exist?(Pathname.new(Rails.root + "app/views/staticpages/#{params[:page]}.html.erb"))
    end

end


2.3. Edit Routes for 'staticpages' and redirect root to staticpages/home

vim config/routes.rb
Rails.application.routes.draw do
    :
  get "/staticpages/:page" => "staticpages#show"

  root 'staticpages#home'
    :

2.4. Edit some StaticPages: home, sitemap, userdoc, about

$ vim app/views/staticpages/home.html.erb
<h1>Static Page #Home</h1>
Find me in app/views/staticpages/home.html.erb

$ vim app/views/staticpages/sitemap.html.erb
<h1>Static Page #Sitemap</h1>
Find me in app/views/staticpages/sitemap.html.erb

$ vim app/views/staticpages/userdoc.html.erb
<h1>Static Page #Userdoc</h1>
Find me in app/views/staticpages/userdoc.html.erb

$ vim app/views/staticpages/about.html.erb
<h1>Static Page #About</h1>
Find me in app/views/staticpages/about.html.erb

2.5. Test StaticPages


3. References


RAILS Using console

1. Introduction

This post shows how to use RAILS Console.



2. Step-by-Step

2.1. Pre-Conditions

You should have a model post title:string body:text and another model comment post: reference body: text. References #1 has a step-by-step of creating objects


2.2. Executing some RAILS console commands


  • Run Console

$ rails console
Running via Spring preloader in process 2669
Loading development environment (Rails 5.0.2)


  • Get first record from model 'Post'

irb(main):001:0> Post.first
  Post Load (3.6ms)  SELECT  "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<Post id: 1, title: "1", body: "first", created_at: "2017-03-18 15:15:30", updated_at: "2017-03-18 15:16:05">


  • Get all records from model 'Post'

irb(main):004:0> Post.all
  Post Load (0.6ms)  SELECT "posts".* FROM "posts"
=> #<ActiveRecord::Relation [#<Post id: 1, title: "1", body: "first", created_at: "2017-03-18 15:15:30", updated_at: "2017-03-18 15:16:05">]>


  • Get records using criteria of filter created_at - result using JSON

irb(main):096:0* Post.where(created_at: Date.yesterday..Date.tomorrow)
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" WHERE ("posts"."created_at" BETWEEN $1 AND $2)  [["created_at", Fri, 17 Mar 2017], ["created_at", Sun, 19 Mar 2017]]
=> #<ActiveRecord::Relation [#<Post id: 1, title: "1", body: "first", created_at: "2017-03-18 15:15:30", updated_at: "2017-03-18 15:16:05">]>

  • Get records using criteria of filter created_at - result using SQL
irb(main):108:0> Post.where(created_at: Date.yesterday..Date.tomorrow).to_sql
=> "SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"created_at\" BETWEEN '2017-03-17' AND '2017-03-19')"

  • Create a record of Post
irb(main):124:0* Post.create! title: 'Hello World', body: 'One World', created_at: '2017-03-15 15:45', updated_at: '2017-03-15 15:45'
   (0.1ms)  BEGIN
  SQL (47.5ms)  INSERT INTO "posts" ("title", "body", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["title", "Hello World"], ["body", "One World"], ["created_at", 2017-03-15 15:45:00 UTC], ["updated_at", 2017-03-15 15:45:00 UTC]]
   (22.7ms)  COMMIT
=> #<Post id: 2, title: "Hello World", body: "One World", created_at: "2017-03-15 15:45:00", updated_at: "2017-03-15 15:45:00">

  • Create a record of  'Comments' from first 'Post'
irb(main):001:0> Post.first.comments
Post Load (0.4ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT $1 [["LIMIT", 1]]
Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy []>

  • Add a record of  'Comments' into first 'Post'
irb(main):002:0> Post.first.comments.create! body: 'Say something funny'
  Post Load (0.4ms)  SELECT  "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT $1  [["LIMIT", 1]]
   (0.1ms)  BEGIN
  SQL (1.0ms)  INSERT INTO "comments" ("post_id", "body", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["post_id", 1], ["body", "Say something funny"], ["created_at", 2017-03-18 19:19:38 UTC], ["updated_at", 2017-03-18 19:19:38 UTC]]
   (15.0ms)  COMMIT
=> #<Comment id: 1, post_id: 1, body: "Say something funny", created_at: "2017-03-18 19:19:38", updated_at: "2017-03-18 19:19:38">

  • Get records of  'Comments' from first 'Post' again - after 'Say something funny' created
irb(main):003:0> Post.first.comments
  Post Load (0.3ms)  SELECT  "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT $1  [["LIMIT", 1]]
  Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1  [["post_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 1, post_id: 1, body: "Say something funny", created_at: "2017-03-18 19:19:38", updated_at: "2017-03-18 19:19:38">]>
irb(main):004:0>


3. References

RAILS Using Scaffold to create CRUD application on PostgreSQL

1. Introduction

This post shows how to create a simple application using scaffolding generator connectiong to PostgreSQL.


2. Step-by-Step

2.1. Create application named 'weblog' using 'PostgreSQL' database

$ pwd
/home/rails-home
$ rails new weblog -d postgresql
$ cd weblog
$ pwd
/home/rails-home/weblog


2.2. Generate scaffold CRUD for 'post' entity with attributes title:string and body:string

a. Generate scaffold

$ rails generate scaffold post title:string body:text
Running via Spring preloader in process 2854
      invoke  active_record
      create    db/migrate/20170318144830_create_posts.rb
      create    app/models/post.rb
        :            :
      invoke  resource_route
       route    resources :posts
      invoke  scaffold_controller
      create    app/controllers/posts_controller.rb
      invoke    erb
      create      app/views/posts
      create      app/views/posts/index.html.erb
      create      app/views/posts/edit.html.erb
      create      app/views/posts/show.html.erb
      create      app/views/posts/new.html.erb
      create      app/views/posts/_form.html.erb
        :            :
      invoke    jbuilder
      create      app/views/posts/index.json.jbuilder
      create      app/views/posts/show.json.jbuilder
      create      app/views/posts/_post.json.jbuilder
        :            :


b. Checking what scaffold has done: 

(i) migration script

$ cat db/migrate/*_create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end

(ii) model for application

$ cat app/models/post.rb
class Post < ApplicationRecord
end

(iii) controller with actions new, create, ..., destroy

$ cat app/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]
    :
  def index
    :
  end
    :
  def show
    :
  end
    :
  def new
    :
  end
    :
  def edit
    :
  end
    :
  def create
    :
  end
    :
  def update
    :
  end
    :
  def destroy
    :
  end
    :
  private
    def set_post
    :
    end
    :
    def post_params
    :
    end
    :
end

(iv) views

$ ls -la app/views/posts
total 36
drwxr-xr-x. 2 root root 4096 Mar 18 11:48 .
drwxr-xr-x. 4 root root   32 Mar 18 11:48 ..
-rw-r--r--. 1 root root  123 Mar 18 11:48 edit.html.erb
-rw-r--r--. 1 root root  579 Mar 18 11:48 _form.html.erb
-rw-r--r--. 1 root root  591 Mar 18 11:48 index.html.erb
-rw-r--r--. 1 root root   53 Mar 18 11:48 index.json.jbuilder
-rw-r--r--. 1 root root   88 Mar 18 11:48 new.html.erb
-rw-r--r--. 1 root root  104 Mar 18 11:48 _post.json.jbuilder
-rw-r--r--. 1 root root  227 Mar 18 11:48 show.html.erb
-rw-r--r--. 1 root root   40 Mar 18 11:48 show.json.jbuilder



c. Start RAILS server and observe what scaffold does for us

i) Configure RAILS on to listen for all interfaces

$ vim ./config/boot.rb
        :
      super.merge(Host:  '0.0.0.0', Port: 3000)
        :

ii) Create databases DEV and PROD using

$ rake db:create

iii) Create database tables using migrate

$ rails db:migrate

iv) Run rails server

$ rails server

v) Check results


  • http://localhost:3000 - See Yay! You're on Rails!
  • http://localhost:3000/posts - Simple CRUD application for Posts, you can do: new, show, edit, destroy
  • http://localhost:3000/posts.json - JSON object representing all posts:  [{"id":1,"title":"1","body":"first","created_at":"2017-03-18T15:15:30.015Z","updated_at":"2017-03-18T15:16:05.960Z","url":"http://localhost:3000/posts/1.json"}]


2.3. Adding some validation 

  • Edit model and add validation rule
$ vim app/models/post.rb
class Post < ApplicationRecord
  validates_presence_of :title
end

  • Try to create a post without title and observe error validation:      1 error prohibited this post from being saved:  Title can't be blank

2.3. Creating Comment model reference Post  (master detail)

a. Create resource comment referencing post

$ rails generate resource comment post:references body:text
Running via Spring preloader in process 3025
      invoke  active_record
      create    db/migrate/20170318185201_create_comments.rb
      create    app/models/comment.rb
      invoke    test_unit
      create      test/models/comment_test.rb
      create      test/fixtures/comments.yml
      invoke  controller
      create    app/controllers/comments_controller.rb
      invoke    erb
      create      app/views/comments
      invoke    test_unit
      create      test/controllers/comments_controller_test.rb
      invoke    helper
      create      app/helpers/comments_helper.rb
      invoke      test_unit
      invoke    assets
      invoke      coffee
      create        app/assets/javascripts/comments.coffee
      invoke      scss
      create        app/assets/stylesheets/comments.scss
      invoke  resource_route
       route    resources :comments

b. Run migrate to create database table for 'comment'

$ rails db:migrate
== 20170318185201 CreateComments: migrating ===================================
-- create_table(:comments)
   -> 0.1987s
== 20170318185201 CreateComments: migrated (0.1988s) ==========================

c. Configure nesting of routes on post controller to comment'

$  vim config/routes.rb
Rails.application.routes.draw do
  resources :posts do
    resources :comments
  end
end

d. Check routes created

$ rails routes
           Prefix Verb   URI Pattern                                 Controller#Action
    post_comments GET    /posts/:post_id/comments(.:format)          comments#index
                  POST   /posts/:post_id/comments(.:format)          comments#create
 new_post_comment GET    /posts/:post_id/comments/new(.:format)      comments#new
edit_post_comment GET    /posts/:post_id/comments/:id/edit(.:format) comments#edit
     post_comment GET    /posts/:post_id/comments/:id(.:format)      comments#show
                  PATCH  /posts/:post_id/comments/:id(.:format)      comments#update
                  PUT    /posts/:post_id/comments/:id(.:format)      comments#update
                  DELETE /posts/:post_id/comments/:id(.:format)      comments#destroy
            posts GET    /posts(.:format)                            posts#index
                  POST   /posts(.:format)                            posts#create
         new_post GET    /posts/new(.:format)                        posts#new
        edit_post GET    /posts/:id/edit(.:format)                   posts#edit
             post GET    /posts/:id(.:format)                        posts#show
                  PATCH  /posts/:id(.:format)                        posts#update
                  PUT    /posts/:id(.:format)                        posts#update
                  DELETE /posts/:id(.:format)                        posts#destroy

e. Check model 'comment' created

$ cat app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post
end

f. Adjust 'post' model to has many of 'comment' models

$ vim app/models/post.rb
class Post < ApplicationRecord
  has_many :comments
  validates_presence_of :title
end


2.4. Edit view of 'post' to show related 'comments'

a. Edit view 'show' of 'post' - add code to show related comments

$ vim app/views/posts/show.html.erb
          :
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
<br><br>
<h2>Comments</h2>
  <div id="comments">
    <%# Expands to render partial: 'comments/comment', collection: @post.comments %>
    <%= render @post.comments %>
  </div>
    <%= render 'comments/new', post: @post %>
  </div>

b. Edit view templates '_form' and '_new' of 'Comment'

$ vim  app/views/comments/_new.html.erb
<%= form_for([ @post, Comment.new ], remote: true) do |form| %>
  Your comment:<br>
  <%= form.text_area :body, size: '50x20' %><br>
  <%= form.submit %>
<% end %>

$ vim app/views/comments/_comment.html.erb
<p><%= comment.body %> -- <%= comment.created_at.to_s(:log) %><p>

c. Implement 'comment' controller actions 

$ vim app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  before_action :set_post

  def create
    @post.comments.create! comments_params
    redirect_to @post
  end

  private
    def set_post
      @post = Post.find(params[:post_id])
    end

    def comments_params
      params.required(:comment).permit(:body)
    end

end


3. References



sexta-feira, 17 de março de 2017

RAILS Creating a simple Ruby on RAILS application with PostgreSQL database

1. Introduction

This post gathers information about creating a Ruby on RAILS application with PostgreSQL

2. Step-by-step

2.1. Create a Ruby on RAILS with PostgreSQL database

$ pwd
/home/rails-home
$ rails new myrailsapppostgres -d postgresql


2.2.  Grant PostgreSQL database permission for administration user 'root' used on RAILS

$ psql
postgres=# CREATE USER root WITH PASSWORD 'root';
postgres=# GRANT postgres TO root;
postgres=# ALTER USER root CREATEDB;
postgres=# \q


2.3.  Create RAILS database

$ pwd
/home/rails-home/myrailsapppostgres
$ rake db:create
Created database 'myrailsapppostgres_development'
Created database 'myrailsapppostgres_test'


2.4.  Configure RAILS to listen for any 0.0.0.0 IP adddress on Port 3000 (default is 127.0.0.1:3000) 

$ pwd
/home/rails-home/myrailsapppostgres
$ vim ./config/boot.rb
    :
    require 'rails/commands/server'
    module Rails
      class Server
        def default_options
          super.merge(Host:  '0.0.0.0', Port: 3000)
        end
      end
    end
    :


2.5.  Create Welcome page

$ pwd
/home/rails-home/myrailsapppostgres
$ rails generate controller Welcome index
$ vim app/views/welcome/index.html.erb
<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>
$ vim config/routes.rb
Rails.application.routes.draw do
  get 'welcome/index'
  root 'welcome#index'
end


2.6. Exploring RAILS files and folders

  • app/: Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.
  • bin/: Contains the rails script that starts your app and can contain other scripts you use to setup, update, deploy or run your application.
  • config/: Configure your application's routes, database, and more. This is covered in more detail in Configuring Rails Applications.
  • config.ru: Rack configuration for Rack based servers used to start the application.
  • db/: Contains your current database schema, as well as the database migrations.
  • Gemfile 
  • Gemfile.lock : These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see the Bundler website.
  • lib/: Extended modules for your application.
  • log/: Application log files.
  • public/: The only folder seen by the world as-is. Contains static files and compiled assets.
  • Rakefile: This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.
  • README.md: This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.
  • test/: Unit tests, fixtures, and other test apparatus. These are covered in Testing Rails Applications.
  • tmp/: Temporary files (like cache and pid files).
  • vendor/: A place for all third-party code. In a typical Rails application this includes vendored gems.


2.7. Creating a simple RAILS application

a) create a resource 'articles' and check routes

$ pwd
/root/rails-home/myrailsapppostgres
$ vim config/routes.rb
Rails.application.routes.draw do
  get 'welcome/index'

  resources :articles
  root 'welcome#index'

end


b) check all RESTfull actions

$ rails routes
       Prefix Verb   URI Pattern                  Controller#Action
welcome_index GET    /welcome/index(.:format)     welcome#index
         root GET    /                            welcome#index
     articles GET    /articles(.:format)          articles#index
              POST   /articles(.:format)          articles#create
  new_article GET    /articles/new(.:format)      articles#new
 edit_article GET    /articles/:id/edit(.:format) articles#edit
      article GET    /articles/:id(.:format)      articles#show
              PATCH  /articles/:id(.:format)      articles#update
              PUT    /articles/:id(.:format)      articles#update
              DELETE /articles/:id(.:format)      articles#destroy


c) Create a model for article


  • Generate RAILS model for Article

$ rails generate model Article title:string text:text
Running via Spring preloader in process 3657
      invoke  active_record
      create    db/migrate/20170317185317_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml



  • Checking migrate scripts automatically generated by RAILS

$ cat db/migrate/*_create_articles.rb 
class CreateArticles < ActiveRecord::Migration[5.0]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :text

      t.timestamps
    end
  end
end


cat app/models/article.rb
class Article < ApplicationRecord
  validates :title, presence: true, length: { minimum: 3 }
end


  • Run migrate scripts on environment (DEVELOPMENT)

$  rails db:migrate
== 20170317185317 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0092s
== 20170317185317 CreateArticles: migrated (0.0093s) ==========================



  • Checking on PostgreSQL databases databases created by scripts

$ psql -h 127.0.0.1 -d myrailsapppostgres_development -U root -W
myrailsapppostgres_development=> \l
               List of databases
             Name              |  Owner   
-------------------------------+----------
 myrailsapppostgres_development | root      ...
 myrailsapppostgres_test        | root      ...
          :                       :



  • Checking on PostgreSQL databases tables created by scripts

myrailsapppostgres_development=> \d
                List of relations
 Schema |         Name         |   Type   | Owner
--------+----------------------+----------+-------
 public | ar_internal_metadata | table    | root
 public | articles             | table    | root
 public | articles_id_seq      | sequence | root
 public | schema_migrations    | table    | root
(4 rows)



  • Checking on PostgreSQL databases table description created by scripts

myrailsapppostgres_development=> \d articles
                                     Table "public.articles"
   Column   |            Type             |                       Modifiers
------------+-----------------------------+-------------------------------------------------------
 id         | integer                     | not null default nextval('articles_id_seq'::regclass)
 title      | character varying           |
 text       | text                        |
 created_at | timestamp without time zone | not null
 updated_at | timestamp without time zone | not null
Indexes:
    "articles_pkey" PRIMARY KEY, btree (id)



d) Create controller for article and implement actions from CRUD capabilities

$ rails generate controller Articles
$ vim app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
end
$ vim app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def new       # new action
    @article = Article.new
  end

  def create    # create
    @article = Article.new(article_params)
    if @article.save
      redirect_to @article
    else
      render 'new'
    end
  end

  def show      # show
    @article = Article.find(params[:id])
  end

  def index     # list
    @articles = Article.all
  end

  def edit      # edit
    @article = Article.find(params[:id])
  end

  def update    # update
    @article = Article.find(params[:id])
    if @article.update(article_params)
      redirect_to @article
    else
      render 'edit'
    end
  end

  def destroy
    @article = Article.find(params[:id])
    @article.destroy
    redirect_to articles_path
  end

  private
    def article_params
      params.require(:article).permit(:title, :text)
    end

end



e) Create views for article and implement pages from CRUD capabilities: welcome index, new-create, show, list, edit and destroy


  • welcome#index: view for application Welcome 

$ vim app/views/welcome/index.html.erb
<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>
<%= link_to 'Articles', controller: 'articles' %>


  • new: view for new record

$ vim app/views/articles/new.html.erb
<h1>New Article</h1>

<%= form_for :article, url: articles_path do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>


  • show: view for show record

$ vim app/views/articles/show.html.erb
<h1>Show Article</h1>

<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

<%= link_to 'Back', articles_path %>


  • list: view for listing all records

$ vim app/views/articles/index.html.erb
<h1>Listing articles</h1>

<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.text %></td>
      <td><%= link_to 'Show', article_path(article) %></td>
      <td><%= link_to 'Edit', edit_article_path(article) %></td>
      <td><%= link_to 'Destroy', article_path(article),
              method: :delete,
              data: { confirm: 'Are you sure?' } %></td>
    </tr>
  <% end %>
</table>


  • edit: view for edit record

$ vim app/views/articles/edit.html.erb
<h1>Editing article</h1>

<%= form_for :article, url: article_path(@article), method: :patch do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>

<% end %>

<%= link_to 'Back', articles_path %>


f) Testing simple application CRUD




2.8. Adding some validation to simple RAILS application


  • Required fields and minimum limit of fields

$ vim app/models/article.rb
class Article < ApplicationRecord
  validates :title, presence: true, length: { minimum: 3 }
end



  • Capture new errors exceptions and show on top of page

$ vim app/views/articles/new.html.erb
     :
<%= form_for :article, url: articles_path  do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
     :


2.9. Using form to clean up duplications on view

a. Backup 'new' and 'edit' form

$ cp app/views/articles/new.html.erb  app/views/articles/new.html.erb.without_form
$ cp app/views/articles/edit.html.erb app/views/articles/edit.html.erb.without_form


b. Create template '_form' to be included by 'new' and 'edit'

$ vim app/views/articles/_form.html.erb
<%= form_for @article do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>

<% end %>


c. Change 'new' to include '_form'

$ vim app/views/articles/new.html.erb
<h1>New Article</h1>

<h1>New article</h1>

<%= render 'form' %>


<%= link_to 'Back', articles_path %>



d. Change 'edit' to include '_form'

$ vim app/views/articles/edit.html.erb
<h1>Editing article</h1>


<%= render 'form' %>


<%= link_to 'Back', articles_path %>



2.10. Adding second model detail of first master model

a. Create model comment detail of master article: one article has many comments

$  rails generate model Comment commenter:string body:text article:references
Running via Spring preloader in process 8667
      invoke  active_record
      create    db/migrate/20170318010912_create_comments.rb
      create    app/models/comment.rb
      invoke    test_unit
      create      test/models/comment_test.rb
      create      test/fixtures/comments.yml


b. Checking migrate scripts automatically generated by RAILS

$ cat db/migrate/*_create_comments.rb
$ cat app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :article
end
$ cat test/models/comment_test.rb
  :

$ cat test/fixtures/comments.yml
  :



c. Run migrate scripts on environment (DEVELOPMENT)

$  rails db:migrate
== 20170318010912 CreateComments: migrating ===================================
-- create_table(:comments)
   -> 0.1321s
== 20170318010912 CreateComments: migrated (0.1323s) ==========================


d. Associating models

$ vim app/models/article.rb
class Article < ApplicationRecord
  has_many :comments
  validates :title, presence: true, length: { minimum: 5 }
end


e. Adding routing for new model comments

$ vim config/routes.rb
Rails.application.routes.draw do
  get 'welcome/index'

  resources :articles do
    resources :comments
  end

  root 'welcome#index'

end


f. Generating a controller for detail new model Comment

$ rails generate controller Comments
$ cat app/controllers/comments_controller.rb # will be changed soon
class CommentsController < ApplicationController
end
$ ls -lad app/views/comments/
$ ls -la  test/controllers/comments_controller_test.rb
$ cat  app/helpers/comments_helper.rb
module CommentsHelper
end
$ cat app/assets/javascripts/comments.coffee 
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
$ cat app/assets/stylesheets/comments.scss
// Place all the styles related to the Comments controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/


g. Edit article view 'show' to let make a new details records of comments

$ vim app/views/articles/show.html.erb
<h1>Show Article</h1>

<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>Commenter:</strong>
    <%= comment.commenter %>
  </p>

  <p>
    <strong>Comment:</strong>
    <%= comment.body %>
  </p>
<% end %>

<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>


h. Edit comments controller 'show' to implement 'create' and 'destroy'

$ vim app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create(comment_params)
    redirect_to article_path(@article)
  end

  def destroy
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    @comment.destroy
    redirect_to article_path(@article)
  end
  
  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end
end

$ vim app/views/articles/show.html.erb
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>Commenter:</strong>
    <%= comment.commenter %>
  </p>

  <p>
    <strong>Comment:</strong>
    <%= comment.body %>
  </p>
<% end %>

<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>


i. Partial Comments to clean up 'show' with a template

$ cp app/views/articles/show.html.erb app/views/articles/show.html.erb.without_form
$ vim app/views/comments/_comment.html.erb
<p>
  <strong>Commenter:</strong>
  <%= comment.commenter %>
</p>

<p>
  <strong>Comment:</strong>
  <%= comment.body %>
</p>

<p>
  <%= link_to 'Destroy Comment', [comment.article, comment],
               method: :delete,
               data: { confirm: 'Are you sure?' } %>
</p>


j. Partial Form _form coments._form

$ vim app/views/comments/_form.html.erb
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>


k. Partial Form _form article.show

$ vim app/views/articles/show.html.erb
<h1>Show Article</h1>

<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

<h2>Comments</h2>
<%= render @article.comments %>

<h2>Add a comment:</h2>
<%= render 'comments/form' %>

<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>


l. Adding method 'create' and 'destroy' to controller Comments

$ vim app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create(comment_params)
    redirect_to article_path(@article)
  end

  def destroy
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    @comment.destroy
    redirect_to article_path(@article)
  end

  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end

end


m. Deleting associated Objects

$ vim app/models/article.rb
class Article < ApplicationRecord
  has_many :comments, dependent: :destroy
  validates :title, presence: true, length: { minimum: 3 }
end


3. References