Day 2 ~ 8:Scaffold なしでの掲示板作成

/
#cebu#rails

from Qiita:

使用環境

  • 仮想環境 OS: Ubuntu 18.04
  • Ruby:2.51
    • Rails:5.2.2

rails db:migrate

  • Railsドキュメントより
    • rails db:migrate を実行
    • schema_migrations テーブルを調べ、存在しなければ作成
    • db/migrate ディレクトリ内のすべてのマイグレーションファイルを調べる
    • データベースの現在のバージョンと異なるバージョンがあった場合、データベースに適応
    • schema_migrations テーブルの更新

3日目

scaffold を利用せずに App 作成をし、Scaffold の有難みを知る。

前準備

  1. rails s new qiita_routes -d MySQL
  2. Gemfile の miniracer コメントインして、bundle install
  3. Config/database.yml の password 情報編集
  4. rails db:create

前提:知識

ページ作成に必要なもの

  • view
    • 今日はしなかったので、今投稿には未記載
    • view の中身がブラウザに表示される内容
  • controller
    • ページ表示の際、controller を経由して、view をブラウザに返す
    • controller で設定した action は、controller と同じ名前の view フォルダの中から、action と同じ名前の html ファイルを探してブラウザに返す
  • routing
    • ブラウザと controller を繋ぐ

ページ表示の流れ

Routing => Controller => Model => View model はデータベース情報が必要なときだけ使用。

本段階

controllerを作成

undefined
1
#rails generate controller コントローラ名 (+アクション名)
2
rails generate controller Users

routingの設定:ブラウザとコントローラをつなぐ

config/routes.rb
1
Rails.application.routes.draw do
2
get 'users', action: :index, controller: 'users'
3
end
undefined
1
rails routes
2
3
# Prefix Verb URI Pattern
4
# Controller#Action
5
# users GET /users(.:format)   #追加された行
6
# users#index          #追加された行

controller:modelとviewをつなぐ

app/controllers/users_controller.rb
1
class UsersController < ApplicationController
2
def index
3
render plain: 'Hello'
4
end
5
end

無事に、ブラウザ上で Hello が表示された。

renderメソッド

上 controller 編集時に用いた、render メソッドは実際に画面に表示される内容を生成する。今回の render の plain オプションを指定すると、文字列を直接表示できる。 Rails の controller で render を省略すると、代わりに app/views/コントローラ名/アクション名.html.erb を用いる。 => controller 作成コマンドは rails g controller コントローラ名 アクション名

参照: Ruby on Rails でページを作成する仕組み by @np_misaki氏

  • Config : アプリケーションの設定情報を格納する
  • /routes.rb : ルーティングを設定する
  • /locales : 辞書ファイル(グローバル対応等)
  • /app : アプリケーション開発中にメインで使用するディレクトリ
  • /controllers..Controller クラスを格納する
  • /models : Model クラスを格納する
  • /views :View クラスを格納する

4日目

モデルを作成

  • model とは
    • データベースを操作する
    • app/models 下に配置される
    • テーブルごとに用意され、データの登録・取得・更新・削除などを行なう

model作成コマンド

undefined
1
# rails generate model モデル名 カラム名:データ型 カラム名:データ型 ...
2
rails generate model User name:string email:string sex:integer age:integer address:integer attendance:integer opinion:text
3
# string型は文字型、integer型は整数型

DBの操作

テーブルの作成をする

undefined
1
rails db:migrate

できたテーブルをMySQL側で確認してみる

undefined
1
-- mysql
2
USE scanashi0307_development;
3
-- Reading table information for completion of table and column names
4
-- You can turn off this feature to get a quicker startup with -A
5
6
-- Database changed
7
-- mysql> SHOW TABLES;
8
-- +------------------------------------+
9
-- | Tables_in_scanashi0307_development |
10
-- +------------------------------------+
11
-- | ar_internal_metadata |
12
-- | schema_migrations |
13
-- | users |
14
-- +------------------------------------+
15
-- 3 rows in set (0.00 sec)
16
17
-- usersテーブルが作成されたことが分かる。
undefined
1
SHOW CREATE TABLE users;
2
3
-- | users | CREATE TABLE `users` (
4
-- `id` bigint(20) NOT NULL AUTO_INCREMENT,
5
-- `name` varchar(255) DEFAULT NULL,
6
-- `email` varchar(255) DEFAULT NULL,
7
-- `sex` int(11) DEFAULT NULL,
8
-- `age` int(11) DEFAULT NULL,
9
-- `address` int(11) DEFAULT NULL,
10
-- `attendance` int(11) DEFAULT NULL,
11
-- `opinion` text,
12
-- `created_at` datetime NOT NULL,
13
-- `updated_at` datetime NOT NULL,
14
-- PRIMARY KEY (`id`)
15
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

rails g models で設定したカラム名が作成されているのがわかる。

データベースにfooさんのレコードを追加してみる

undefined
1
INSERT INTO `users` (`name`, `email`, `sex`, `age`, `address`, `attendance`, `opinion`, `created_at`, `updated_at`) VALUES ('foo', '[email protected]', 1, 23, 2, 0, 'foooo', '2017-04-04 04:44:44', '2018-04-04 04:44:44');
2
-- Query OK, 1 row affected (0.00 sec)

MySQLの中から、追加されているレコードを確認してみる

undefined
1
SELECT * FROM users;
2
-- +----+------+---------------+------+------+---------+------------+---------+---------------------+---------------------+
3
-- | id | name | email | sex | age | address | attendance | opinion | created_at | updated_at |
4
-- +----+------+---------------+------+------+---------+------------+---------+---------------------+---------------------+
5
-- | 1 | foo | [email protected] | 1 | 23 | 2 | 0 | foooo | 2017-04-04 04:44:44 | 2018-04-04 04:44:44 |
6
-- +----+------+---------------+------+------+---------+------------+---------+---------------------+---------------------+

rails console から新たにレコードを追加する

undefined
1
user = User.create(name: "taro", email: "[email protected]", sex: 0, address: 1, attendance: 1, opinion: 'nothing special')
2
3
#user.saveでDBに保存する
4
user.save
5
# => true

Rails Console上でレコード取得

undefined
1
User.all # get all users from record
2
User.all.last # get last added user from record
3
4
first_user = User.all.first # get all users and then get the first user
5
first_user.destroy # delete the first user
6
7
user = User.all.first
8
user.name = "ichitaro" # overwrite the name with 'ichitaro
9
user.save # save the data
10
11
User.all.count # count the number of all users
12
User.find_by(id:2) # get a user with id:2

controller

app/controllers/users_controller.rb
1
class UsersController < ApplicationController
2
def index
3
@users = User.all
4
end
5
end

view

app/view/index.html.erb
1
<body>
2
<h1>Users</h1>
3
<table>
4
<thead>
5
<tr>
6
<th>Name</th>
7
<th>Email</th>
8
<th>Sex</th>
9
<th>Age</th>
10
<th>Address</th>
11
<th>Attendance</th>
12
<th>Opinion</th>
13
<th colspan="3"></th>
14
</tr>
15
</thead>
16
17
<tbody>
18
<% @users.each do |user| %>
19
<tr>
20
<td><%= user.name %></td>
21
<td><%= user.email %></td>
22
<td><%= user.sex %></td>
23
<td><%= user.age %></td>
24
<td><%= user.address %></td>
25
<td><%= user.attendance %></td>
26
<td><%= user.opinion %></td>
27
</tr>
28
<% end %>
29
</tbody>
30
</table>
31
</body>
app/views/layouts/application.html.erb
1
<!DOCTYPE html>
2
<html>
3
<head>
4
# 割愛
5
</head>
6
<body>
7
<%= yield %>
8
</body>
9
</html>

ルーティングを変更

app/config/routes.erb
1
resources :users

rails routes 実行

undefined
1
# =>
2
# Prefix Verb URI Pattern Controller#Action
3
4
# users GET /users(.:format) users#index
5
# POST /users(.:format) users#create
6
# new_user GET /users/new(.:format) users#new
7
# edit_user GET /users/:id/edit(.:format) users#edit
8
# user GET /users/:id(.:format) users#show
9
# PATCH /users/:id(.:format) users#update
10
# PUT /users/:id(.:format) users#update
11
# DELETE /users/:id(.:format) users#destroy
12
# ...

次に上にある、「users GET /users(.:format) users#index」を実装 UserController の中に show アクションを作成

app/controllers/users_controller.rb
1
class UsersController < ApplicationController
2
def index
3
@users = User.all
4
end
5
# 下が追加したshowアクション
6
def show
7
end
8
end
app/views/users/index.html.erb
1
# user.nameのラインを下の様に変更
2
<td><%= link_to user.name, user_path(user.id) %></td>
3
# <% link_to ("A"."/B") %>
4
# 上はhtml上で <a href="/B">A</a>に変化する。

この時点で rails s で立ち上げると

showアクション

  • users_path は users#index へのリンク
  • new_user_path は users#new へのリンク
  • edit_user_path は users#edit へのリンク
  • user_path は users#show へのリンク
app/views/users/show.html.erb
1
<p id="notice"><%= notice %></p>
2
<p>
3
<strong>Name:</strong>
4
<%= @user.name %>
5
</p>
6
<p>
7
<strong>Email:</strong>
8
<%= @user.email %>
9
</p>
10
# 割愛
11
12
<%= link_to 'Edit', edit_user_path(@user) %> |
13
<%= link_to 'Back', users_path %>

show, edit アクションの定義

app/controllers/users_controller.rb
1
def show
2
@user = User.find params[:id]
3
end
4
5
def edit
6
@user = User.find(params[:id])
7
end
app/views/users/edit.html.erb
1
<%= form_with(model: @user, local: true) do |form| %>
2
<% if @user.errors.any? %>
3
<div id="error_explanation">
4
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this @user from being saved:</h2>
5
<ul>
6
<% @user.errors.full_messages.each do |message| %>
7
<li><%= message %></li>
8
<% end %>
9
</ul>
10
</div>
11
<% end %>
12
<div class="field">
13
<%= form.label :name %>
14
<%= form.text_field :name %>
15
</div>
16
<div class="field">
17
<%= form.label :email %>
18
<%= form.text_field :email %>
19
</div>
20
<div class="field">
21
<%= form.label :sex %>
22
<%= form.number_field :sex %>
23
</div>
24
# 割愛
25
<% end %>

追加:2日目を参考にし、表示を触ってみる

性別の値 0 or 1 を男性 or 女性で表示させる。

app/models/user.rb
1
class User < ApplicationRecord
2
enum sex: { male: 0 ,female: 1}
3
end

男性、女性で表示されるようになった。だが、edit ページは、テキスト入力のまま

ラジオボタンに変更

app/views/users/edit.html.erb
1
<div class="field">
2
<%= form.label :sex %>
3
<%= form.radio_button :sex, 'male' %>男性
4
<%= form.radio_button :sex, 'female' %>女性
5
</div>

同様に、年齢、住所、参加不参加もラジオボタンにしておく。

undefined
1
user = User.find_by(name:"foo") # get a user named 'foo'
2
user.age = 0 # rewrite the user's data about age with 0
3
user.save
4
User.find_by(name: "foo") # confirm
5
# =>
6
# <User id: 1, name: "foo", email: "[email protected]", sex: "女性", age: 0, address: "日本以外", attendance: "参加", opinion: "foooo", created_at: "2017-04-04 04:44:44", updated_at: "2019-03-08 00:07:47"

年齢のラジオボタンを追加


8日目

users_controller

app/controllers/uupdate.rb
1
def update
2
@user = User.find params[:id]
3
if @user.update(params.require(:user).permit(:name, :email, :sex, :age, :address, :attendance, :opinion))
4
respond_to do |format|
5
format.html { redirect_to @user, notice: 'User was successfully updated.' }
6
end
7
else
8
respond_to do |format|
9
format.html { render :edit }
10
end
11
end
12
end
13
14
def destroy
15
@user = User.find params[:id]
16
@user.destroy
17
respond_to do |format|
18
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
19
end
20
end
21
22
def new
23
@user = User.new
24
end

indexページからのdestroyへのリンク作成

app/views/users/index.html.erb
1
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>

newページ編集

app/views/users/new.html.erb
1
<h1>New User</h1>
2
<%= form_with(model: @user, local: true) do |form| %>
3
<% if @user.errors.any? %>
4
<div id="error_explanation">
5
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
6
<ul>
7
<% @user.errors.full_messages.each do |message| %>
8
<li><%= message %></li>
9
<% end %>
10
</ul>
11
</div>
12
<% end %>
13
<div class="field">
14
<%= form.label :name %>
15
<%= form.text_field :name %>
16
</div>
17
<div class="field">
18
<%= form.label :email %>
19
<%= form.text_field :email %>
20
</div>
21
# 割愛
22
23
<% end %>
24
<%= link_to 'Back', users_path %>

indexからnewへのリンク作成

app/views/users/index.html.erb
1
<%= link_to 'New User', new_user_path %>

createアクション定義

app/controllers/users_controller.rb
1
def create
2
@user = User.new(params.require(:user).permit(:name, :email, :sex, :age, :address, :attendance, :opinion))
3
if @user.save
4
respond_to do |format|
5
format.html { redirect_to @user, notice: 'User was successfully updated.' }
6
end
7
else
8
respond_to do |format|
9
format.html { render :edit }
10
end
11
end
12
end

リファクタリング

wikipedia

リファクタリング (refactoring) とは、コンピュータプログラミングにおいて、プログラムの外部から見た動作を変えずにソースコードの内部構造を整理すること

createアクションとupdateアクションの共通化

2 アクションに下の共通箇所がある

app/controllers/users_controller.rb
1
@user = User.new(params.require(:user).permit(:name, :email, :sex, :age, :address, :attendance, :opinion))

リファクタリング後

app/controllers/users_controller.rb
1
def create
2
@user = User.new(user_params)
3
if @user.save
4
respond_to do |format|
5
format.html { redirect_to @user, notice: 'User was successfully updated.' }
6
end
7
else
8
respond_to do |format|
9
format.html { render :edit }
10
end
11
end
12
end
13
14
def update
15
@user = User.find params[:id]
16
if @user.update(user_params)
17
respond_to do |format|
18
format.html { redirect_to @user, notice: 'User was successfully updated.' }
19
end
20
else
21
respond_to do |format|
22
format.html { render :edit }
23
end
24
end
25
end
26
27
private
28
29
def user_params
30
params.require(:user).permit(:name, :email, :sex, :age, :address, :attendance, :opinion)
31
end
32
end

show. edit. updata, destroyの共通化

app/controllers/users_controller.rb
1
# 共通している部分
2
@user = User.find params[:id]
3
4
# 共通化した結果
5
# set_user追加
6
def set_user
7
@user = User.find params[:id]
8
end
9
10
# before_action追加
11
# show, edit, update, destroyアクションの前に、必ず実行の意
12
class UsersController < ApplicationController
13
before_action :set_user, only: [:show, :edit, :update, :destroy]

アクションのリファクタリング後(全体)

app/controllers/users_controller.rb
1
class UsersController < ApplicationController
2
before_action :set_user, only: [:show, :edit, :update, :destroy]
3
4
def index
5
@users = User.all
6
end
7
def show; end
8
def edit; end
9
def update
10
if @user.update(user_params)
11
respond_to do |format|
12
format.html { redirect_to @user, notice: 'User was successfully updated.' }
13
end
14
else
15
respond_to do |format|
16
format.html { render :edit }
17
end
18
end
19
end
20
def destroy
21
@user.destroy
22
respond_to do |format|
23
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
24
end
25
end
26
def new
27
@user = User.new
28
end
29
def create
30
@user = User.new(user_params)
31
if @user.save
32
respond_to do |format|
33
format.html { redirect_to @user, notice: 'User was successfully updated.' }
34
end
35
else
36
respond_to do |format|
37
format.html { render :edit }
38
end
39
end
40
end
41
42
private
43
def set_user
44
@user = User.find params[:id]
45
end
46
def user_params
47
params.require(:user).permit(:name, :email, :sex, :age, :address, :attendance, :opinion)
48
end
49
end