#はじめに
今回はRuby on railsの解説記事です。
初心者向けに、わかりやすく解説していきます。
頑張っていきましょう。
今回は、記事を書く上でたかし君
に協力してもらいます。
#Ruby on rails とは
Ruby on rails とは、Webフレームワークの一種です。
最初に、そもそもフレームワークとは一体何なのかについて解説します
###フレームワークとは
フレームとは、簡単に言えば骨組み
のことです。
フレームワークの意味をwikipedia先生に聞いてみましょう。
プログラミングにおいて、一般的な機能をもつ共通コードをユーザーが選択的に上書きしたり特化させたりすることで、ある特定の機能をもたせようとする抽象概念のことである。
相変わらず堅い言葉なので、噛み砕いて解説します。
フレームワークとは、様々な機能を提供してくれる骨組み
のことであると考えて問題ないと思います。
今度は、フレームワークの具体例をみて考えていきましょう。
####Bootstrap
何かWebサイトを作成しようとしたときに、コツコツHTMLとCSSを書いていくのは大変ですよね。
当然、何とか楽をしたいと考えます。どうすれば楽にできるでしょうか。
そうです、誰かが作ってくれたものをパクれば楽ができるのです。
しかし、Webサイトをそのままパクれば怒られてしまうし、作れるバリエーションも限られてしまいます。
ここでたかし君は考えました。
たかし君「そういえば、Webサイトに使われる部品って限られてるよな。ヘッダー部分とかボタン部分とかを個別に楽にかける枠組み
があれば楽に書けるんじゃね?」
こうして生まれたのがBootstrap
です。
BootstrapはCSSのフレームワークで、Webサイトの各々の部品ごとの枠組みを提供してくれています。
###Webフレームワークとは
ここまでの説明でなんとなく分かりましたね。
Webフレームワークとは、Webアプリを作るための枠組み
のことです。
もう一度たかし君に聞いてみましょう。
たかし君「Webアプリ作るのめっちゃだるいな。でも、Webアプリで使う機能って以外に限られてるよな。ユーザーが打ち込んだURLに応じてデータベースを操作したり、HTMLファイルを作成して送ったり、ログイン機能が必要だったりするだけじゃん。この枠組み
を誰かが作ってくれて、それをパクれば楽に書けるんじゃね?」
このようにして生まれたのが、Webフレームワークだったり、Ruby on railsだったりするわけです。
それでは、実際にRuby on railsでアプリを作ってみましょう。
#骨組みの作成 (rails new)
最初にローカルのパソコンにRubyとRuby on railsをインストールしてください。
環境構築については、色々な人が記事を書いているので割愛します。
環境構築はうまく行かないことがほとんどですが、できるまで粘り強く調べ続けてください。応援しています。
最初に、railsアプリを作りたいディレクトリに移動して、以下のコマンドを打ちましょう。
rails new qiita_project
new
の後ろは何でも好きな名前にしてください。
以下のようファイルが作成されます。
これで、Webアプリを作る際の枠組み
を作成することができました。
#サーバーの起動(rails server)
作成したqiita_project
に移動してください。
cd qiita_project
これで作成したqiita_project
に移動することができました。
次はサーバーを起動してみましょう。次のコマンドです。
rails server
次に、chromeなどのブラウザのURL欄に以下のURLを入力してください。
http://localhost:3000/
ここまでで、サーバーを起動することができました。
#コントローラーの作成 (rails generate controller コントローラー名)
以下のコードでコントローラーを作成することができます。
コントローラーが何を行うかは後に解説します。
rails generate controller home
上のコードを実行すると、app>>controllers配下にhome_controller.rb
という名前のファイルが作成されます。
home_controllerの中身を見てみましょう。
class HomeController < ApplicationController
end
このようにして、コントローラーを作成することができました。
それでは、コントローラーの解説行います。
##コントローラーとは
コントローラーを理解するためには、まず以下の図を理解する必要があります。railが動作する仕組みについてです。
順番に見ていきましょう。
まず、左のユーザーがサーバーにリクエストを送ります。右の様々な動作は、全てサーバー側の話です。
リクエスト送る
とは、サーバーに何かを要求することです。例えば、URLを入力すると、「このURLに対応するファイルを送ってこい!」と要求(getリクエスト)することになりますし、IDとパスワードを入れてログインしようとすれば、「送ったデータを使って何かしらの処理をしろ!」と要求(postリクエスト)することになります。
####②ルーティングによりどのコントローラーを使うのかを決定
ルーティングにより、ユーザーから受け取ったURLを処理します。
例えば、ユーザーからhome/top
というURLを受け取ったとします。
そうすると、ルーティングはhome#top
というルーティングに変換します。
これは、「homeコントローラーのtopアクションを利用します」という意味です。アクションというのは、コントローラーごとに設定されている「何かを行うコード」だと考えてください。
今回は、簡単のためにユーザーからは「このURLに対応するファイルを送ってこい!」と要求(getリクエスト)されたと考えます。
ユーザーから"home/top"というURLが送られてきて、それをhomeコントローラーのtopアクションを実行するという命令にルーティングしましょう。
configディレクトリ配下のroutes.rbファイルに以下のように追記してください。
Rails.application.routes.draw do
get "home/top" => "home#top"
end
####コントローラーによりviewファイルを探索
home/top
というURLがユーザーから送られてきて、ルーティングによりhome#top
に変換されたとします。
この場合、homeコントローラーのtopアクションを行うことになります。
以下のように、homeコントローラーにtopアクションを追加しましょう。
class HomeController < ApplicationController
def top
end
end
このようにコードを書くと、homeコントローラーはhome/top.html.erb
ファイルを探して、それをユーザーに返してくれます。
####viewファイルの作成
app >> views 配下のhomeディレクトリにtop.html.erbファイルを追加してください。
top.html.erbファイルを以下のように編集してください。
<h1>Hello World</h1>
このようにして、viewファイルを作成することができました。
実際にレスポンスを見てみましょう。
####ユーザーがURLを打ち込んだ場合
再び、以下のコードでサーバーを起動しましょう。
rails server
webブラウザで以下のURLを打ち込んでください。
http://localhost:3000/home/top
そうすると、以下の画面が送られてきます。
何が起きているのかを、もう一度ざっくり解説します。
http://localhost:3000/home/top
というURLが送られると、それがルーティングによりhome#top
という形に変換されます。
それにより、homeコントローラーのtopアクションが行われます。
そうすると、app >> viewsディレクトリ配下のhomeディレクトリの中のtop.html.erbファイルがrailsにより発見され、それがユーザーに送られます。
#ルーティングの変更
ルーティングは自分の好きなように設定することができます。
例えば、/pocomaru
と書いたときに、home#top
(homeコントローラーのtopアクション)が行われるようにしましょう。
ルーティングを以下のように変更します。
Rails.application.routes.draw do
get "pocomaru" => "home#top"
end
この状態で、以下のようにURLを打ちます。
http://localhost:3000/pocomaru
このようにすると、http://localhost:3000/pocomaru
というURLはhome#top
(homeコントローラーのtopアクション)という命令に置き換えられます。
ルーティングは、localhost:3000以降のURLに対して行います。
実行すると、以下の画面になりました。
#リンクの作成
それでは、リンクを作成していきましょう。
top.html.erbというファイルに、test.html.erbファイルへのリンクを張ります。
test.html.erbファイルの中身は次のようにします。
<h1>テスト</h1>
このファイルへのリンクを作成していきましょう。
###リンクをクリックすると別のファイルになぜ飛ぶか
しかし、リンクをクリックして、それがユーザーに送られるとはどういうことでしょうか。
一度、何が起きているのかを考えてみましょう。以下の図をみてください。
リンクをクリックして別のファイルに飛ぶということは、上の図の赤く囲った部分の話になります。
ユーザーがURLをサーバーに送り、そのURLに応じてコントローラーがviewファイルを探し出し、アクションに書いてある処理をした後、viewファイルをユーザーに送ります。
このように、ユーザーがサーバーにviewファイルを要求することをgetリクエストを送る
と呼びます。
ユーザーがURLをサーバーに送る動作は様々です。リンクが貼られている文字をクリックしたり、IDを打ち込んだ後に送信
などと書かれたボタンを押したりする、などがあります。
そのようなURLが送られてきた後、サーバーはルーティングにより翻訳を行うのでしたね。
ルーティングにより、どのコントローラーのどのアクションを行うかを指定します。
また、これらのアクションは、viewファイルに対応しています。
例えば、ルーティングによりhomeコントローラーのtopアクション
が呼ばれると、app >> views 配下のhomeディレクトリのtop.html.erbファイルが呼ばれます。
つまり、何故リンクをクリックすると別ファイルに飛ぶのかを考えると以下のように答えることができます。
リンクをクリックすると、URLがルーティングにより変換され、どのコントローラーのどのアクションを行うかが指定され、そのアクションに応じたviewsファイルがユーザーに送られてくるから
##実際にリンクを作成
Ruby on railsのリンクの作成方法は大きく分けて以下の2つがあります。
- htmlのaタグのhrefで指定する
- Railsのlink_toメソッドを使う
せっかくなので、2つの方法で実装してみましょう。
top.html.erbファイルを以下のように書き換えました。
<h1>Hello World</h1>
<a href="test">test by href</a>
<%= link_to("test by link_to", "test") %>
二行目のリンクの書き方は、典型的なhtmlのリンクの書き方ですね。
三行目の書き方に注目してください。
<%= %>
という形で囲むと、これはRubyのコードだよ!
と伝えることになります。link_toを使ったコードは、htmlのコードではなくRubyのコードなので、このように囲む必要があります。
ちなみに、<% %>
で囲っても、Railsのコードであると伝えることになります。
<%%>で囲むのか、<%=%>で囲むのかについて解説と、link_toの使い方の解説を以下で行います。
###<%= %>と<% %>の違い
実は.html.erbのerbとはEmbedded RuBy
の略称になります。つまり、Rubyを埋め込んだhtmlファイルであるという意味です。
つまり、このhtml.erbファイルの内部にはRubyのスクリプトを埋め込むことができます。
<%= %>と<% %>の2つは、html.erbファイルにおいてrubyのコードを書くときに使うことになります。
しかし、htmlファイルにrubyスクリプトを埋め込むときに、別にブラウザに表示する必要がない処理を行う場合があります。
そのようなときに、この2つを使い分ける必要があります。ざっくりと以下のように覚えてください。
- ブラウザに表示させたいときは
<%= %>
を使う - ブラウザに表示させたくないときは
<% %>
を使う
###link_toの使い方
link_toはRubyのコードであるので、<% %>
か<%= %>
で囲む必要があります。
今回はクリックしたらどこかに飛ぶリンクを作成したいので、当然ブラウザに表示する必要があります。
<%= %>
で囲みましょう。
link_toは、第一引数にブラウザに表示する文字
を取り、第二引数にURL
を取ります。
今回は、test
というURLを取ることにしました。
ここからは、ユーザーからリンクがクリックされた、つまりURLが送られてきたときに、test.html.erbファイルを送る方法について解説します。
まず、最初にルーティングを変更しましょう。
##ルーティングを変更
以下のようにルーティングを変更してください。
Rails.application.routes.draw do
get "pocomaru" => "home#top"
get "test" => "home#test"
end
新しく、test
とうURLが送られてきた場合にhome#top
というルーティングに変換するコードを追記しました。
つまり、ユーザーからtestというURLがクリックされると、homeコントローラーのtopアクションが実行されるようになります。
次は、homeコントローラーにtopアクションを追記しましょう。
##コントローラーにアクションを追記
homeコントローラにtestアクションを追記しましょう。
class HomeController < ApplicationController
def top
end
def test
end
end
このようなコードが追記されることで、ユーザーからhome#test
というルーティングが呼ばれたときに、homeコントローラーのtestアクションを行い、view >> home >> test.html.erbファイルをユーザに送り返すことができるようになります。
それでは次に、データベースについて見ていきましょう。
#データベースとは
データベースとは、データを保存しておく場所のことです。
Ruby on Railsにおいては、コントローラーからモデルを作成することによりデータベースを操作することができます。
#コントローラーの作成
今回は、ユーザーのIDとパスワードを保存するデータベースを作成することを考えます。
データベースを作成する前に、一度コントローラーとアクションを作成してみましょう。
ターミナルで以下のコードを実行してください。
rails g controller users index
これでuserコントローラーを作成し、その中にindexアクションを追加することができました。rails g コマンドにおいて、コントローラー名とアクション名の2つを設定することができます。
以下のようにルーティングしてください。
get 'users/index' => "users#index"
これで、ユーザーからuser/index
というURLが送られてきたときに、userコントローラーのindexアクションを行うことができるようになりました。
userコントローラーを確認してみましょう。今回は、最初からアクションが追加されています。
class UsersController < ApplicationController
def index
end
end
実はviewファイルも自動で生成されています。
以下のようにindex.html.erbファイルを書きましょう。
<h1>Users#index</h1>
<p>Find me in app/views/users/index.html.erb</p>
以下のURLでこのファイルにアクセスしましょう。
http://localhost:3000/users/index
以下の画面がでてきます。
コントローラーがviewファイルを探してきて、それをユーザーに返します。
その時、コントローラーの中のアクションに変数を定義することで、その変数をviewファイル内で用いることができます。
以下のように変数を定義しましょう。
class UsersController < ApplicationController
def index
@users = ["maru", "poco"]
end
end
@userのように、変数の前に@を用いることでその変数はインスタンス変数になります。こちらに解説がありました。
このように、コントローラーからviewファイルに変数を渡すときは、ローカル変数ではなくインスタンス変数を用います。
Railsのコントローラでインスタンス変数を使用するのは、以下の場合です。
・メソッド間でのデータの受け渡し(典型的には、before_actionでデータをロードしておくとか)
・ビューへのデータの受け渡し
このように、@変数で作成したインスタンス変数はviewファイル内で利用することができます。
<% @users.each do |user| %>
<div>
<%= user %>
</div>
<% end %>
@usersは配列が格納されているので、.each do ~ end で取り出すことができます。この部分は全てRubyのコードなので、<%%>ではさみましょう。ブラウザに表示する必要がないので、<%=%> ではなく <%%>ではさむところがポイントです。
<%= user %>
の部分で、ブラウザに表示させます。
今回は、コントローラーのアクション内で配列を定義して、それをviewファイルに渡すことで利用しました。
今度は、データベースからデータをアクション内に持ってきて、それをviewファイルに渡すことを考えてみましょう。
データベースを操作するためには、モデルを作成する必要があります。
モデルとは、データベースの情報を操作する仕組み
のことです。または、データベースとのやり取りを行うクラス
とも言うことができます。
以下のコードでモデルと。マイグレーションファイルを作成します。
rails g model user name:string password:string
Userがモデル名で、id、passwordがカラムになります。カラムとは、データベースの縦のデータ、つまり列のことです。
このコードで作成したデータベースは、以下のような表になっています。
この表全体をテーブル
と呼び、縦のデータをカラム
、横のデータをレコード
と呼びます。モデルとは、このデータベースに対応するRubyのクラスであり、モデルクラスのインスタンスは一つの行(レコード)を表すオブジェクトであり、テーブルの列(カラム)に対応する属性をもちます。
上記のコードを実行すると、データベースを作成するためのmigrationファイルと、モデルが作成されます。
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.string :password
t.timestamps
end
end
end
class User < ApplicationRecord
end
上記の作成したマイグレーションファイル以下のコードで取り込むことで、データベースを作成することができます。
rails db:migrate
ここまでで、データベースを作成することができました。
それでは、マイグレーションファイルとは何なのかについてまとめていきましょう。
###マイグレーションファイルとは
マイグレーションファイルとは、データベースを生成する際の設計図のようなものです。
マイグレーションファイルを実行することで、その内容に基づいたデータテーブルを作成することができます。
railsでは、rails g model
コマンドを実行すると、マイグレーションファイルとモデルの両方が生成されます。
マイグレーションファイルはデータベースの枠組みを作成するための道具で、モデルはデータベースとコントローラーを橋渡しする道具のようなものだと覚えておいてください。
###データをデータベースに保存
以下のコードでRailsのコンソールを起動しましょう。
rails console
コンソールを起動したら、モデルを使ってデータベースにデータを保存してみましょう。
user = User.new(name: "poco", password: "maru")
user.save
これでデータベースにデータを保存することができました。
###データベースの確認
それでは作成したデータベースを確認していきましょう。
####データベースクライアントの起動
以下のコードでデータベースクライアントを起動できます。
rails dbconsole
####テーブルの一覧表示
データベースクライアントを起動した後は、以下のコードでテーブル一覧を表示することができます。
sqlite>.table
ar_internal_metadata schema_migrations users
####スキーマの表示
以下のコードでスキーマを表示することができます。スキーマとは、構造という意味です。指定したデータベースの構造を確認することができます。
sqlite>.schema users
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "password" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
####データベースクライアントの停止
以下のコードでデータベースクライアントを停止することができます。
sqlite>.quit
ここまでで、データベースを作成することができました。
それでは、実際にデータベースを利用してみましょう。
#データベースの利用
データベースには、モデルを用いてアクセスします。
データベースを利用する際は、コントローラーからモデルを用いてアクセスします。
class UsersController < ApplicationController
def index
@user = User.first
end
end
これで、index.html.erbファイル内でインスタンス変数@userを使用することができるようになりました。
@userには、usersテーブルの一番最初の列のレコードが格納されています。
以下のように、index.html.erbファイル内で使用します。
<p><%= @user.name %></p>
<p><%= @user.password %></p>
それでは次に、命名規則について見ていきましょう。
#Railsの命名規則について
ここまで、コントローラーやモデルを作成してきました。
それらには、命名規則があります。学んでいきましょう。
##Modelの命名規則
モデルとは、データベースを作成するための設計図です。
設計図は一つであるため、モデルクラス名は単数形
で作成します。
テーブルは、そのモデルのデータが複数あるため、自動的に複数形
で表されます。
前回の記事でuser
という名前でモデルを作成しました。
そうすると、users
という名前でテーブルが作成されます。
また、クラス名はUser
というふうに、最初が大文字になります。
##Viewの命名規則
Viewフォルダは配下に複数のファイルを持つため、複数形
になります。
##Controllerの命名規則
Controllerは複数のアクションを持つため、複数形
で作成します。
#データベースにデータを登録
以前の記事では、railsのコンソールを使用してデータベースにデータを登録しました。
今回は、ブラウザをユーザーに操作してもらうことでデータベースにデータを登録しましょう。
その前に、一度データベースの確認を行います。
ターミナルに以下のコマンドを打ち込みましょう。
rails dbconsole
次のコードでカラム名の表示をONにできます。
sqlite> .headers on
この状態で、次のSQLの文を書くと中身を確認することができます。
sqlite> select * from users;
id|name|password|created_at|updated_at
1|poco|maru|2020-05-20 10:50:13.177731|2020-05-20 10:50:13.177731
現在は、usersテーブルにnameカラムとpaswordカラムが格納されていることが分かりますね。
それでは、入力フォームを作成してユーザーから送られてくるデータをデータベースに格納してみましょう。
/users/new.html.erbファイルに以下のコードを書いてください。
<%= form_tag("/users/create") do %>
<p>ユーザー名</p>
<input name="name">
<p>password</p>
<input name="password">
<input type="submit" value="送信">
<% end %>
form_tag
は、viewファイルからコントローラーに何か値を送ったり、削除したりするときに使います。いわゆるPOSTリクエスト
と呼ばれるものです。getリクエストとpostリクエストの違いについては、こちらの記事を参考にしてください。
type="submit"
となっているボタンがユーザーから送られると、users/create
に対応するpostリクエストが実行されます。
今回は、以下のようにルーティングしています。
post "users/create" => "users#create"
つまり、上記のデータはusersコントローラーのcreateアクションに送信されます。createアクションでは以下のコードを書きます。
def create
user = User.new(name: params[:name], password: params[:password])
user.save
end
このコードで、userモデルのUserクラスを用いて、データベースのusersテーブルにデータを格納しています。
form_tagで送られてきたデータにおいて、name属性が指定されているタグが存在した場合、コントローラー内においてparams[name属性]
として値を扱うことができます。
この場合、<input name="name">
内の値がparams[:name]
に、<input name="password">
の値がparams[:password]に格納されます。
その送られてきたデータに対してUser.new(name: params[:name], password: params[:password])
を用いることでモデルを作成し、データベースに格納しています。
ユーザーからは以下のようになっています。
この状態で送信
を押してみましょう。すると、usersコントローラーのcreateアクション内において、thisという文字列がparams[:name]に格納され、testという文字列がparams[:password]に格納されます。
以下のようにデータを格納することができました。
3|this|test|2020-05-21 05:30:36.718523|2020-05-21 05:30:36.718523
しかし、このままだと送信を押しても特に変化はありません。退屈なので、他のファイルにリダイレクトさせましょう。
###送信を押した場合にリダイレクト
送信を押すとusersコントローラーのcreateアクションが実行されるので、このcreateアクション内にリダイレクトのコードを書けば、他のファイルにリダイレクトされるようになります。
usersコントローラーに以下のようにコードを追記しましょう。
def create
user = User.new(name: params[:name], password: params[:password])
user.save
redirect_to("/users/index")
end
このように書くと、送信を押した場合に/users/index
に対応するファイルにリダイレクトされます。
ちなみに、リダイレクトを書く場合は、パスの書き始めに/
を入れることを忘れないようにしてください。
それでは次に、データベースの編集を行っていきましょう。
#データベースのデータ一覧の表示
以下のコードでusersテーブルのデータを取得して表示しましょう。
<% @users.each do |user| %>
<p>name</p>
<div class="ruby-name"><%= user.name %></div>
<% end %>
インスタンス変数@usersを使用するために、コントローラ内で渡しています。
def index
@users = User.all
end
以下のような画面が表示されます。
また、以下のようにcssを指定しています。
.ruby-name {
color: purple;
display: inline-block;
font-weight: bold;
}
#データベースの削除
それではデータベースの削除を実装してみましょう。
以下のようにコードを書き換えてください。
<% @users.each do |user| %>
<p>name</p>
<div class="ruby-name">
<%= user.name %>
<%= link_to("削除", "/users/#{user.id}/destroy", {method: "post"})%>
</div>
<% end %>
削除ボタンをクリックすると、要素を削除することができました。
具体的な処理を見ていきましょう。index.html.erbに、以下のコードが追記されています。
<%= link_to("削除", "/users/#{user.id}/destroy", {method: "post"})%>
これにより、削除をクリックすると、第二引数の処理が実行されます。
第二引数の"/users/#{user.id}/destroy"は、usersコントローラーのdestroyアクションへのルーティングに、データベースのidを含めたものになっています。このようにURLを指定することで、コントローラーは削除したいデータベースのidを受け取ることができます。
第三引数は、これがgetリクエストではなく、postリクエストであることを指定しています。
以下のようにルーティングしてください。
post "users/:id/destroy" => "users#destroy"
:id の部分は、任意の数字を受け取ることができます。受け取った数字は、usersコントローラーにおいて、params[:id]
の中に格納されます。
以下のようにコントローラーをコーディングしてください。
def destroy
user = User.find_by(id: params[:id])
user.destroy
redirect_to("/users/index")
end
user = User.find_by(id: params[:id])
の部分で、データベースからモデルを使ってデータを抜き出します。index.html.erbから送られてきたidと同じidのデータをデータベースから抜き出し、userに格納します。
user.destroy
の部分でそのデータを削除しています。
redirect_to("/users/index")
の部分で、index.html.erbにリダイレクトしています。今回は、index.html.erbから削除リンクをクリックしたときの動作であるので、リロードになります。
ここまでで、データベースからデータを削除することができました。
#データベースの編集
次はデータベースの編集を行っていきましょう。
次のようにindex.html.erb
を編集してください。
<% @users.each do |user| %>
<p>name</p>
<div class="ruby-name">
<%= user.name %>
<%= link_to("削除", "/users/#{user.id}/destroy", {method: "post"})%>
<%= link_to("編集", "/users/#{user.id}/edit") %>
</div>
<% end %>
今回新たに追加されたのは<%= link_to("編集", "/users/#{user.id}/edit") %>
の部分です。
これにより、新たにusers/edit
というviewファイルへ移動します。
そのときに、そのviewファイルに編集したいデータベースのidを渡すことになります。
次のようにルーティングしてください。
get "users/:id/edit" => "users#edit"
<%= form_tag("/users/#{@user.id}/update") do %>
<input type="text" value="<%=@user.name%>" name="new_name">
<input type="submit" value="送信">
<% end %>
試しに以下のindex.html.erbファイルの編集と書いてある部分をクリックしましょう。
ここで、edit.html.erbファイルについての解説です。
form_tag("/users/#{@user.id}/update")
の部分で、どのコントローラーのどのアクションを使うかを指定しています。
今回は、usersコントローラーのupdateアクションを使用します。また、データベースの編集を行うため、編集したいデータベースのidも送ります。form_tagはpostリクエストになるのでしたね。
<input type="text" value="<%=@user.name%>" name="new_name">
の部分で、inputタグの初期値と名前を設定しています。@user
はusersコントローラーのeditアクションから送られてきたものです。
def edit
@user = User.find_by(id: params[:id])
end
@user
には、データベースからidに応じて探してきた値が格納されています。
それでは、下のように値を変更して送信してみましょう。
そうすると、以下のルーティングにより、usersコントローラーのupdateアクションが実行されます。
post "users/:id/update" => "users#update"
def update
user = User.find_by(id: params[:id])
user.name = params[:new_name]
user.save
redirect_to("/users/index")
end
updateアクション内では、送られてきたidに応じてデータベースからデータを探索し、ローカル変数userに格納した後、nameカラムのデータを送られてきた新しい名前に書き換えて、user.save
でセーブした後に、/users/index
にリダイレクトしています。
そのため、以下のように変化します。
それでは次に、バリデーションについて学んでいきましょう。そのために、新しいコントローラーを作成します。
#新しいコントローラーの作成
新しいコントローラーを作成していきましょう。
今回は、投稿を管理するpostsコントローラーを作成します。ターミナルで以下のコードを実行してください。
rails g controller posts all
all.html.erbファイルで、全ての投稿を表示するようにしましょう。
そのために、新しい投稿を作成するファイルを作成します。new.html.erbファイルをpostsファイルの中に作成しましょう。
このnew.html.erbファイルで、新しい投稿を作成していきます。
#新しいモデルの作成
では、投稿を管理するデータベースを作成しましょう。今回は、まだデータベースを全く作成していないので、モデルから作成していきます。
モデルとは、データベースの情報を操作する仕組み
であり、データベースとのやり取りを行うクラス
とも言うことができるものでしたね。
モデルは通常、小文字から始まる単数形で命名します。なぜなら、モデルとはtableに対して一つしか存在しないからです。
rails g model post content: string
このようにモデルを作成すると、同時にデータベースの設計図であるmigrationファイルが作成されるのでしたね。
以下のコードでマイグレーションファイルを実行しましょう。
rails db:migrate
データベースコンソールから、作成したtableを確認してみましょう。
rails dbconsole
.table
ar_internal_metadata schema_migrations
posts users
postsテーブルが作成されていますね。以下のコードで中身を見てみましょう。
.schema posts
CREATE TABLE IF NOT EXISTS "posts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "content" varchar, "string" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
#投稿を作成
new.html.erbファイルに、投稿を作成するコードを追加しましょう。
<%= form_tag("/posts/create") do %>
<textarea name="content" cols="30" rows="10"></textarea>
<input type="submit" value="送信">
<% end %>
/posts/create
というURLにpostリクエストを送っています。params[:content]に、textarea内部のデータが格納されて、送られます。
以下のようにルーティングしましょう。
post "posts/create" => "posts#create"
postsコントローラーのcreateアクションにルーティングされています。textareaのデータをpostsテーブルに格納するために、postsコントローラーを以下のようにコーディングします。
def create
post = Post.new(content: params[:content])
post.save
redirect_to("/posts/new")
end
これで、postsテーブルにデータを保存することができるようになりました。
以下のようにtextareaに記入して送信ボタンを押しましょう。
データベースを確認してみましょう。ターミナルで以下のコードを打ってください。
rails dbconsole
.header on
select * from posts;
id|content|string|created_at|updated_at
1|pocomaru||2020-05-23 10:37:51.509719|2020-05-23 10:37:51.509719
このように、投稿をデータベースに格納することができました。
##バリデーションの設定
バリデーションとは、データベースにデータを保存する際にかける制約のことです。
例えば、何かのサイトにログインする際にメールアドレスやパスワードが空っぽでもログイン可能だとやばいですよね。
そんなことを防ぐために存在します。
バリデーションは、モデルに設定します。
実際に設定してみましょう。
###空っぽの投稿を防ぐ
空っぽの投稿を防ぐバリデーションを考えます。
投稿を保存するのはpostsテーブルなので、このバリデーションはpostモデルのPostクラス内部に記入します。
postモデルはデフォルトでは以下のようになっています。
class Post < ApplicationRecord
end
バリデーションは、以下の書式で書きます
validates :カラム名, {検証内容}
空っぽの投稿を防ぐバリデーションは以下のようになります。
class Post < ApplicationRecord
end
バリデーションは、以下の書式で書きます
validates :カラム名, {検証内容}
空っぽの投稿を防ぐバリデーションは以下のようになります。
class Post < ApplicationRecord
validates :content, {presence: true}
end
これで、空っぽの投稿を防ぐことができました。
バリデーションに引っかかった場合、saveすることができなくなります。また、saveに成功スっればTrueが戻り値として帰ってきて、saveに失敗すればFalseが戻り値として帰ってきます。
postsコントローラーを以下のように書き換えましょう。
def create
post = Post.new(content: params[:content])
if post.save
redirect_to("/posts/all")
else
redirect_to("/posts/new")
end
このようにコードを書き換えることで、saveが成功した場合には/posts/all
にリダイレクトし、saveが失敗した場合には/posts/new
にリダイレクトします。
これで、空っぽの投稿を排除するバリデーションを作成することができました。
次は、一定以上の文字数を削除するバリデーションを作成してみましょう。
###一定以上の文字数を防ぐ
今回は20文字以上の投稿を防ぐバリデーションを設定してみましょう。
以下のようになります。
class Post < ApplicationRecord
validates :content, {presence: true}
validates :content, {length: {maximum: 20}}
end
このvalidates :content, {length: {maximum: 20}}
の部分により、20文字以上の投稿を制限することができるようになりました。
しかし、このようにバリデーションを設定するだけだと、問題があります。20文字以上の投稿をしたときに、textareaが空っぽになってしまうのです。
理由はpostsコントローラーにあります。バリデーションに引っかかり、redirect_to("/posts/new")
が呼ばれたとき、ルーティングによりpostsコントローラーのnewアクションが実行されます。そうすると、インスタンス変数をnew.html.erbファイルに送ることができないため、頑張って書いたtextareaが空っぽになってしまうのです。
これを防ぐために、render
というメソッドを使います。
renderとはレンダリングすることができるメソッドであり、レンダリングとはブラウザにviewファイルを読み込ませて描画させることです。
renderメソッドをviewファイル内で使うと、複数のviewファイルの共通の部分を描画する部分テンプレートを使うことができます。
今回はコントローラー内部で使うことにより、アクションを介することなくレンダリングを行うことで、作成したインスタンス変数をviewファイルに渡すことができます。
postsコントローラーを次のように書き換えましょう。
def create
post = Post.new(content: params[:content])
@content = params[:content]
if post.save
redirect_to("/posts/all")
else
render("posts/new")
end
end
@content
に、投稿の内容を格納した後、redirect_to の代わりにrenderを使ってnew.html.erbファイルを描画しています。
このようにすることで、インスタンス変数であ@content
をnew.html.erbに渡すことができます。
new.html.erbファイル内でこのインスタンス変数を表示するために、以下のように書き換えましょう。
<%= form_tag("/posts/create") do %>
<textarea name="content" cols="30" rows="10"><%= @content%></textarea>
<input type="submit" value="送信">
<% end %>
textareaの初期値に@content
を渡しています。これで、バリデーションに引っかかったときに、その値を表示することができます。
実際に試してみましょう。
以下のように20文字以上入力して、送信を押してみましょう。
特に何も変わりません。
それでは次に、フラッシュについて学んでいきましょう。
#フラッシュとは
具体例を探しに、Twitterにで試してみました。
この入力されたユーザー名が~
の部分がフラッシュです。
フラッシュとはページ上に一度だけ表示されるものであり、ページを更新したり別のページに移動したりするとフラッシュは表示されなくなります。
このフラッシュを実装してみましょう。
#フラッシュの実装
railsでフラッシュを表示するためには、特殊な変数flashが用意されています。
アクションで変数flash[:notice]
に文字列を代入すると、viewファイルで使用することができます。flashは一度使用された後は自動的に削除されることになっています。
また、フラッシュは色々な場所で共通して使用するので、application.html.erb
ファイル内で使用すると便利です。
application.html.erb
ファイルに書かれたものは、全てのviewファイルに共通して表示されるようになります。
views >> layoutsフォルダの配下にあるapplication.html.erbファイルに以下のように記入してフラッシュが表示できるようにしましょう。
<% if flash[:notice]%>
<div class="flash">
<%= flash[:notice]%>
</div>
<% end %>
これで、フラッシュが存在するなら表示されるようになりました。
どうせなんで、cssも設定しておきましょう。
.flash {
background-color: brown;
color: white;
}
postsコントローラーを次のように書き直して、flash[:notice]
にエラーメッセージを代入してみましょう。
def create
post = Post.new(content: params[:content])
@content = params[:content]
if post.save
flash[:notice] = "投稿に成功しました"
redirect_to("/posts/all")
else
flash[:notice] = post.errors.full_messages[0]
render("posts/new")
end
end
post.save
の部分で失敗した場合に、post.errors.full_messages
にエラーメッセージがリストとして格納されるため、その1つ目の値をflash[:notice]
に格納しています。投稿に成功した場合は、その旨をflash[:notice]
に格納します。
これでフラッシュを実装することができました。
実際に試してみましょう。
以下のnew.html.erbファイルを開いてみましょう。また、バリデーションは以下のようになっています。
<%= form_tag("/posts/create") do %>
<textarea name="content" cols="30" rows="10"><%= @content%></textarea>
<input type="submit" value="送信">
<% end %>
class Post < ApplicationRecord
validates :content, {presence: true}
validates :content, {length: {maximum: 20}}
end
試しに、値を何も入れずに送信を押してみましょう。バリデーションに弾かれ、エラーメッセージがflash[:notice]
に格納されます。
次は、20文字以上入力して送信を押してみましょう。次のエラーメッセージが表示されます。
今度は、投稿に成功した場合を試してみます。次のようになります。
上手くいきましたね。
#終わりに
今回の記事はここまでになります。
とても長い記事になってしまいました。
ここまでお付き合い頂きありがとうございました。