Ruby on Rails でちゃんとTodoアプリを作ろう

Ruby on Rails でちゃんと Todo アプリを作ってみます。
要件は、以下の 2 つです。

  • 認証できること。(devise gem を使用)
  • ユーザーに紐付いた ToDo を登録できる。
  • CSS ライブラリを普段使ってこなかったものを使う。
  • Git を使う。

新しい職場で、Ruby と Ruby on Rails の基礎(erb をちゃんと使う、MVC をしっかり構築する)を固めたほうがいいと教えてくれた人がいた。
素直なので、その通りやってみます。

では本編。

目次

参考

構築

github にとりあえず素のアプリを登録

いつも通り、どこかのディレクトリでrails new [アプリ名]から始める。
以下実行内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>rails new ToDoApp
>cd ToDoApp
rails server
# ここまでで一旦動作確認
ctrl+c

# github に登録
>git init
>git add .
>git commit

# コンソールから離れてgithub でリポジトリを作成する作業を一旦行う

# コンソールの作業を再開
>git remote add origin git@github.com:Octo8080/Rails-App-Sample.git
>git push -u origin master

# これで素のアプリをgithubに公開できた。

以上の操作で、素のアプリを github に公開できた。

ToDo のモデル、コントローラ、ビューを作ろう

Todo モデル作成

Todo モデルとデータベース、テーブル、コントローラを作る。
Todo モデルは、string 型の Title カラムと text 型の Detail カラムを持つとする。

1
2
3
4
# モデル作成
>rails db:create
>rails generate model Todo Title:string Detail:text
>rails db:migrate

Todos コントローラ作成

1
2
# コントローラー作成
>rails generate controller Todos

\ToDoApp\app\controllers\todos_controller.rb を編集。

\ToDoApp\app\controllers\todos_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class TodosController < ApplicationController
before_action :set_todo, only: [:show, :edit, :update, :destroy]

def index
puts '[index]'
@todos = Todo.all
end

def show
puts `[show]`
end

def new
puts `[new]`
@todo = Todo.new()
end

def create
puts `[create]`
@todo = Todo.new(todo_params)

respond_to do |format|
if @todo.save()
format.html {redirect_to @todo, notice: 'User was successfully created.'}
else
format.html {render :new}
end
end
end

def edit
puts `[edit]`
end

def update
puts `[update]`

respond_to do |format|
if @todo.update(todo_params)
format.html { redirect_to @todo, notice: 'User was successfully updated.' }
else
format.html { render :edit }
end
end
end

def destroy
puts `[destroy]`
@todo.destroy

respond_to do |format|
format.html { redirect_to todos_url, notice: 'User was successfully destroyed.' }
end
end

private
def set_todo
puts '[set_todo]'
@todo = Todo.find(params[:id])
end

def todo_params
params.require(:todo).permit(:Title,:Detail)
end
end

ルーティング設定

今回は、resources を利用しないで作りますが、
内容は resources を使用した別のアプリのrails routesの結果を参考にします。
\ToDoApp\config\routes.rb を編集。

\ToDoApp\config\routes.rb
1
2
3
4
5
6
7
8
9
10
Rails.application.routes.draw do
get 'todos', to: 'todos#index'
post 'todos', to: 'todos#create'
get 'todos/new', to: 'todos#new',as: 'new_todo'
get 'todos/:id/edit', to: 'todos#edit',as: 'edit_todo'
get 'todos/:id', to: 'todos#show',as: 'todo'
patch 'todos/:id', to: 'todos#update'
put 'todos/:id', to: 'todos#update'
delete 'todos/:id', to: 'todos#destroy'
end

todo モデル用ビューを作成

\ToDoApp\app\views\todos 以下にビューを作成します。
別のアプリでの作成物を参考に作成するのは以下の 5 つのファイルです。

  • _form.html.erb
  • index.html.erb
  • show.html.erb
  • new.html.erb
  • edit.html.erb
\ToDoApp\app\views\todos_form.html.erb
\ToDoApp\app\views\todos_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%= form_with(model: todo,local:true) do |form|%> <% puts "_form"%> <% if
todo.errors.any? %> <% puts "[ERR]"%>
<div id="error_explanation">
<h2>
<%= pluralize(todo.errors.count, "error") %> prohibited this user from being
saved:
</h2>

<ul>
<% todo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="field"><%= form.label :Title %> <%= form.text_field :Title %></div>

<div class="field">
<%= form.label :Diteil %> <%= form.text_field :Detail %>
</div>

<div class="actions"><%= form.submit %></div>

<% end %>
\ToDoApp\app\views\todos\index.html.erb
\ToDoApp\app\views\todos\index.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
<thead>
<tr>
<th>Todo</th>
<th colspan="3"></th>
</tr>
</thead>

<tbody>
<% @todos.each do |todo| %>
<tr>
<td><%= todo.Title %></td>
<td><%= link_to 'Show', todo %></td>
<td><%= link_to 'Edit', edit_todo_path(todo.id) %></td>
<td>
<%= link_to 'Destroy', todo, method: :delete, data: { confirm: 'Are you
sure?' } %>
</td>
</tr>
<% end %>
</tbody>
</table>

<br />

<%= link_to 'New Todo', new_todo_path %>
\ToDoApp\app\views\todos\show.html.erb
\ToDoApp\app\views\todos\show.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<p id="notice"><%= notice %></p>

<p>
<strong>ToDo:</strong>
<table>
<tbody>
<tr><td>Title</td><td>=><%= @todo.Title %></td></tr>
<tr><td>Detail</td><td>=><%= @todo.Detail %></td></tr>
</tbody>
</table>
</p>

<%= link_to 'Edit', edit_todo_path(@todo) %> |
<%= link_to 'Back', todos_path %>
\ToDoApp\app\views\todos\new.html.erb
\ToDoApp\app\views\todos\new.html.erb
1
2
3
<h1>New Todo</h1>

<%= render 'form', todo: @todo %> <%= link_to 'Back', todos_path %>
\ToDoApp\app\views\todos\edit.html.erb
\ToDoApp\app\views\todos\edit.html.erb
1
2
3
4
<h1>Editing ToDo</h1>

<%= render 'form', todo: @todo %> <%= link_to 'Show', @todo %> | <%= link_to
'Back', todos_path %>

以上で一度動作確認。
scafford で Todo モデルを作成したときと同じ動作ができていることを確認する。

Devise gem で認証用のユーザーを作成

Devise gem  インストール

gemfile 末尾にgem 'devise'を書き加えて以下の操作を実行。

1
2
>bundle install
>rails generate devise:install

インストール時のメッセージに基づき設定を行う。

Devise gem 設定 1

\ToDoApp\config\environments\development.rb を編集。
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }を追記。

\ToDoApp\config\environments\development.rb
1
2
3
4
5
Rails.application.configure do
#~省略~
#末尾に以下を追加
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end

Devise gem 設定 2

\ToDoApp\config\routes.rb を編集。
root to: "todos#index"を追記。

\ToDoApp\config\routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
Rails.application.routes.draw do

get 'todos', to: 'todos#index'
post 'todos', to: 'todos#create'
get 'todos/new', to: 'todos#new',as: 'new_todo'
get 'todos/:id/edit', to: 'todos#edit',as: 'edit_todo'
get 'todos/:id', to: 'todos#show',as: 'todo'
patch 'todos/:id', to: 'todos#update'
put 'todos/:id', to: 'todos#update'
delete 'todos/:id', to: 'todos#destroy'

root to: "todos#index"
end

Devise gem 設定 3

\ToDoApp\app\views\layouts\application.html.erb を編集。
以下を追記する。

1
2
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

追記後の\ToDoApp\app\views\layouts\application.html.erb は以下の通り。

\ToDoApp\app\views\layouts\application.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<title>ToDoApp</title>
<%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag
'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%=
javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>

Devise gem でのモデル作成とマイグレーション、ビュー作成

以下コマンドを実行。

1
2
3
>rails generate devise User
>rails db:migrate
>rails g devise:views

Todo コントローラでログインの検証を追加

\ToDoApp\app\controllers\todos_controller.rb を編集。
Devise gem が提供するbefore_action :authenticate_user!を追記。

\ToDoApp\app\controllers\todos_controller.rb
1
2
3
4
class TodosController < ApplicationController
before_action :authenticate_user!
before_action :set_todo, only: [:show, :edit, :update, :destroy]
# 以下省略

以上で再度動作確認。
devise gem での認証画面、認証操作ができることを確認する。

ログオフボタンの設置

配置は後で再度検討するものとして、一度動作としてログオフできるようにする。
\ToDoApp\app\views\layouts\application.html.erb を編集。
以下の内容を書き換える。

1
2
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

書き換え後の内容は以下の通り。

1
2
3
4
5
6
7
<% if user_signed_in? %>
LogOnUser:<%= current_user.email %>
<%= link_to 'SignOut', destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to 'SingUp', new_user_registration_path %>
<%= link_to 'SignIn', new_user_session_path %>
<% end %>

書き換えが終わった、\ToDoApp\app\views\layouts\application.html.erb となる。

\ToDoApp\app\views\layouts\application.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<title>ToDoApp</title>
<%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag
'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%=
javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

<body>
<% if user_signed_in? %> LogOnUser:<%= current_user.email %> <%= link_to
'SignOut', destroy_user_session_path, method: :delete %> <% else %> <%=
link_to 'SingUp', new_user_registration_path %> <%= link_to 'SignIn',
new_user_session_path %> <% end %> <%= yield %>
</body>
</html>

以上で再度動作確認。
ログオフ、ログインができることを確認する。

一旦ここで github にコミットしておく。

以下の通り、実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 追加、書き換えがあったファイルを表示
>git status

# git add したときの確認
>git add -n

# git に管理されてるファイルで、書き換えがあったものをaddする。
>git add -u

# ファイルも増えたので、すべてaddoした
>git add .

# 変更に Deviseを追加 とコメントをつけてコミット
>git commit -m 'Deviseを追加'

# githubにプッシュ
>git push -u origin master

# コミット履歴を確認する。'Deviseを追加'とコメントを付けたコミットが確認できる。
>git log
commit [------------------乱数------------------] (HEAD -> master, origin/master)
Author: githubアカウント名 <メールアドレス>
Date: Mon Oct 28 00:19:43 2019 +0900

'Deviseを追加'

commit [------------------乱数------------------]
Author: githubアカウント名 <メールアドレス>
Date: Sun Oct 27 19:21:55 2019 +0900

first commit

User モデルと、Todo モデルの関連付け

マイグレーションの作成

以下コマンドを実行。

1
>rails generate migration AddColumnToTodo User:references

\ToDoApp\db\migrate[数字列]_add_column_to_todo.rb が作成される。

\ToDoApp\db\migrate[数字列]_add_column_to_todo.rb
1
2
3
4
5
class AddColumnToTodo < ActiveRecord::Migration[5.2]
def change
add_reference :todos, :User, foreign_key: true
end
end

マイグレーション実行。

1
>rails db:migrate

モデル修正

\ToDoApp\app\models\user.rb にhas_many :todos, dependent: :destroyを追記。
追記したものが以下の通り。

\ToDoApp\app\models\user.rb
1
2
3
4
5
6
7
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :todos, dependent: :destroy
end

\ToDoApp\app\models\todo.rb にbelongs_to :userを追記。
追記したものが以下の通り。

\ToDoApp\app\models\todo.rb
1
2
3
class Todo < ApplicationRecord
belongs_to :user,optional: true
end

コントローラ、ビューの追加

user がログインしてからの、画面となる。
コントローラとビューを作成します。

1
>rails generate controller Users index

\ToDoApp\app\controllers\users_controller.rb を修正。

1
2
3
4
5
6
7
8
class UsersController < ApplicationController
before_action :authenticate_user!, only: [ :show]
def index
if current_user.id!=nil
@user = User.find(current_user.id)
end
end
end

\ToDoApp\app\views\users\index.html.erb を修正。

1
<h1>INDEX</h1>

ルーティング修正

\ToDoApp\config\routes.rb を修正。
root to: "todos#index"を追記。

\ToDoApp\config\routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Rails.application.routes.draw do
devise_for :users

get 'users', to: 'users#index'

get 'todos', to: 'todos#index'
post 'todos', to: 'todos#create'
get 'todos/new', to: 'todos#new',as: 'new_todo'
get 'todos/:id/edit', to: 'todos#edit',as: 'edit_todo'
get 'todos/:id', to: 'todos#show',as: 'todo'
patch 'todos/:id', to: 'todos#update'
put 'todos/:id', to: 'todos#update'
delete 'todos/:id', to: 'todos#destroy'

root to: "users#index"

end

以上で再度動作確認。
user/index.erb と user/show.erb が動作していることを確認する。

todos コントローラ修正

\ToDoApp\app\controllers\todos_controller.rb の create アクションを修正。
@todo.User_id = current_user.idを追記。

\ToDoApp\app\controllers\todos_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

def create
puts `[create]`
@todo = Todo.new(todo_params)
# ログインユーザーのIDを挿入
@todo.User_id = current_user.id

respond_to do |format|
if @todo.save()
format.html {redirect_to @todo, notice: 'User was successfully created.'}
else
format.html {render :new}
end
end
end

users\index.html.erb を修正

\ToDoApp\app\views\users\index.html.erb を修正。
@user が持っている todos プロパティを表示する。
内容は、\ToDoApp\app\views\todos\index.html.erb を真似する。

\ToDoApp\app\views\users\index.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<h1>Index</h1>
<% if @user %>
<p>email:<%= @user.email %></p>
<p>ID:<%= @user.id %></p>

<table>
<thead>
<tr>
<th>Todo</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @user.todos.each do |todo| %>
<tr>
<td><%= todo.Title %></td>
<td><%= link_to 'Show', todo %></td>
<td><%= link_to 'Edit', edit_todo_path(todo.id) %></td>
<td>
<%= link_to 'Destroy', todo, method: :delete, data: { confirm: 'Are you
sure?' } %>
</td>
</tr>
<% end %>
</tbody>
</table>

<%= link_to 'New Todo', new_todo_path %> <%end%>

todos\edit.html.erb の修正

\ToDoApp\app\views\todos\edit.html.erb を以下の通り変更する。
Back のリンクをroot_pathに変更する。

\ToDoApp\app\views\todos\edit.html.erb
1
2
3
4
<h1>Editing ToDo</h1>

<%= render 'form', todo: @todo %> <%= link_to 'Show', @todo %> | <%= link_to
'Back', root_path %>

todos\new.html.erb の修正

\ToDoApp\app\views\todos\new.html.erb を以下の通り変更する。
Back のリンクをroot_pathに変更する。

\ToDoApp\app\views\todos\new.html.erb
1
2
3
<h1>New Todo</h1>

<%= render 'form', todo: @todo %> <%= link_to 'Back', root_path %>

todos\show.html.erb の修正

\ToDoApp\app\views\todos\show.html.erb を以下の通り変更する。
Back のリンクをroot_pathに変更する。

\ToDoApp\app\views\todos\show.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<p id="notice"><%= notice %></p>

<p>
<strong>ToDo:</strong>
<table>
<tbody>
<tr><td>Title</td><td>=><%= @todo.Title %></td></tr>
<tr><td>Detail</td><td>=><%= @todo.Detail %></td></tr>
</tbody>
</table>
</p>

<%= link_to 'Edit', edit_todo_path(@todo) %> |
<%= link_to 'Back', root_path %>

controllers\todos_controller.rb の修正

\ToDoApp\app\controllers\todos_controller.rb を修正する。
destroy 時のリダイレクト先を、root_pathに変更する。

\ToDoApp\app\controllers\todos_controller.rb
1
2
3
4
5
6
7
8
def destroy
puts `[destroy]`
@todo.destroy

respond_to do |format|
format.html { redirect_to root_url, notice: 'User was successfully destroyed.' }
end
end

不要なルーティングの削除

users/index.html.erb から Todo 見ることができるようになった。
todos コントローラへの不要なルーティングを停止する。
\ToDoApp\config\routes.rb を編集する。

\ToDoApp\config\routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Rails.application.routes.draw do

get 'userinfos/:id/edit', to: 'userinfos#edit',as:'edit_userinfo'
patch 'userinfos/:id',to: 'userinfos#update'
put 'userinfos/:id',to: 'userinfos#update'
get 'userinfos/new',to: 'userinfos#new',as:'new_userinfo'
post 'userinfos',to: 'userinfos#create'
get 'userinfos/:id', to: 'userinfos#show',as: 'userinfo'

devise_for :users

get 'users', to: 'users#index'

#get 'todos', to: 'todos#index'
post 'todos', to: 'todos#create'
get 'todos/new', to: 'todos#new',as: 'new_todo'
get 'todos/:id/edit', to: 'todos#edit',as: 'edit_todo'
get 'todos/:id', to: 'todos#show',as: 'todo'
patch 'todos/:id', to: 'todos#update'
put 'todos/:id', to: 'todos#update'
delete 'todos/:id', to: 'todos#destroy'

root to: "users#index"

end

以上で再度動作確認。
ログインしたユーザーで Todo の表示が動作していることを確認する。

一旦ここで github にコミットしておく。

以下の通り、実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 追加、書き換えがあったファイルを表示
>git status

# git add したときの確認
>git add -n

# git に管理されてるファイルで、書き換えがあったものをaddする。
>git add -u

# 変更に Deviseを追加 とコメントをつけてコミット
>git commit -m 'UserとTodoを連携'

# githubにプッシュ
>git push -u origin master

# コミット履歴を確認する。'Deviseを追加'とコメントを付けたコミットが確認できる。
>git log

今度はブランチを切ってみる

以下の通り実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 現在のブランチを確認
>git branch
*master

# 以降の作業をnewfunctionというブランチで行うものとして作成
>git branch newfunction

# newfunctionブランチが作成されていることが確認できる。
>git branch
* master
newfunction

# ブランチをnewfunctionに切り替え
>git checkout newfunction

# newfunctionブランチに切り替わったことを確認。
>git branch
master
* newfunction

User の情報を 1 対 1 で持つ Userinfo モデルを作る

モデル作成とマイグレーション

Name と Profile を持つ、Userinfo モデルを作成する。
以下の通り操作。

1
2
3
4
5
6
7
8
9
10
11
# モデル作成
>rails generate model Userinfo name:string profile:text

# マイグレーション実行
>rails db:migrate

# Userモデルへの外部キーを作成するマイグレーションを作成
>rails generate migration AddColumnToUserinfo User:references

# マイグレーション実行
>rails db:migrate

モデル修正

\ToDoApp\app\models\user.rb を修正。
has_one :userinfo, dependent: :destroyを追記。

1
2
3
4
5
6
7
8
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :todos, dependent: :destroy
has_one :userinfo, dependent: :destroy
end

has_many:では[モデル名]sだったが、has_one では[モデル名]でないと動作しなかった。
ここで小一時間停滞。

\ToDoApp\app\models\userinfo.rb を修正。
belongs_to :user,optional: trueを追記。

1
2
3
class Userinfo < ApplicationRecord
belongs_to :user,optional: true
end

Userinfo モデルのコントローラを作成

以下を実行。

1
2
3
# Userモデルに対して1対1で持つUserinfoモデルを一覧で表示はしない見込みなので、
# indexのビューは作らない
>rails generate controller Userinfos edit new
\ToDoApp\app\controllers\userInfos_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class UserinfosController < ApplicationController
before_action :set_userinfo, only: [:show,:edit,:update]

def show
end

def edit
end

def update
respond_to do |format|
if @userinfo.update(userinfo_params)
format.html {redirect_to root_path ,notice:'was successfully updated.' }
else
format.html {render :edit}
end
end
end

def new
@userinfo = Userinfo.new()
end

def create
@userinfo = Userinfo.new(userinfo_params)
@userinfo.User_id = current_user.id
respond_to do|format|
if @userinfo.save()
format.html {redirect_to root_path,notice:'User was successfully created.'}
else
format.html {redirect_to :new}
end
end
end

private
def set_userinfo
@userinfo = Userinfo.find(params[:id])
end
def userinfo_params
params.require(:userinfo).permit(:name,:profile)
end
end

userinfos コントローラへのルーティングを設定

\ToDoApp\config\routes.rb を編集。
userinfosから始まるルーティングを準備する。

\ToDoApp\config\routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Rails.application.routes.draw do

get 'userinfos/:id', to: 'userinfoss#show',as: 'userinfo'
get 'userinfos/:id/edit', to: 'userinfos#edit',as:'edit_userinfo'
patch 'userinfos/:id',to: 'userinfos#update'
put 'userinfos/:id',to: 'userinfos#update'
get 'userinfos/new',to: 'userinfos#new',as:'new_userinfo'
post 'userinfos',to: 'userinfos#create'

devise_for :users

get 'users', to: 'users#index'

#get 'todos', to: 'todos#index'
post 'todos', to: 'todos#create'
get 'todos/new', to: 'todos#new',as: 'new_todo'
get 'todos/:id/edit', to: 'todos#edit',as: 'edit_todo'
get 'todos/:id', to: 'todos#show',as: 'todo'
patch 'todos/:id', to: 'todos#update'
put 'todos/:id', to: 'todos#update'
delete 'todos/:id', to: 'todos#destroy'

root to: "users#index"

end

userinfoss#showへのルーティングを用意しないと、後から出てくるform_withメソッドで、
ActionView::Template::Error (undefined method `userinfo_path' for #<#<Class:~~~>といったエラーが出る。

1
get   'userinfos/:id', to: 'userinfoss#show',as: 'userinfo'

userinfoss#show使う気がなかったので、書かないでいたらエラーに遭遇。
ここで 3 時間停滞。
理由が、明確に書かれた資料を見つけられず、もやもや。

userinfo モデル用のビューを用意

用意するビューは以下の 3 つ。

  • \ToDoApp\app\views\userinfos_form.html.erb
  • \ToDoApp\app\views\userinfos\edit.html.erb
  • \ToDoApp\app\views\userinfos\new.html.erb

\ToDoApp\app\views\userinfos_form.html.erb

\ToDoApp\app\views\userinfos_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%= form_with(model: userinfo ,local:true) do |form|%> <% if
userinfo.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(userinfo.errors.count, "error") %> prohibited this user from
being saved:
</h2>

<ul>
<% userinfo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="field"><%= form.label :name %> <%= form.text_field :name %></div>

<div class="field">
<%= form.label :profile %> <%= form.text_field :profile %>
</div>

<div class="actions"><%= form.submit %></div>

<% end %>

\ToDoApp\app\views\userinfos\edit.html.erb

\ToDoApp\app\views\userinfos\edit.html.erb
1
2
<h1>Userinfos#edit</h1>
<%= render 'form', userinfo: @userinfo %> <%= link_to 'Back', root_path %>

\ToDoApp\app\views\userinfos\new.html.erb

\ToDoApp\app\views\userinfos\new.html.erb
1
2
3
4
<h1>Userinfos#new</h1>
<h1>New Todo</h1>

<%= render 'form', userinfo: @userinfo %> <%= link_to 'Back', root_path %>

users\index.html.erb に Userinfo が表示されるように修正

Userinfo モデルの表示を users\index.html.erb に設定します。
\ToDoApp\app\views\users\index.html.erb を編集し、以下を書き加える。

1
2
3
4
5
6
7
<% if @user.userinfo %>
<p>name:<%= @user.userinfo.name %></p>
<p>profile:<%= @user.userinfo.profile %></p>
<p><%= link_to 'EDIT', edit_userinfo_path(@user.userinfo.id) %></p>
<% else %>
<p><%= link_to 'NEW', new_userinfo_path %></p>
<% end %>

書き加えたものが以下の通り。

\ToDoApp\app\views\users\index.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<h1>Index</h1>
<% if @user %>
<p>email:<%= @user.email %></p>
<p>ID:<%= @user.id %></p>

<% if @user.userinfo %>
<p>name:<%= @user.userinfo.name %></p>
<p>profile:<%= @user.userinfo.profile %></p>
<p><%= link_to 'EDIT', edit_userinfo_path(@user.userinfo.id) %></p>
<% else %>
<p><%= link_to 'NEW', new_userinfo_path %></p>
<% end %>

<table>
<thead>
<tr>
<th>Todo</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @user.todos.each do |todo| %>
<tr>
<td><%= todo.Title %></td>
<td><%= link_to 'Show', todo %></td>
<td><%= link_to 'Edit', edit_todo_path(todo.id) %></td>
<td>
<%= link_to 'Destroy', todo, method: :delete, data: { confirm: 'Are you
sure?' } %>
</td>
</tr>
<% end %>
</tbody>
</table>

<%= link_to 'New Todo', new_todo_path %> <%end%>

ここで再度実行して、userinfo の登録ができることを確認する。

再度 github にコミットしておく。

以下の通り、実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 追加、書き換えがあったファイルを表示
>git status

# git add したときの確認
>git add -n

# git に管理されてるファイルで、書き換えがあったものをaddする。
>git add -u

# 変更に Deviseを追加 とコメントをつけてコミット
>git commit -m 'Userinfoを追加'

# githubにnewfunctionブランチをプッシュ
>git push -u origin newfunction

# newfunctionブランチでの変更を、masterブランチにマージ
> git checkout master
> git merge newfunction

# コミット履歴を確認する。
# --graphwオプションに加えると変遷をツリーで見ることができるが、
# 現在は、commitが一直線になっている。
>git log --graph

ブランチを切って合流させてみたい。

現在の作業は、コミット履歴が1直線になっています。
一人で作業していると仕方がないのかなとは思いつつ、あえて分岐させて合流させてみます。
CSS の適用を例にしてやってみます。

一旦 CSS ファイルをダウンロードと設置

適用する CSS ライブラリは、BULMAにします。
BULMAから zip ファイルがでダウンロードできるので、
/public/bulma-0.8.0 以下に展開します。

ここで CSS を含んだ状態で一度コミット

CSS を含んだ状態で 1 度コミットします。
操作は以下の通り。

1
2
3
4
5
6
7
8
9
10
11
# 追加、書き換えがあったファイルを表示
>git status

# git public以下にファイルを追加したので、「.」を入れて 全部追加する。
>git add .

# 変更に Deviseを追加 とコメントをつけてコミット
>git commit -m 'BULMAを追加'

# githubにnewfunctionブランチをプッシュ
>git push -u origin

ブランチを切る

以下のようにブランチを切ることにする。

  • /views/users の中のファイルに CSS を適用するブランチ userstocss
  • /views/userinfos の中のファイルに CSS を適用するブランチ userinfostocss

操作は以下の通り。

1
2
3
4
5
# userstocssを作成
>git branch userstocss

# userinfotocssを作成
>git branch usersinfotocss

/views/users 以下に CSS を適用

一旦チェックアウト。
以下の通り実行。

1
>git checkout userstocss

head 要素に CSS の指定をするのも userstocss ブランチで行うことにする。
よって書き換えするのは以下の 2 ファイル。

  • \ToDoApp\app\views\users\index.html.erb
  • \ToDoApp\app\views\layouts\application.html.erb

以下を\ToDoApp\app\views\users\index.html.erb に追加。

1
<link rel="stylesheet" href="/public/bulma-0.8.0/css/bulma.css" />

そのほかマークアップを追加します。

終わったのなら、再度コミットします。

1
2
3
4
5
6
7
8
9
10
11
# 書き換えがあったファイルを表示
>git status

# 書き換えがあったファイルをadd
>git add -u

# "/users/index,/layouts/applicationを編集"という名前でcommit
>git commit -m "/users/index,/layouts/applicationを編集"

# githubにnewfunctionブランチをプッシュ
>git push -u origin userstocss

これで、userstocss ブランチの中でコミットできた。

/views/userinfos に CSS を適用

今度は、/views/userinfos 以下のファイルに CSS の適用を追加します。

まずは userinfostocss ブランチにチェックアウトします。
以下の通り実行。

1
>git checkout userinfostocss

対象は、以下の 3 ファイルです。

  • \ToDoApp\app\views\userinfos_form.html.erb
  • \ToDoApp\app\views\userinfos\edit.html.erb
  • \ToDoApp\app\views\userinfos\new.html.erb

ですが、layouts\application.html.erb に書いた css のロードの設定が消えています。
以下のファイルも再度編集します。

  • \ToDoApp\app\views\layouts\application.html.erb

それぞれ編集が終わったならい以下の操作でコミットします。

1
2
3
4
5
6
7
8
9
10
11
# 書き換えがあったファイルを表示
>git status

# 書き換えがあったファイルをadd
>git add -u

# "/users/index,/layouts/applicationを編集"という名前でcommit
>git commit -m "/userinfos/_form,edit,new,を編集"

# githubにnewfunctionブランチをプッシュ
>git push -u origin userinfostocss

これで、userinfostocss ブランチの中でコミットできた。

2 つのブランチを master にマージ。

userstocss ブランチと、userinfostocss ブランチを master ブランチに取り込みます。

1
2
3
4
5
6
7
8
9
#masterブランチにチェックアウト
>git checkout master

#userstocssブランチをmasterにマージ
>git merge userstocss

#userinfostocssブランチをmasterにマージ
>git merge userinfostocss
#コンフリクト発生!!!

\ToDoApp\app\views\layouts\application.html.erb はそれぞれのブランチで書き換えていたので、
コンフリクトを起こしてしまいました。

コンフリクトの解消

VSCode 上で、それぞれのブランチでの\ToDoApp\app\views\layouts\application.html.erb の比較が表示されるので、
どちらを採用するか選択します。
今回は、userstocss ブランチの\ToDoApp\app\views\layouts\application.html.erb の記載を採用しました。

再度マージ

以下の通り実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#userinfostocssブランチをmasterにマージ
>git merge userinfostocss

# 追加、書き換えがあったファイルを表示
>git status

# git に管理されてるファイルで、書き換えがあったものをaddする。
>git add -u

# serstocssブランチ,userinfostocssブランチをmasterにマージ とコメントをつけてコミット
>git commit -m "userstocssブランチ,userinfostocssブランチをmasterにマージ"

# mastorブランチをgithubにpushする。
>git push -u origin master

# コミット履歴を確認する。
# --graphwオプションに加えると変遷をツリーで見ることができる。
# 今回は2又になった。
>git log --graph
* commit [------------------乱数------------------] (HEAD -> master)
|\ Merge: a6b3485 18aae56
| | Author: githubアカウント名 <メールアドレス>
| | Date: Thu Oct 31 00:21:00 2019 +0900
| |
| | userstocssブランチ,userinfostocssブランチをmasterにマージ
| |
| * commit [------------------乱数------------------] (origin/userinfotocss, userinfotocss)
| | Author: githubアカウント名 <メールアドレス>
| | Date: Wed Oct 30 23:47:30 2019 +0900
| |
| | /userinfos/_form,edit,new,を編集
| |
* | commit [------------------乱数------------------] (origin/userstocss, userstocss)
|/ Author: githubアカウント名 <メールアドレス>
| Date: Wed Oct 30 23:18:31 2019 +0900
|
| /users/index,/layouts/applicationを編集
|
* commit [------------------乱数------------------] (origin/master)
| Author: githubアカウント名 <メールアドレス>
| Date: Wed Oct 30 21:44:21 2019 +0900
|
| 'BULMAを追加'

動作確認していたら、軽微なミスを見つけたので、修正して「バグ修正」というコメントをつけて再度コミット、プッシュした。


一旦ここまでで、本記事は終わろうと思う。

ここ記事で作ったアプリは、Octo8080/Rails-App-Sampleにアップしてある。
参考になれば、幸い。

ではでは。