terça-feira, 23 de maio de 2017

RAILS Faq HowTo Reference Sample Using scopes on Rails to Filter index page and Re-display filter inputs

1. Introduction

This post gathers information about FAQ-Frequently Asked Question, How To, technical document references and samples about these RAILS topics.

  • Using scopes on Rails to Filter index page and Re-display filter inputs


2. FAQ, HOWTO, REFERENCES, SAMPLES, etc

2.1. Create model scopes for each filter condition

# vim app/models/cluster_config.rb
class ClusterConfig < ApplicationRecord
  include Filterable
  scope :cluster_config, -> (id) { where id: id}
  scope :cluster_status, -> (cluster_status_id) { where cluster_status_id: cluster_status_id}
  scope :cluster_environment_type, -> (cluster_environment_type_id) { where cluster_environment_type_id: cluster_environment_type_id}
  scope :cluster_content_type, -> (cluster_content_type_id) { where cluster_content_type_id: cluster_content_type_id}
end


2.2. Implement generic filter on model concerns

# vim app/models/concerns/filterable.rb
module Filterable
  extend ActiveSupport::Concern
  module ClassMethods
    def filter(filtering_params)
      results = self.where(nil)
      filtering_params.each do |key, value|
        results = results.public_send(key, value) if value.present?
      end
      results
    end
  end
end


2.3. Implement filter on index controller

# vim app/controllers/cluster_configs_controller.rb
class ClusterConfigsController < ApplicationController
  before_action :set_cluster_config, only: [:show, :edit, :update, :destroy]
    :
  def index
    @cluster_configs = ClusterConfig.filter(params.slice(:cluster_config, :cluster_status, :cluster_environment_type, :cluster_content_type)).paginate(page: params[:page], per_page: 20)
  end
    :
  private
    def set_cluster_config
      @cluster_config = ClusterConfig.find(params[:id])
    end
    :
    def cluster_config_params
      params.require(:cluster_config).permit(:cluster_status_id, :cluster_environment_type_id, :cluster_content_type_id, :url_rest_service, :db_host, :db_port, :db_name, :dt_created, :dt_delivered, :obs)
    end
end


2.4. Implement filter on index viewer

# vim app/views/cluster_configs/index.html.erb
<h3>Filter by:</h3>
<%= form_for cluster_configs_path do %>
<div>
  Id: <%= text_field_tag 'cluster_config', '' %>
  Status Massa: <%= select("cluster_status", "cluster_status", ClusterStatus.all.map {|a| [a.cluster_status, a.id] }, { include_blank: true }) %>
  Environment Type: <%= select("cluster_environment_type", "cluster_environment_type", ClusterEnvironmentType.all.map {|a| [a.cluster_environment_type, a.id] }, { include_blank: true }) %>
  Content Type: <%= select("cluster_content_type", "cluster_content_type", ClusterContentType.all.map {|a| [a.cluster_content_type, a.id] }, { include_blank: true }) %>
  <br><br>
  <%= submit_tag 'Filter' %>
  <br><br>
</div>
<% end %>


2.5. Erro

Error when "Filter" submit button

ActionController::ParameterMissing in ClusterConfigsController#create
  param is missing or the value is empty: cluster_config
  Extracted source (around line #73):
    72: def cluster_config_params
    73:    params.require(:cluster_config).permit(:cluster_status_id, :cluster_environment_type_id, :cluster_content_type_id, :url_rest_service, :db_host, :db_port, :db_name, :dt_created, :dt_delivered, :obs)
    74: end
Request
Parameters:
{"utf8"=>"✓",
 "authenticity_token"=>"BF22bYvS/UXHOgeLLXeindCqWeXj41w/MxPE93cNoLBnaGwMhdC+HOuvvc6TCoteFHTsyyCZsoxO2j0kA4q/yA==",
 "cluster_config"=>"",
 "cluster_status"=>{"cluster_status"=>""},
 "cluster_environment_type"=>{"cluster_environment_type"=>""},
 "cluster_content_type"=>{"cluster_content_type"=>""},
 "commit"=>"Filter"}


3. References


segunda-feira, 22 de maio de 2017

RAILS Faq HowTo Reference Sample Bootstrap Navbar with RAILS

1. Introduction

This post gathers information about FAQ-Frequently Asked Question, How To, technical document references and samples about these RAILS topics.
* Bootstrap Navbar with RAILS


2. FAQ, HOWTO, REFERENCES, SAMPLES, etc

2.1. Bootstrap Navbar with RAILS

a) HOWTO

a.1) Setp #1: Find Gemfile configuration


  •  Open rubygems and search for "bootstrap-sass"

https://rubygems.org/
[ bootstrap-sass ] | Search

You should be redirect to https://rubygems.org/gems/bootstrap-sass
Copy gemfile command on the left corner, something like "gem 'bootstrap-sass', '~> 3.3', '>= 3.3.7'"
Edit ./Gemfile on your project root and add bootstrap-sass


a.2) Setp #2: Configure your project Gemfile

$ cd ~/myrailsproject
$ vim Gemfile
  :
# Josemarsilva - 2017-05-19 - http://www.rubydoc.info/gems/bootstrap-sass/3.3.7#a-ruby-on-rails
gem 'bootstrap-sass', '~> 3.3', '>= 3.3.7'
gem 'sass-rails', '~> 5.0'


a.3) Setp #3: Configure your project Gemfile and 

# bundle install


a.4) Step #4: Hide default "application.css" and configure "application.scss"

# mv  app/assets/stylesheets/application.css app/assets/stylesheets/application.css.hidden-by-bootstrap
# vim app/assets/stylesheets/application.scss
+----------------------------------------------------------------------------------------+
|// "bootstrap-sprockets" must be imported before "bootstrap" and "bootstrap/variables"  |
|$icon-font-path: "bootstrap-sass/assets/fonts/bootstrap/";                              |
|@import "bootstrap-sprockets";                                                          |
|@import "bootstrap";                                                                    |
+----------------------------------------------------------------------------------------+


a.5) Step #5: configure "application.js"

# vim app/assets/javascripts/application.js
+----------------------------------------------------------------------------------------+
|// JosemarSilva 2017-05-19 http://www.rubydoc.info/gems/bootstrap-sass/3.3.7            |
|//= require bootstrap                                                                   |
|//= require jquery                                                                      |
|//= require jquery_ujs                                                                  |
|//= require turbolinks                                                                  |
|//= require bootstrap-sprockets                                                         |
|//= require_tree .                                                                      |
+----------------------------------------------------------------------------------------+


a.6) Step #6: configure "app/views/layouts/application.html.erb"

# vim app/views/layouts/application.html.erb
+-------------------------------------------------------------------------------------------------+
|<!DOCTYPE html>                                                                                  |
|<html>                                                                                           |
|  <head>                                                                                         |
|    :                                                                                            |
|    <%= csrf_meta_tags %>                                                                        |
|    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %> |
|    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>               |
|    :                                                                                            |
|  </head>                                                                                        |
|    :                                                                                            |
|  <body>                                                                                         |
|    :                                                                                            |
|    <%= render '/staticpages/header' %>                                                          |
|    :                                                                                            |
|    <div class="container">                                                                      |
|      <%= yield %>                                                                               |
|    </div>                                                                                       |
|    :                                                                                            |
|  </body>                                                                                        |
|</html>                                                                                          |
+-------------------------------------------------------------------------------------------------+



a.7) Step #7: configure Navbar on header part template using bootstrap


  • Open Bootstrap Navbar documentation and copy example

http://getbootstrap.com/components/#navbar



  • Paste example into '_header.html.erb' part

# vim app/views/staticpages/_header.html.erb
+-------------------------------------------------------------------------------------------------+
| <nav class="navbar navbar-default">                                                             |
|  <div class="container-fluid">                                                                  |
|    <!-- Brand and toggle get grouped for better mobile display -->                              |
|    <div class="navbar-header">                                                                  |
|       :                                                                                         |
|      <ul class="nav navbar-nav navbar-right">                                                   |
|       :                                                                                         |
|      </ul>                                                                                      |
|    </div><!-- /.navbar-collapse -->                                                             |
|  </div><!-- /.container-fluid -->                                                               |
|</nav>                                                                                           |
+-------------------------------------------------------------------------------------------------+



b) REFERENCES





quinta-feira, 13 de abril de 2017

RAILS Faq HowTo Reference Sample Paginate index result and Lookup Table - Foreign Key

1. Introduction

This post gathers information about FAQ-Frequently Asked Question, How To, technical document references and samples about RAILS.

  • Paginating index result in Rails
  • Lookup Table, Foreign Key, 


2. FAQ, HOWTO, REFERENCES, SAMPLES, etc

2.1. Paginating in RAILS

The will_paginating gem modifies Collection of ActiveRecord to Display Page Links for Querying records. See also:

a) HOWTO


  • Step#1: add gem will_paginating
# vim Gemfile
  :
gem 'will_paginate', '~> 3.1.0'
  :


  • Step#2: bundle install
# bundle install


  • Step#3: Creating MVC for Product and custom controller for paginating each 5 records for page
# rails generate scaffold Product name price:decimal quantity:integer
# vim app/controllers/products_controller.rb
class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  def index
     @products = Product.all.paginate(page: params[:page], per_page: 5)
  end
   :


  • Step#4: Custom index view to paginate
#  vim app/views/products/index.html.erb
   :
</table>
<%= will_paginate @products %>
<br>
   :


  • Step#5: Custom CSS stylesheets
# vim app/assets/stylesheets/products.scss
.pagination {
  .previous_page { background:#7777ff; color:white }
  .previous_page.disabled { background: white; color: #777 }
  .current { background: yellow }
  .next_page { background: #7777ff; color: white }
  .next_page.disabled { background: white; color: #777 }
}


  • Step#6: Making will_paginate prettier# 


2.2. ActiveRecord Association, Reference, Lookup Table, Foreign Key

This post shows how to create 2 models, where a model referencing another model, on index.html viewer shows attributes from referenced model.

a) HOWTO

  • Step#1: Generate 2 models
# rails generate scaffold Author name:string
# rails generate scaffold Book   title:string publishedAt:date author:references


  • Step#2: Let's check 2 models created and association
cat app/models/author.rb
class Author < ApplicationRecord
end
# cat app/models/book.rb
class Book < ApplicationRecord
  belongs_to :author
end


  • Step#3: Let's see how books are listed on http:// ... /books. As you can see, author is shown as internal object identification. It's not much pretty, isn't it?
# vim app/views/books/index.html.erb
                   :
        <td><%= book.title %></td>
        <td><%= book.publishedAt %></td>
        <td><%= book.author %></td>
        <td><%= book.author.name %></td>

        <td><%= link_to 'Show', book %></td>
                   :

Books
Title Publishedat Author
Titulo 2017-04-14 #<Author:0x007ff9681cd4f0> Show Edit Destroy
New Book

  • Step#4: Adjust app/views/books/index.html.rb to show author name insted of internal object identification

vim app/views/books/index.html.erb
                   :
        <td><%= book.title %></td>
        <td><%= book.publishedAt %></td>
        <td><%= book.author.name %></td>
        <td><%= book.author.name %></td>

        <td><%= link_to 'Show', book %></td>
                   :

Books
Title Publishedat Author
Titulo 2017-04-14 Machado de Assis Show Edit Destroy
New Book



  • Step#5: Adjust app/views/books/show.html.rb to show author name insted of internal object identification



vim app/views/books/show.html.erb
                   :
<p>
  <strong>Author:</strong>
  <%= @book.author.name %>
</p>
                   :

Books
Title: Titulo
Publishedat: 2017-04-14
Author: Machado de Assis
Edit | Back

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