ここで使用している環境
OS: Windows10
IDE: RubyMine 2020.2.3
Rails: 6.1.0
> C:\\Ruby30\\bin\\ruby.exe -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [i386-mingw32]
注意
- 一部、分かりやすくするために冗長な説明をしている箇所があります。
-
アクション
を関数
と呼んでいます。 - IDEにRubyMineを使用することを前提としています。
※ただし、やっていることは他エディタ/IDEでも同じなので参考にはなるかもしれません。
以上の点について、ご理解ください。
プロジェクト作成
-
New Project
画面を開く -
Rails
->Application
を選択 -
Location
に好きなディレクトリ(プロジェクト名になる)を指定 -
Ruby SDK
で使用するRubyを選択 -
Rails Version
でRailsバージョンを選択 -
Create
をクリック
Create
をクリックした後、少し処理に時間が掛かるのでしばらく待ちます。
※この解説ではディレクトリ(プロジェクト名)にRailsTestApp
を使用します。
手順4で使いたいRubyが無い場合
手順5で使いたいRailsバージョンが無い場合
-
Rails Version
ドロップダウンからInstall Rails Gem...
を選択 - 少し待って出てきた画面の
Version to install
で好きなバージョンを選択してInstall
(今回は6.1.0
を使用)
LoadError: cannot load such file -- rexml/document
-
Gemfile
の一番下に、gem 'rexml'
を追加する -
Tools
->Bundler
->Install
をクリック -
Run
をクリック
ポートを変更する(任意)
- 右上のドロップダウンから
Edit Configurations...
を選択 -
Port
に好きなポートを入力する
早速起動する
- 右上の再生ボタンのようなものをクリック
Listening on http://127.0.0.1:3000
と表示されたら起動完了です。
エラーで起動できない場合の対処
- A server is already running. Check path/to/app/tmp/pids/server.pid.
/tmp/pids/server.pid
を削除して再度起動します。
サイトにアクセスしてみる
- ブラウザで
localhost:3000
にアクセスする
Routing・Model・View・Controllerの役割
Routing: リクエストから使用するコントローラを決定する
Model: データの塊(オブジェクト)
View: 見た目を制御する処理(主にHTMLなど)
Controller: 必要なModelをViewに渡す、受け取ったパラメータからModelを作成する、などの内部的な処理
例えば、全てのメモを表示する場合の全体的な順序としては
- Routingによって適切なControllerの関数を呼び出し
- ControllerでメモのModelを全て取得してViewに渡す
- Viewでそれらのデータを視覚的に表示する
といった感じです。MVC
などで調べてみると面白いかもしれません。
恐らく、書いているうちに理解できると思います。
とりあえず適当なページを作ってみる
※ここではあえてジェネレータを使用していません。
ここでは、localhost:3000/hello
にアクセスしたらHomeコントローラのindex関数が呼ばれ、app/views/home/index.html.erbが表示されるようにしてみます。
コントローラ作成
Homeコントローラを作成したいため、コントローラのクラス名はHomeControllerとなります。
-
app/controllers
ディレクトリを右クリック -
New
->Ruby File/Class
をクリック -
HomeController
と入力 -
Class
を選択 Enter
これでapp/controllers/home_controller.rb
が作成されました。
コントローラ編集
-
app/controllers/home_controller.rb
のclass HomeController
の行に< ApplicationController
を追加してApplicationControllerを継承する - 空の
index
関数を作成
class HomeController < ApplicationController
def index
end
end
View作成
Homeコントローラのindex関数に対応するViewを作成したいので、app/views/home/index.html.erbを作成します。
-
app/views
ディレクトリを右クリック -
New
->ERB File
をクリック -
home/index.html
と入力 Enter
これでapp/views/home/index.html.erb
が作成されました。
View編集
-
app/views/home/index.html.erb
に適当な内容を書く
拡張子が.erb
ですが普通のHTMLです。
<h1>index.html.erb</h1>
<p>Hello, world!</p>
ルーティング編集
localhost:3000/helloへのGETリクエストを受けたらHomeコントローラのindex関数を呼ぶように設定します。
そのため、必要なルーティングはget 'hello' => 'home#index'となります。
※GETというのはHTTPメソッドの一種で、ブラウザで普通にアクセスした場合はGETになります。
-
config/routes.rb
にget 'hello' => 'home#index'
を追加
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
get 'hello' => 'home#index'
end
ブラウザで確認
- ブラウザで
localhost:3000/hello
にアクセスする
app/views/home/index.html.erb
の内容が表示されます。
※Railsの再起動は不要です。
作ったページをrootに割り当てる
localhost:3000/へのGETリクエストを受けたらHomeコントローラのindex関数を呼ぶように設定します。
そのため、必要なルーティングはroot 'home#index'となります。
やっていることはget '/' => 'home#index'とほぼ同じですが、root
を使用することで、それがルートであることを明示することができます。
-
config/routes.rb
にroot 'home#index'
を追加
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
get 'hello' => 'home#index'
root 'home#index'
end
ブラウザで確認
- ブラウザで
localhost:3000/
にアクセスする
localhost:3000/
でもlocalhost:3000/hello
でも同じ内容が表示されていることが分かります。
※お好みでlocalhost:3000/hello
へのルーティング(get 'hello' => 'home#index'
)を削除しても良いです。
メモを投稿できる機能を作る
モデルはMemo
、コントローラはMemosController
、テーブル名はmemos
、メモの内容を入れるカラム名はcontent
とし、以下の通りに使用出来るようにします。
コントローラ関数名 | パス | 内容 |
---|---|---|
index | GET /memos | メモの一覧を表示する |
show | GET /memos/:id | IDが:id のメモを表示する |
new | GET /memos/new | メモを作成するためのフォームを表示する |
create | POST /memos | メモを作成するためのフォームの送信先(ここでメモが追加される) |
さらにメモの内容は空にできなく、最大1000文字までとします。
モデル作成
「メモ」というデータの塊(オブジェクト)を扱うために、「モデル」と呼ばれるものを作成する必要があります。
ここでは、Memo
というモデルを作成します。
モデル名がMemoでText型のcontentカラムを作成したいので、Generator arguments
はMemo content:textとなります。
ここでmemos
というテーブル名を入力していない理由は、モデル名のMemoから自動的に推測されるためです。
-
Ctrl+Alt+G
もしくはTools
->Run Rails Generator...
をクリック -
rails g model
を選択してEnter
-
Generator arguments
にMemo content:text
を入力 -
OK
をクリック
※Ctrl2回
->Run Anything
起動->rails g model
でもOKです
マイグレーションファイル編集
テーブルを作成したり、カラムを追加するための「マイグレーション」と呼ばれる仕組みがあります。
これは、どんな名前のテーブルを作るのか、どんなカラムを作るのか、を定義するものです。
このファイルはモデルを作成するときのrails g model
コマンドによって自動的に生成されています。
ここでは、これを編集してcontent
カラムをnull
にできないようにします。
-
db/migrate/xxxxxxxx_create_memos.rb
を開く -
t.text :content
の行にnull: false
を追加する
class CreateMemos < ActiveRecord::Migration[6.1]
def change
# memosテーブルを作成する
create_table :memos do |t|
# Text型のcontentカラムを作成する
t.text :content, null: false
# created_at(作成日時)、updated_at(更新日時)のカラムを作成する(デフォルト)
t.timestamps
end
end
end
マイグレーション実行
-
Ctrl2回
->Run Anything
起動->db:migrate
を選択する Enter
※選択肢にdb:migrate
が無い場合は、入力欄にdb:migrate
と入力する。
モデル編集
contentを空に出来ないように、そして文字数を1000文字までであることを検証するようにします。
-
app/models/memo.rb
を開く
class Memo < ApplicationRecord
# contentカラムのバリデーションを設定する
# presence: true - 空に出来ない
# lenght: {maximum: 1000} - 長さは最大1000文字
validates :content, presence: true, length: {maximum: 1000}
end
コントローラ作成
Home
コントローラを作成するときは分かりやすくするため手動でファイルを作成しましたが、今回はモデルの時のようにrails g
コマンドを使用して生成します。
Controller name
は、基本的にモデル名の複数形にします。
Actions
にはコントローラ関数名の一覧をスペース区切りで入れます。
-
Ctrl+Alt+G
もしくはTools
->Run Rails Generator...
をクリック -
rails g controller
を選択してEnter
-
Controller name
にMemos
を入力 -
Actions
にindex show new create
を入力 -
OK
をクリック
ルーティング編集
先ほどのrails g controller
によってルーティングが生成されています。
自動で生成されたルーティングを削除し、以下のように編集します。
ルーティングの意味が分からない場合は前述のルーティング編集を参照してください。
-
config/routes.rb
を開く - 以下のように編集する
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
get 'hello' => 'home#index'
resources 'memos', only: %i[index show new create]
root 'home#index'
end
resources
は、RESTfulなルーティングをいい感じに作ってくれるやつです。
今回はindex
、show
、new
、create
しか使用しないので、onlyでシンボルの配列を指定しています。
上記のルーティングは、以下とほぼ同じです。
/memos/:id
というルーティングが出てきますが、これは:id
の部分に任意の値が入るという意味です。
例えば/memos/1
にアクセスした場合、変数params[:id]
に1が入ります。この変数はコントローラやViewで使用することができます。
ルーティングの優先順位は上からです。そのため、get 'memos/:id' => 'memos#show'
より下にget 'memos/new' => 'memos#new'
を配置すると、memos#show
のid=new
としてルーティングされてしまいます。
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
get 'hello' => 'home#index'
# GET /memos
get 'memos' => 'memos#index'
# GET /memos/new
get 'memos/new' => 'memos#new'
# GET /memos/:id
get 'memos/:id' => 'memos#show'
# POST /memos
post 'memos' => 'memos#create'
root 'home#index'
end
コントローラ編集
コントローラでは、主に必要なモデルを取得する処理をします。
@
を付けた変数をコントローラで定義することによって後述するViewで使用することができるようになります。
-
app/controllers/memos_controller.rb
を以下のように編集します。
class MemosController < ApplicationController
def index
# すべてのメモを取得する
@memos = Memo.all
end
def show
# :idのメモを取得する
memo_id = params[:id]
@memo = Memo.find(memo_id)
end
def new
# 空のメモを作成する
@memo = Memo.new
end
def create
# 受け入れるパラメータを定義
# requireにはモデル名、permitにはカラム名
memo_param = params.require(:memo).permit(:content)
# メモの中身を埋めて作成
@memo = Memo.new(memo_param)
# セーブする(データベースに書き込む)
if @memo.save
# 成功した場合はメモ一覧にリダイレクト
redirect_to(@memo)
else
# エラーが発生した場合はnew(フォーム)を再表示する
render :new
end
end
end
View編集
以下のように編集します。
これはerb
ファイルなので、中にRubyの文を埋め込むことができます。
Rubyのifやeachなどは<% %>
で囲います。
変数の中身などの結果を表示したい場合は<%= %>
で囲います。
コメントを書きたい場合は<%# %>
で囲います。
HTMLの<!-- -->
も使用可能ですが、こちらはブラウザの「ページのソースを表示」などから見ることができます。
<%= link_to('戻る', :back) %>
は、リンクを生成する関数です。
第二引数に入れている:back
は前のページのパスを指しています。
link_to
にmemo
を入れていますが、これはメモのパス(/memos/:id
)として機能します。
index
<h1>メモ一覧</h1>
<ul>
<% @memos.each do |memo| %>
<%= link_to memo do %>
<li><%= memo.content %></li>
<% end %>
<% end %>
</ul>
<%= link_to('新規作成', new_memo_path) %>
<%= link_to('戻る', :back) %>
show
<h1>メモ閲覧</h1>
<pre><%= @memo.content %></pre>
<%= link_to('戻る', :back) %>
new
<h1>メモ作成</h1>
<%# エラーがあったら表示する %>
<% if @memo.errors.any? %>
<ul>
<% @memo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<%# modelにはコントローラで作った空のメモを指定する %>
<%= form_with(model: @memo, local: true) do |form| %>
<div class="field">
<%# メモ内容を入力するテキストエリア(labelはその説明) %>
<%= form.label :content %><br>
<%= form.text_area :content %>
</div>
<div class="actions">
<%# 送信ボタン %>
<%= form.submit %>
</div>
<% end %>
<%= link_to('戻る', :back) %>
create
app/views/memos/create.html.erb
は使用しないため削除する。
-
create.html.erb
ファイルを右クリック -
Delete
をクリック -
OK
をクリック
※これはお好みの方法でOK
動作を確認する
ブラウザでlocalhost:3000/memos
にアクセスして、正常に動作するか確認します。
日本語に対応させる
デフォルトでは、このようにメッセージやボタンなどが英語になっています。
rails-i18n
gemを入れる
-
Gemfile
の一番下に、gem 'rails-i18n'
を追加する -
Tools
->Bundler
->Install
をクリック -
Run
をクリック
日本語に設定する
-
config/application.rb
を以下のように書き換える。
require_relative "boot"
require "rails/all"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module RailsTestApp
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
# in config/environments, which are processed later.
#
# config.time_zone = "Central Time (US & Canada)"
# config.eager_load_paths << Rails.root.join("extras")
# タイムゾーンを日本に設定
config.time_zone = 'Tokyo'
config.active_record.default_timezone = :local
# デフォルトのロケールを日本語に設定
config.i18n.default_locale = :ja
# 使用可能なロケールに日本語を設定
config.i18n.available_locales = %i[ja]
end
end
モデルの日本語表記を作成
-
config/locale/ja.yml
を作成して以下のように編集
ja:
activerecord:
models:
# モデル名: モデルの日本語表記
memo: メモ
attributes:
# モデル名
memo:
# カラム名: カラムの日本語表記
content: メモ内容
このように書くことによって、Viewに書いてある<%= form.label :content %>
だけでいい感じに置き換わってくれます。
日本語化出来ているか確認
- Railsを再起動する(停止ボタン->再生ボタン)
-
localhost:3000/memos/new
でエラーを出して日本語化出来ているか確認する
メモにタイトルを設定できるようにする
マイグレーションファイル作成
メモを投稿できる機能を作る/マイグレーションファイル編集で編集したファイルを書き換えたくなりますが、一旦マイグレーションを行ったマイグレーションファイルを編集することはしてはいけません。そうすると、マイグレーションの意味が無くなってしまいます。
そのため、タイトルカラムを追加するマイグレーションを作成する必要があります。
今回はモデルの作成は不要なので、マイグレーションファイルのみを作成するコマンドを使用します。
memosテーブルにString型のTitleカラムを追加したいので、Generator arguments
はAddTitleToMemos title:stringとなります。
ここで、Text
型ではなくString
型を使う理由は、タイトルは255文字を超えないからです。
-
Ctrl+Alt+G
もしくはTools
->Run Rails Generator...
をクリック -
rails g migration
を選択してEnter
-
Genetaror arguments
にAddTitleToMemos title:string
を入力 -
OK
をクリック
マイグレーションファイル確認
db/migrate/xxxxxxxx_add_title_to_memos.rb
というマイグレーションファイルが作成されているので、見てみます。
class AddTitleToMemos < ActiveRecord::Migration[6.1]
def change
add_column :memos, :title, :string
end
end
今回は特に変更したい箇所は無いので変更しません。
ここでnull: false
によってnull
を禁止しない理由は、後からnull
を許可しないカラムを追加することは少しだけ難しいからです。
というのも、すでにレコードがある場合に必然的にtitle
カラムがnull
になってしまいます。
そのため、null
を許可しない場合はデフォルト値を設定するなどをする必要があります。
今回はi18nの問題もあり、表示側でnull
であったら設定されていない旨の表示をすることにします。
マイグレーション実行
モデル編集
タイトルの文字数上限を50文字にします。
-
app/models/memo.rb
にvalidates :title, length: {maximum: 50}
を追記する
以下のようになっていればOKです。
class Memo < ApplicationRecord
# contentカラムのバリデーションを設定する
# presence: true - 空に出来ない
# lenght: {maximum: 1000} - 長さは最大1000文字
validates :content, presence: true, length: {maximum: 1000}
# titleカラムのバリデーションを設定する
# lenght: {maximum: 50} - 長さは最大50文字
validates :title, length: {maximum: 50}
end
コントローラ編集
カラムtitle
の編集を許可する。
-
app/controllers/memos_controller.rb
を開く - 21行目、
~permit(:content)
を~permit(:content, :title)
に変更する
以下のようになっていればOKです。
class MemosController < ApplicationController
def index
# すべてのメモを取得する
@memos = Memo.all
end
def show
# :idのメモを取得する
memo_id = params[:id]
@memo = Memo.find(memo_id)
end
def new
# 空のメモを作成する
@memo = Memo.new
end
def create
# 受け入れるパラメータを定義
# requireにはモデル名、permitにはカラム名
memo_param = params.require(:memo).permit(:content, :title)
# メモの中身を埋めて作成
@memo = Memo.new(memo_param)
# セーブする(データベースに書き込む)
if @memo.save
# 成功した場合はメモ一覧にリダイレクト
redirect_to(memos_path)
else
# エラーが発生した場合はnew(フォーム)を再表示する
render :new
end
end
end
View書き換え
以下のように編集します。
index
タイトルを表示するようにする。
<h1>メモ一覧</h1>
<ul>
<% @memos.each do |memo| %>
<%= link_to memo do %>
<li><%= memo.title.blank? ? 'タイトルなし' : memo.title %>: <%= memo.content %></li>
<% end %>
<% end %>
</ul>
<%= link_to('新規作成', new_memo_path) %>
<%= link_to('戻る', :back) %>
show
タイトルを表示するようにする。
<h1>メモ閲覧</h1>
<h2><%= @memo.title.blank? ? 'タイトルなし' : memo.title %></h2>
<pre><%= @memo.content %></pre>
<%= link_to('戻る', :back) %>
new
タイトルの入力フィールドを追加する。
<h1>メモ作成</h1>
<%# エラーがあったら表示する %>
<% if @memo.errors.any? %>
<ul>
<% @memo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<%# modelにはコントローラで作った空のメモを指定する %>
<%= form_with(model: @memo, local: true) do |form| %>
<div class="field">
<%# タイトルを入力するテキストフィールド(labelはその説明) %>
<%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<div class="field">
<%# メモ内容を入力するテキストエリア(labelはその説明) %>
<%= form.label :content %><br>
<%= form.text_area :content %>
</div>
<div class="actions">
<%# 送信ボタン %>
<%= form.submit %>
</div>
<% end %>
<%= link_to('戻る', :back) %>
モデルの日本語表記を作成
-
config/locale/ja.yml
を以下のように編集
title: タイトル
を追加しています。
ja:
activerecord:
models:
# モデル名: モデルの日本語表記
memo: メモ
attributes:
# モデル名
memo:
# カラム名: カラムの日本語表記
content: メモ内容
title: タイトル
ブラウザで確認
- ブラウザで
localhost:3000/memos
にアクセスする
メモのタイトルが表示されていて、タイトル付きのメモを新規作成できるようになっています。
完成!
お疲れさまでした!
もし間違っている所や指摘がありましたら伝えて頂けるとありがたいです。
あとよろしければLGTMもよろしくお願いします!
時間があれば、編集や削除機能の付け方やテストの書き方の記事なども作成するかもしれません。