1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

Ruby on rails を初心者向けに解説⑥ ~バリデーションの作成~

はじめに

今回は以前の記事の続きになります。

よろしければ、以前の記事も御覧ください。

今回はバリデーションについて学んでいきましょう。

Ruby on rails を初心者向けに解説①

Ruby on rails を初心者向けに解説② ~リンクの作成~

Ruby on rails を初心者向けに解説③ ~データベースの作成~

Ruby on rails を初心者向けに解説④ ~命名規則とform_Tagの使い方について~

Ruby on rails を初心者向けに解説⑤ ~データベースの編集と削除~

新しいコントローラーの作成

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

今回は、投稿を管理する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

終わりに

今回はここまでになります。

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

よろしければ以下の記事も御覧ください。

Ruby on rails を初心者向けに解説⑦ ~フラッシュの実装~

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?