目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina
前提
下記実装済み。
・Slim導入
・Bootstrap3導入
・ログイン機能実装
投稿機能を実装
1.モデル
ターミナル
$ rails g model Book user_id:integer title:string body:text
ターミナル
$ rails db:migrate
schema.rb
ActiveRecord::Schema.define(version: 2020_04_05_115005) do
create_table "books", force: :cascade do |t|
t.integer "user_id"
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
user.rb
class User < ApplicationRecord
has_many :books, dependent: :destroy
end
book.rb
class Book < ApplicationRecord
belongs_to :user
end
2.コントローラー
ターミナル
$ rails g controller books index
books_controll.rb
class BooksController < ApplicationController
def create
@book = Book.new(book_params)
@book.user_id = current_user.id
if @book.save
redirect_to book
else
@books = Book.all
render 'index'
end
end
def index
@book = Book.new
@books = Book.all
end
def destroy
@books.destroy
redirect_to books_path
end
private
def book_params
params.require(:book).permit(:title, :body)
end
end
3.ルーティング
routes.rb
Rails.application.routes.draw do
resources :books
end
4.ビュー
books/index.html.slim
.row
.col-xs-3
= form_with model: @book, local: true do |f|
= f.label :title, 'タイトル'
br
= f.text_field :title, class:'form-control'
br
= f.label :body, '本文'
br
= f.text_area :body, class:'form-control'
br
= f.submit '投稿', class: 'btn btn-primary btn-block'
.col-xs-9
table.table
thead
tr
th
| 投稿者
th
| タイトル
th
| 本文
th
tbody.new_book
- @books.each do |book|
tr
td
= link_to book.user do
= book.user.name
td
= link_to book.title, book_path(book)
td
= book.body
td
-if book.user == current_user
= link_to '削除', book, method: :delete, data: { confirm: '本当に削除してもよろしいですか?' }, class: 'btn-sm btn-danger'
非同期機能を実装
1.jQueryを導入
Gemfile
gem 'jquery-rails'
ターミナル
$ bundle
application.js
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery // turbolinksより下に記述
//= require_tree .
2.createアクションを編集
books.controller.rb
class BooksController < ApplicationController
def create
@book = Book.new(book_params)
@book.user_id = current_user.id
unless @book.save
@books = Book.all
render 'index'
end
end
end
3.ビューを編集
books/index.html.slim
.row
.col-xs-3
/ 「local: true」から「remote: true」に変更
= form_with model: @book, remote: true do |f|
= f.label :title, 'タイトル'
br
/ クラスを付与
= f.text_field :title, class:'form-control book-title'
br
= f.label :body, '本文'
br
/ クラスを付与
= f.text_area :body, class:'form-control book-body'
br
= f.submit '投稿', class: 'btn btn-primary btn-block'
.col-xs-9
table.table
thead
tr
th
| 投稿者
th
| タイトル
th
| 本文
th
/ 投稿一覧の親要素にクラスを付与
tbody.new_book
- @books.each do |book|
/ 投稿一覧をパーシャル化
= render 'books', book: book
books/_books.html.slim
/ 各投稿にIDを付与
tr id='book-#{ book.id }'
td
= link_to book.user do
= book.user.name
td
= link_to book.title, book_path(book)
td
= book.body
td
-if book.user == current_user
/ 「remote: true」を付与
= link_to '削除', book, method: :delete, data: { confirm: '本当に削除してもよろしいですか?' }, remote: true, class: 'btn-sm btn-danger'
「remote: true」
を付与する事で、JavaScriptファイルを呼び出せる様になる。
※ 非同期投稿を行うときは必ず「form_with」
を使用する。
5.JavaScriptファイルを作成
books/create.js.erb
$(".book-title").val('');
$(".book-body").val('');
$(".new_book").append("<%= j(render 'books', book: @book) %>");
$(".book-title").val('');
$(".book-body").val('');
➡︎ 入力フォームを空にする
$(".new_book")
➡︎ 「4」で付けたクラスを指定
.append("<%= j(render 'books', book: @book) %>");
➡︎ 既存投稿の後尾に新規投稿を表示
※ 先頭に表示したい場合は「prepend」を使用する。
books/destroy.js.erb
$("#book-<%= @book.id %>").remove();
$("#book-<%= @book.id %>")
➡︎ 「4」で付与したIDを指定
.remove();
➡︎ 表示を消す