73
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RailsAdvent Calendar 2020

Day 8

[初心者向け]Ruby on Railsについて徹底解説してみた

Last updated at Posted at 2020-12-07

#はじめに
今回は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の後ろは何でも好きな名前にしてください。

以下のようファイルが作成されます。

image.png

これで、Webアプリを作る際の枠組みを作成することができました。

#サーバーの起動(rails server)

作成したqiita_projectに移動してください。

cd qiita_project

これで作成したqiita_projectに移動することができました。

次はサーバーを起動してみましょう。次のコマンドです。

rails server

次に、chromeなどのブラウザのURL欄に以下のURLを入力してください。

http://localhost:3000/

image.png

ここまでで、サーバーを起動することができました。

#コントローラーの作成 (rails generate controller コントローラー名)
以下のコードでコントローラーを作成することができます。

コントローラーが何を行うかは後に解説します。

rails generate controller home

上のコードを実行すると、app>>controllers配下にhome_controller.rbという名前のファイルが作成されます。

image.png

home_controllerの中身を見てみましょう。

home_controller.rb
class HomeController < ApplicationController

end

このようにして、コントローラーを作成することができました。

それでは、コントローラーの解説行います。
##コントローラーとは
コントローラーを理解するためには、まず以下の図を理解する必要があります。railが動作する仕組みについてです。

image.png

順番に見ていきましょう。

####①ユーザーがサーバーにリクエストを送る
image.png

まず、左のユーザーがサーバーにリクエストを送ります。右の様々な動作は、全てサーバー側の話です。

リクエスト送るとは、サーバーに何かを要求することです。例えば、URLを入力すると、「このURLに対応するファイルを送ってこい!」と要求(getリクエスト)することになりますし、IDとパスワードを入れてログインしようとすれば、「送ったデータを使って何かしらの処理をしろ!」と要求(postリクエスト)することになります。

####②ルーティングによりどのコントローラーを使うのかを決定
image.png

ルーティングにより、ユーザーから受け取ったURLを処理します。

例えば、ユーザーからhome/topというURLを受け取ったとします。

そうすると、ルーティングはhome#topというルーティングに変換します。

これは、「homeコントローラーのtopアクションを利用します」という意味です。アクションというのは、コントローラーごとに設定されている「何かを行うコード」だと考えてください。

今回は、簡単のためにユーザーからは「このURLに対応するファイルを送ってこい!」と要求(getリクエスト)されたと考えます。

ユーザーから"home/top"というURLが送られてきて、それをhomeコントローラーのtopアクションを実行するという命令にルーティングしましょう。

configディレクトリ配下のroutes.rbファイルに以下のように追記してください。

routes.rb
Rails.application.routes.draw do
  get "home/top" => "home#top"
end

####コントローラーによりviewファイルを探索

image.png

home/topというURLがユーザーから送られてきて、ルーティングによりhome#topに変換されたとします。

この場合、homeコントローラーのtopアクションを行うことになります。

以下のように、homeコントローラーにtopアクションを追加しましょう。

home_controller.rb
class HomeController < ApplicationController
    def top
    end
end

このようにコードを書くと、homeコントローラーはhome/top.html.erbファイルを探して、それをユーザーに返してくれます。

####viewファイルの作成
app >> views 配下のhomeディレクトリにtop.html.erbファイルを追加してください。

image.png

top.html.erbファイルを以下のように編集してください。

top.html.erb
<h1>Hello World</h1>

このようにして、viewファイルを作成することができました。

実際にレスポンスを見てみましょう。

####ユーザーがURLを打ち込んだ場合
再び、以下のコードでサーバーを起動しましょう。

rails server

webブラウザで以下のURLを打ち込んでください。

http://localhost:3000/home/top

そうすると、以下の画面が送られてきます。

image.png

何が起きているのかを、もう一度ざっくり解説します。

http://localhost:3000/home/topというURLが送られると、それがルーティングによりhome#topという形に変換されます。

それにより、homeコントローラーのtopアクションが行われます。

そうすると、app >> viewsディレクトリ配下のhomeディレクトリの中のtop.html.erbファイルがrailsにより発見され、それがユーザーに送られます。

#ルーティングの変更
ルーティングは自分の好きなように設定することができます。

例えば、/pocomaruと書いたときに、home#top(homeコントローラーのtopアクション)が行われるようにしましょう。

ルーティングを以下のように変更します。

routes.rb
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に対して行います。

実行すると、以下の画面になりました。

image.png

#リンクの作成
それでは、リンクを作成していきましょう。

top.html.erbというファイルに、test.html.erbファイルへのリンクを張ります。

以下のようなファイル構造になっています。
image.png

test.html.erbファイルの中身は次のようにします。

test.html.erb
<h1>テスト</h1>

このファイルへのリンクを作成していきましょう。

###リンクをクリックすると別のファイルになぜ飛ぶか
しかし、リンクをクリックして、それがユーザーに送られるとはどういうことでしょうか。

一度、何が起きているのかを考えてみましょう。以下の図をみてください。

image.png

リンクをクリックして別のファイルに飛ぶということは、上の図の赤く囲った部分の話になります。

ユーザーがURLをサーバーに送り、そのURLに応じてコントローラーがviewファイルを探し出し、アクションに書いてある処理をした後、viewファイルをユーザーに送ります。

このように、ユーザーがサーバーにviewファイルを要求することをgetリクエストを送ると呼びます。

ユーザーがURLをサーバーに送る動作は様々です。リンクが貼られている文字をクリックしたり、IDを打ち込んだ後に送信などと書かれたボタンを押したりする、などがあります。

そのようなURLが送られてきた後、サーバーはルーティングにより翻訳を行うのでしたね。

image.png

ルーティングにより、どのコントローラーのどのアクションを行うかを指定します。

また、これらのアクションは、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ファイルを以下のように書き換えました。

top.html.erb
<h1>Hello World</h1>
<a href="test">test by href</a>
<%= link_to("test by link_to", "test") %>

image.png

二行目のリンクの書き方は、典型的な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ファイルを送る方法について解説します。

まず、最初にルーティングを変更しましょう。

##ルーティングを変更
以下のようにルーティングを変更してください。

routes.rb
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アクションを追記しましょう。

hoem_controller.rb
class HomeController < ApplicationController
    def top
    end
    
    def test
    end
end

このようなコードが追記されることで、ユーザーからhome#testというルーティングが呼ばれたときに、homeコントローラーのtestアクションを行い、view >> home >> test.html.erbファイルをユーザに送り返すことができるようになります。

image.png

それでは次に、データベースについて見ていきましょう。

#データベースとは
データベースとは、データを保存しておく場所のことです。

Ruby on Railsにおいては、コントローラーからモデルを作成することによりデータベースを操作することができます。
image.png

#コントローラーの作成
今回は、ユーザーのIDとパスワードを保存するデータベースを作成することを考えます。

データベースを作成する前に、一度コントローラーとアクションを作成してみましょう。

ターミナルで以下のコードを実行してください。

rails g controller users index

これでuserコントローラーを作成し、その中にindexアクションを追加することができました。rails g コマンドにおいて、コントローラー名とアクション名の2つを設定することができます。

以下のようにルーティングしてください。

routes.rb
get 'users/index' => "users#index"

これで、ユーザーからuser/indexというURLが送られてきたときに、userコントローラーのindexアクションを行うことができるようになりました。

userコントローラーを確認してみましょう。今回は、最初からアクションが追加されています。

users_controller.rb
class UsersController < ApplicationController
  def index
  end
end

実はviewファイルも自動で生成されています。

image.png

以下のようにindex.html.erbファイルを書きましょう。

index.html.erb
<h1>Users#index</h1>
<p>Find me in app/views/users/index.html.erb</p>

以下のURLでこのファイルにアクセスしましょう。

http://localhost:3000/users/index

以下の画面がでてきます。

image.png

##アクションから変数をviewファイルに渡す
image.png

コントローラーがviewファイルを探してきて、それをユーザーに返します。

その時、コントローラーの中のアクションに変数を定義することで、その変数をviewファイル内で用いることができます。

以下のように変数を定義しましょう。

users_controller.rb
class UsersController < ApplicationController
  def index
    @users = ["maru", "poco"]
  end
end

@userのように、変数の前に@を用いることでその変数はインスタンス変数になります。こちらに解説がありました。

このように、コントローラーからviewファイルに変数を渡すときは、ローカル変数ではなくインスタンス変数を用います。

Railsのコントローラでインスタンス変数を使用するのは、以下の場合です。
・メソッド間でのデータの受け渡し(典型的には、before_actionでデータをロードしておくとか)
・ビューへのデータの受け渡し

このように、@変数で作成したインスタンス変数はviewファイル内で利用することができます。

index.html.erb
<% @users.each do |user| %>
  <div>
    <%= user %>
  </div>
<% end %>

image.png

@usersは配列が格納されているので、.each do ~ end で取り出すことができます。この部分は全てRubyのコードなので、<%%>ではさみましょう。ブラウザに表示する必要がないので、<%=%> ではなく <%%>ではさむところがポイントです。

<%= user %>の部分で、ブラウザに表示させます。

今回は、コントローラーのアクション内で配列を定義して、それをviewファイルに渡すことで利用しました。

今度は、データベースからデータをアクション内に持ってきて、それをviewファイルに渡すことを考えてみましょう。

#モデルの作成
image.png

データベースを操作するためには、モデルを作成する必要があります。

モデルとは、データベースの情報を操作する仕組みのことです。または、データベースとのやり取りを行うクラスとも言うことができます。

以下のコードでモデルと。マイグレーションファイルを作成します。

rails g model user name:string password:string

Userがモデル名で、id、passwordがカラムになります。カラムとは、データベースの縦のデータ、つまり列のことです。

このコードで作成したデータベースは、以下のような表になっています。

image.png

この表全体をテーブルと呼び、縦のデータをカラム、横のデータをレコードと呼びます。モデルとは、このデータベースに対応するRubyのクラスであり、モデルクラスのインスタンスは一つの行(レコード)を表すオブジェクトであり、テーブルの列(カラム)に対応する属性をもちます。

上記のコードを実行すると、データベースを作成するためのmigrationファイルと、モデルが作成されます。

.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name
      t.string :password

      t.timestamps
    end
  end
end
user.rb
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

ここまでで、データベースを作成することができました。

それでは、実際にデータベースを利用してみましょう。

#データベースの利用
データベースには、モデルを用いてアクセスします。

image.png

データベースを利用する際は、コントローラーからモデルを用いてアクセスします。

users_controller.rb
class UsersController < ApplicationController
  def index
    @user = User.first
  end
end

これで、index.html.erbファイル内でインスタンス変数@userを使用することができるようになりました。

@userには、usersテーブルの一番最初の列のレコードが格納されています。

以下のように、index.html.erbファイル内で使用します。

index.html.erb
<p><%= @user.name %></p>
<p><%= @user.password %></p>

image.png

それでは次に、命名規則について見ていきましょう。

#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ファイルに以下のコードを書いてください。

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リクエストが実行されます。

今回は、以下のようにルーティングしています。

routes.rb
post "users/create" => "users#create"

つまり、上記のデータはusersコントローラーのcreateアクションに送信されます。createアクションでは以下のコードを書きます。

users_controller.rb
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])を用いることでモデルを作成し、データベースに格納しています。

ユーザーからは以下のようになっています。

image.png

この状態で送信を押してみましょう。すると、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コントローラーに以下のようにコードを追記しましょう。

users_controller.rb
def create
  user = User.new(name: params[:name], password: params[:password])
  user.save
  redirect_to("/users/index")
end

このように書くと、送信を押した場合に/users/indexに対応するファイルにリダイレクトされます。

ちなみに、リダイレクトを書く場合は、パスの書き始めに/を入れることを忘れないようにしてください。

それでは次に、データベースの編集を行っていきましょう。

#データベースのデータ一覧の表示
以下のコードでusersテーブルのデータを取得して表示しましょう。

index.html.erb
 <% @users.each do |user| %>
   <p>name</p>
   <div class="ruby-name"><%= user.name %></div>
 <% end %>

インスタンス変数@usersを使用するために、コントローラ内で渡しています。

users_controller.rb
def index
  @users = User.all
end

以下のような画面が表示されます。

image.png

また、以下のようにcssを指定しています。

users.scss
.ruby-name {
    color: purple;
    display: inline-block;
    font-weight: bold;
}

#データベースの削除
それではデータベースの削除を実装してみましょう。

以下のようにコードを書き換えてください。

index.html.erb
 <% @users.each do |user| %>
   <p>name</p>
   <div class="ruby-name">
     <%= user.name %>
     <%= link_to("削除", "/users/#{user.id}/destroy", {method: "post"})%>
   </div>
 <% end %>

image.png

削除ボタンをクリックすると、要素を削除することができました。

image.png

具体的な処理を見ていきましょう。index.html.erbに、以下のコードが追記されています。

<%= link_to("削除", "/users/#{user.id}/destroy", {method: "post"})%>

これにより、削除をクリックすると、第二引数の処理が実行されます。

第二引数の"/users/#{user.id}/destroy"は、usersコントローラーのdestroyアクションへのルーティングに、データベースのidを含めたものになっています。このようにURLを指定することで、コントローラーは削除したいデータベースのidを受け取ることができます。

第三引数は、これがgetリクエストではなく、postリクエストであることを指定しています。

以下のようにルーティングしてください。

routes.rb
post "users/:id/destroy" => "users#destroy"

:id の部分は、任意の数字を受け取ることができます。受け取った数字は、usersコントローラーにおいて、params[:id]の中に格納されます。

以下のようにコントローラーをコーディングしてください。

users_controller.rb
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を編集してください。

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を渡すことになります。

次のようにルーティングしてください。

routes.rb
get "users/:id/edit" => "users#edit"

次のパスに以下のviewファイルを準備してください。
image.png

edit.html.erb
<%= form_tag("/users/#{@user.id}/update") do  %>
  <input type="text" value="<%=@user.name%>" name="new_name">
  <input type="submit" value="送信">
<% end %>

試しに以下のindex.html.erbファイルの編集と書いてある部分をクリックしましょう。
image.png

以下のようになります。
image.png

ここで、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アクションから送られてきたものです。

users_controller.rb
def edit
  @user = User.find_by(id: params[:id])
end

@userには、データベースからidに応じて探してきた値が格納されています。

それでは、下のように値を変更して送信してみましょう。

image.png

そうすると、以下のルーティングにより、usersコントローラーのupdateアクションが実行されます。

routes.rb
post "users/:id/update" => "users#update"
users_controller.rb
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にリダイレクトしています。

そのため、以下のように変化します。

image.png

それでは次に、バリデーションについて学んでいきましょう。そのために、新しいコントローラーを作成します。

#新しいコントローラーの作成
新しいコントローラーを作成していきましょう。

今回は、投稿を管理するpostsコントローラーを作成します。ターミナルで以下のコードを実行してください。

rails g controller posts all

all.html.erbファイルで、全ての投稿を表示するようにしましょう。

そのために、新しい投稿を作成するファイルを作成します。new.html.erbファイルをpostsファイルの中に作成しましょう。

image.png

この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ファイルに、投稿を作成するコードを追加しましょう。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"></textarea>
  <input type="submit" value="送信">
<% end %>

image.png

/posts/createというURLにpostリクエストを送っています。params[:content]に、textarea内部のデータが格納されて、送られます。

以下のようにルーティングしましょう。

routes.rb
post "posts/create" => "posts#create"

postsコントローラーのcreateアクションにルーティングされています。textareaのデータをpostsテーブルに格納するために、postsコントローラーを以下のようにコーディングします。

posts_controller.rb
def create
  post = Post.new(content: params[:content])
  post.save
  redirect_to("/posts/new")
end

これで、postsテーブルにデータを保存することができるようになりました。

以下のようにtextareaに記入して送信ボタンを押しましょう。

image.png

データベースを確認してみましょう。ターミナルで以下のコードを打ってください。

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モデルはデフォルトでは以下のようになっています。

post.rb
class Post < ApplicationRecord
end

バリデーションは、以下の書式で書きます

validates :カラム名, {検証内容}

空っぽの投稿を防ぐバリデーションは以下のようになります。

post.rb
class Post < ApplicationRecord
end

バリデーションは、以下の書式で書きます

validates :カラム名, {検証内容}

空っぽの投稿を防ぐバリデーションは以下のようになります。

post.rb
class Post < ApplicationRecord
    validates :content, {presence: true}
end

これで、空っぽの投稿を防ぐことができました。

バリデーションに引っかかった場合、saveすることができなくなります。また、saveに成功スっればTrueが戻り値として帰ってきて、saveに失敗すればFalseが戻り値として帰ってきます。

postsコントローラーを以下のように書き換えましょう。

posts_controller.rb
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文字以上の投稿を防ぐバリデーションを設定してみましょう。

以下のようになります。

post.rb
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ファイル内でこのインスタンス変数を表示するために、以下のように書き換えましょう。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"><%= @content%></textarea>
  <input type="submit" value="送信">
<% end %>

textareaの初期値に@contentを渡しています。これで、バリデーションに引っかかったときに、その値を表示することができます。

実際に試してみましょう。

image.png

以下のように20文字以上入力して、送信を押してみましょう。

image.png

特に何も変わりません。

image.png

それでは次に、フラッシュについて学んでいきましょう。
#フラッシュとは
具体例を探しに、Twitterにで試してみました。

image.png

この入力されたユーザー名が~の部分がフラッシュです。

フラッシュとはページ上に一度だけ表示されるものであり、ページを更新したり別のページに移動したりするとフラッシュは表示されなくなります。

image.png

このフラッシュを実装してみましょう。

#フラッシュの実装
railsでフラッシュを表示するためには、特殊な変数flashが用意されています。

アクションで変数flash[:notice]に文字列を代入すると、viewファイルで使用することができます。flashは一度使用された後は自動的に削除されることになっています。

また、フラッシュは色々な場所で共通して使用するので、application.html.erbファイル内で使用すると便利です。

application.html.erbファイルに書かれたものは、全てのviewファイルに共通して表示されるようになります。

views >> layoutsフォルダの配下にあるapplication.html.erbファイルに以下のように記入してフラッシュが表示できるようにしましょう。

application.html.erb
<% if flash[:notice]%>
  <div class="flash">
    <%= flash[:notice]%>
  </div>
<% end %>

これで、フラッシュが存在するなら表示されるようになりました。

どうせなんで、cssも設定しておきましょう。

application.css
.flash {
    background-color: brown;
    color: white;
}

postsコントローラーを次のように書き直して、flash[:notice]にエラーメッセージを代入してみましょう。

posts_controller.rb
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ファイルを開いてみましょう。また、バリデーションは以下のようになっています。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"><%= @content%></textarea>
  <input type="submit" value="送信">
<% end %>
post.rb
class Post < ApplicationRecord
    validates :content, {presence: true}
    validates :content, {length: {maximum: 20}}
end

image.png

試しに、値を何も入れずに送信を押してみましょう。バリデーションに弾かれ、エラーメッセージがflash[:notice]に格納されます。

image.png

次は、20文字以上入力して送信を押してみましょう。次のエラーメッセージが表示されます。

image.png

今度は、投稿に成功した場合を試してみます。次のようになります。

image.png

上手くいきましたね。

#終わりに
今回の記事はここまでになります。

とても長い記事になってしまいました。

ここまでお付き合い頂きありがとうございました。

73
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?