SuzuBlog

webのお勉強はじめたばかりの初心者。備忘録

Rails基礎 ストロングパラメータとバリデーション

今回はユーザーの入力値チェックを行う機能について書いていく。

ストロングパラメータとは?

WEB上でユーザーが送信してきたパラメータの内容をチェックしてから受け取る仕組みのこと。

悪意のあるデータを事前に防ぐことができる。

事前に受け付ける項目を指定しておくことで、裏で持っているユーザーからの入力を受け付けていない項目に値が入っていたら弾いてくれる。

フォームから送られてくるパラメータが対象で、createupdateなどの機能に実装する。

書き方例

postモデルのcreateに機能を実装したい場合 controllerに記述していく。

    def create
         @post = Post.new(params.require(:post).permit(:title,:body))
    end

まず、requireメソッドで対象とするモデル、キーを指定することで、それに紐付いている値だけを抽出することが可能になる。

そしてpermitメソッドで許可する値を明示的に指定してあげることで、他の項目が悪意ある改ざんを受けたとしてもスルーしてくれるようになる。

(この場合、titleとbody以外にカラムがあったとしてもそのカラムの登録・変更は受け付けない)

メソッドに切り出す

上記ではcreateメソッドに直接書きましたが、繰り返されることが多い処理なので(登録と編集とか) privateメソッドに切り出すのが慣習のよう。

    def create
         @post = Post.new(post_params)
    @post.save
    end

    private
        def post_params
            params.require(:post).permit(:title,:body)
        end

メソッド名はモデル名_paramsとしてあげるのが一般的らしい。

バリデーションとは?

先程のストロングパラメータとは違い、バリデーションは入力された値そのものに対してチェックを行っていく

例えば、入力必須の項目であったり、最低文字数が決まっている、メールアドレスだと@が入っているかどうか、等。

バリデーションはapp/models/post.rbに記入していく。

class Post < ApplicationRecord
    validates :title, presence: true, length: {minimum: 3, message: 'Too short to post!'}
    validates :body, presence: true
end

タイトルの行は「タイトルに対してのバリデーションで、必須項目だよ、最低文字数は3文字で、条件が満たない場合は「Too short to post!」とエラーメッセージを返してね」という意味になる。

バリデーションが成功したかどうかは.saveの返り値でbool型で返却されるので、controllerで結果を受け取って処理を行う。

    def create
        @post = Post.new(post_params)
        if @post.save
            redirect_to posts_path
        else
            render 'new'
        end
    end

これで、成功すればposts_pathにリダイレクトし、そうじゃない場合はnewと同じviewを表示してくれる。

あとはviewでエラーメッセージを表示するようにすれば良い。

<% if @post.errors,messages[:title].any? %>

でエラーメッセージがあるかどうかを調べ、エラーが有る場合(=true)は、

<%= @post.errors.messages[:title][0] %>

としてあげれば、複数のエラーがあった場合も、最初のエラーが消えるまで最初の1つ表示してくれる。 (必須チェック→文字数チェック、のように、順番も意識したほうが良さそう)

Rails基礎 フォームヘルパー(form_for)

フォームヘルパーとは?

Railsでフォームを作成するためのヘルパー。 これを使用すると簡単な記述でフォームを作成することが可能になる。 内部ではHTMLを生成してくれる。input、textarea、submit等

  • form_for

  • form_tag

  • form_with

と3種類用意されているが、Rails5.1で登場したform_withは他2つを統合したものになるため、 Rails5.1以降はform_withを使用することが推奨されている

今回ドットインストールに出てきたのがform_forだったため、これについて書いていく。

form_for

form_forは特定のモデルを編集・作成するのに向いている。 フォームとモデルオブジェクトを紐付けることで簡単に作成することができる。

html.erbファイルに記述していく。

<%= form_for @post, url: posts_path do |f| %>
    <p>
        <%= f.text_field :title, placeholder: 'enter title' %>
    </p>
    <p>
        <%= f.text_area :body, placeholder: 'enter body text' %>
    </p>
    <p>
        <%= f.submit %>
    </p>
<% end %>

ちなみに、1行目を省略しないで書くと以下

<%= form_for(@post, {url: posts_path}) do |f| %>
オプション
オプション 説明 デフォルト値
:as ハッシュのキー名前
:url フォームの送信先
:namespace 名前空間の設定
:method メソッド(get, post, patch, put, deleteなど)
:authenticity_token 認証トーク
:remote JavaScriptを使うか false
:enforce_utf8 utf8用の非表示用を出力するか? true
:html タグの属性
:format フォーマット

form_forでの入力は、上記の場合post[属性名]というフォーム名を持つ。 今回だと:title:bodyキーを持つハッシュがparams[:post]に入る。

:urlオプションを渡しルーティングパスを指定している。

Controllerで作成したインスタンスが空であればcreateアクション、そうでなければupdateアクションへ自動的に振り分けてくれる。

fオブジェクトを使用することでテキストボックスをはじめ、チェックボックスやパスワード入力ボックス、ファイル選択フォーム等を簡単に作成することが可能になる。

  • check_box…チェックボックス
  • radio_button…ラジオボタン
  • text_area…テキストエリア
  • password_field…パスワード入力ボックス
  • hidden_field…隠しフィールド
  • label…ラベルタグ
  • text_field…テキストボックス
  • file_field…ファイル選択ボックス
  • select…選択ボックス
  • email_field…メールアドレス入力ボックス
  • number_field…数値入力ボックス
  • range_field…範囲選択バー
  • search_field…検索ボックス
  • telephone_field…電話番号入力ボックス
  • url_field…URL入力ボックス
  • submit…サブミットボタン
  • datetime_select…日時選択ボックス
  • color_field…色の入力欄
  • date_field…日付の入力欄
  • datetime_field…日時の入力欄
  • datetime_local_field…ローカル日時の入力欄
  • month_field…月の入力欄
  • time_field…時間の入力欄
  • week_field…週の入力欄
  • date_select…日付選択ボックス
  • time_select…時間選択ボックス

等…最後に_tagをつけると汎用的な○○ができるらしい。

いずれ各メソッドがどんな形でこれらを生成するのか確かめたい。

参考

railsdoc.com

railsguides.jp

pikawaka.com

Rails基礎 link_toヘルパー

link_toとは

viewでリンクを表示させることが出来る。最終的には<a>タグを生成して表示される。

helperメソッドの1つ。

link_toメソッドに表示させたい文字列とリンク先を引数として渡す必要がある。

link_to '表示させる文字列',リンク先のパス(URL)

URLを指定

<%= link_to 'Title','http://www…./' %>

ルーティングの名前で指定

ルーティングの名前の後ろに_pathをつけてあげると同じアプリケーション内へのリンクを作成してくれる。

基本的な使い方。

$rails routesを実行したときに表示されるroute一覧を見て、Prefixの列に表示されている名前を指定してあげればOK。

# users#new
<%= link_to '新規登録', new_user_path %>

また、idを指定してあげることで特定のユーザーの詳細ページにリンクしたい場合などは、パスに引数として変数(この場合はuser)を渡してあげることで、 この変数に入っているユーザーデータのidを元にリンク先をいい感じに解釈して設定してくれる。

# users#show
<%= link_to User.Name, user_path(user) %>
リンク関連のビューヘルパーについて

qiita.com

link_to の他にもurl_for、link_to_if / link_to_unless、link_to_inless_current

を紹介してくれています。

その他ヘルパー

middlemanapp.com

画像にリンクを貼る

上記では、対象の文字列をクリックすることでリンク先に飛べるようになりますが、

画像にリンクをつけたい場合は、image_tagヘルパーというものを使用すれば良い。

また画像はassets/imagesディレクトリがデフォルトで用意されているのでそこに入れればOK。

画像の表示のみ
<%= image_tag 'image.png' %>

また、画像にクラスを指定したい場合は

<%= image_tag 'image.png' class: 'logo'%>

のように記述すれば適用させてくれる。

画像にリンク
<%= link_to image_tag('image.png'  class: 'logo'), root_path %>

このようにlink_toimage_tagを組み合わせると画像に対しリンクが貼られるようになる。

Rails基礎⑥ ビューの作成

ビューの作成

例えば、postsコントローラーのindexアクションに対応するviewはapp/view/posts/index.html.erbというファイルを作成する。

ERBとは?

Railsが用意しているテンプレートエンジンのこと。

これを使用することで、 <% %>Rubyソースコードとして実行することができたり、<%= %>とすることで、実行結果(コントローラーで定義したインスタンス変数等)が使用できるようになります。

記述ルール

www.code-magagine.com

viewの記述

controllerに

def index
  @posts = Post.all.order(created_at: 'desc')
end

とあった場合、@postsに取得したデータが入っている。

Post.allは内部で

SELECT "posts".* FROM "posts"

というSQLが発行されているし、 上記のPost.all.order(created_at: 'desc')では、

SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC

というSQLActiveRecordが代わりに発行してくれている。

そして、app/view/posts/index.html.erb

<h2>My Posts</h2>
<ul>
    <% @posts.each do |post| %>
    <li>
        <%= post.title %>
    </li>
    <% end %>
</ul>

とすると、以下のようなページが出来上がる。

f:id:hpsuzucat:20201020142939p:plain

rootパスの設定

先程のページはURLの最後に/postsをつけなければいけないが、

そのページがメインになる場合はrootパスに設定してあげることで、その必要がなくなる。

routes.rbにrootを設定する。

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  resources :posts
  
  root 'posts#index' #追加
end

基本レイアウトの設定

特に指定がない場合、アプリケーション全体でapp/views/layouts/application.html.erbというファイルが読み込まれる。

<!DOCTYPE html>
<html>
  <head>
    <title>Myblog</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

viewで書いたコードは上記の<%= yield %>の部分で読み込まれる。

また、CSSapp/assets/stylesheets/application.cssが読み込まれる。

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Myblog</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class="container">
    <%= yield %>
    </div>
  </body>
</html>

application.css

 .container {
     width:400px;
     margin: 20px auto;
 }
 
 body{
     font-family: Verdana, sans-serif;
     font-size: 14px;
 }
 
 h2{
     font-size: 16px;
     padding-bottom: 10px;
     margin-bottom: 15px;
     border-bottom: 1px solid #ddd;
 }
 
 ul > li {
     margin-bottom: 5px;
 }

とすると、以下のように表示されるようになる

f:id:hpsuzucat:20201020152515p:plain

Rails基礎⑤ コントローラーの作成

コントローラーの作成

$ rails g controller [コントローラー名]

Controllerでは複数のデータを扱うため、コントローラー名は複数形、頭文字は大文字にすること。

主に、controllerディレクトリにxxx_controller、viewディレクトリに新しいディレクトリ、テスト用のファイルなどが生成される。

ルーティングの設定

どのURLにアクセスされたときに、controllerのどのメソッドを実行するかを設定していく作業のこと。

config/routes.rbに記述していく。

一般的な処理を一気に設定したい場合

resources :名称[複]

なので、

Rails.application.routes.draw do
  resources :コントローラー名
end

でOK。

これで、 index,show,new,create,edit,update,delete の7種類のアクションが一気に定義することができる。

特定のルーティングのみを指定したい場合、

Rails.application.routes.draw do
  resources :コントローラー名, only: [:index, :show]
end

のようにonlyを使用する。

resource

resources とはまた別物となる。 indexアクションが定義されない、URI Pattersにidが含まれなくなる、といった違いがある。

Rails.application.routes.draw do
  resource :名称[単]
end

ルーティングの確認

$ rails routes

で一覧を確認できる。

Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index

だとすると、「/postsでgetでアクセスしてきたら、postsコントローラーのindexアクションを実行」という意味。

参考

qiita.com

controllerにアクションを記述する

app/controller/名称_controllerに記述していく。

メソッドの形で記述していく。 アクション名=メソッド名なので、アクションを作成する場合はアクション名のメソッドを定義する必要がある。

アクションを表すメソッドはpublicで作成する必要がある。(Rubyはデフォルトがpublicとなっている)

Postsを作成日時の新しい順に並べてすべて取得したい場合は以下のように記述する。

def index
  @posts = Post.all.order(created_at: 'desc')
end

Rails基礎④ 初期データの管理

DBの操作・確認

DBへの接続

$ rails dbconsole

もしくは、

$ rails db

デフォルトはSQLiteとなっている。

テーブルの確認

sqlite > .tables

モデル名Postのデータを確認する

sqlite > Select * From Posts;

※テーブル名は複数形であることに注意。

DB操作から抜ける

sqlite > .quit 

ファイルで初期データの管理をする

db/seeds.rb

 Post.create(title: "hogehoge",body:  "fugafuga")

これは、

post = Post.new(title: "hogehoge")
post.body = "fugafuga"
post.save

と同じで、ひとまとめにして登録ができる。

保存したい属性(カラム)をすべて引数で渡す必要がある。 登録できたかどうかをtrueまたはfalseで返却してくれる。

newを使用することで、生成したインスタンスを受け取ることができるので、 インスタンスが必要な場合はnew~saveを使用することも検討する。

他の記述方法、初期データの登録方法は以下のサイトが勉強になった。

www.javadrive.jp

テーブルの中身をクリア

$ rails db:migrate:reset

seeds.rbで作成したデータをDBに流し込む

$ rails db:seed

マイグレーションファイルについて

マイグレーションファイルはデータベースを生成する際の設計図のようなもの。 これを実行することにより、その内容に基づいてテーブルを生成してくれる。

$ rails g modelを実行したときに一緒に生成されるが、

マイグレーションファイルのみ生成したい場合は

$ rails g migration マイグレーション名

を実行する。

db:migrateを実行すると、形がほぼ完成してしまうので、あとで変更が難しくなってしまうため注意が必要(オプションやインデックスの追加等)。

Rails基礎③ モデルの作成

モデルの作成

$ rails generate model 名前 [カラム名:型] [オプション]

generateはgで省略することが出来るので、以下のようにも書ける

$ rails g model 名前 [カラム名:型] [オプション]
データ型
データ型 説明
string 文字列
text 長い文字列
integer 整数
float 浮動小数
decimal 精度の高い小数
datetime 日時
timestamp より細かい日時
time 時間
date 日付
binary バイナリデータ
boolean Boolean型
オプション
オプション 説明 デフォルト値
skip-namespace 名前空間をスキップする
old-style-hash 古いハッシュの形式を使う
-o, -orm=名前 使用するO/Rマッパー active_record
migration マイグレーションファイルを生成するか true
timestamps true
parent=名前
indexes true
-t, test-frameword=名前 使用するテストフレームワーク test_unit
fixtures フィクスチャを生成するか true
-r, fixture-replacement=名前 フィクスチャを変更
-f, force ファイルが存在する場合に上書き
-q, quiet 進捗状況を非表示
-p, pretend ドライラン
-s, skip 既に存在するファイルについてはスキップ
-h, help ヘルプを表示

 

例えば、タイトルと記事を持つブログアプリの場合

$ rails g model Post title:string body:text

また、モデルは個々のデータ構造を定義するため、名前を単数形にする

その後、データ構造を反映させるために

 $ rails db:migrate

を実行する。

データの格納

コンソールの起動
$ rails console

もしくは、省略記法を利用して

$ rails c
コンソールからデータを登録する

タイトル:title1、内容をbody1として登録したい場合、

コンソール上で

> p = Post.new(title: 'title 1', body: 'body 1') 
> p.save

と記述する。

Postは先程のモデルにつけた名前を指定。UserならUser.newとなる。

Post.new と p.save をわけずに、一度に書くことができる

> Post.create(title: 'title 2', body: 'body 2')

このように、SQLを発行しなくてもデータを格納できる仕組みを Active Record  という。

Active Recordとは

Railsが採用しているO/Rマッパーのこと。 Railsでは、テーブルごとに作成されたモデルクラスを通じてデータベースに接続する。

O/Rマッパーとは?

O/R(Object/Relational)マッピングの考えに基づいて実装されたライブラリ。 オブジェクト指向プログラミング言語からRDBにアクセスする際の架け橋となる仕組みのこと。 プログラミング言語で扱うクラス・オブジェクトとRDBで扱うテーブル同士のリレーションが異なる仕組みのため、 その違いを吸収するために考えられた。

Active Recordの主な機能
  • SQLを書かなくてもデータの検索、登録、更新、削除が出来る
  • RDBの関連付けをモデルクラスの関連付けとして表現することができる
  • データの検証機能を提供
コンソールを抜ける
> quit

とすれば、コンソールから抜けることができる。

モデルクラスとテーブルの命名ルール

モデルクラス名は単数形、テーブル名は複数形で表現すること。

2つ以上の単語を組み合わせたモデルクラスの場合、 テーブル名はアンダースコアで繋げた最後の単語を複数形とする決まり。

モデルクラス名 テーブル名
User users
UserItem user_items

テーブルのカラム名命名ルール

ActiveRecordでは、レコードを識別するためのカラムはデフォルトでidとなる。

ActiveRecordでテーブルを作成すると、自動的に追加される。

また、created_atupdated_atというカラムも同時に追加され、レコードの作成日時と更新日時が自動的に設定されるようになっている。

参考

railsdoc.com

いつもお世話になってます。