3月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のDMM WEBCAMP(旧WEBCAMP PRO)。
2月生は満員となっております。3月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

はじめに

Railsの学習を進めていく中で、ディレクトリやファイルの構成、モデルやコントローラ、Viewの関係などは、みなさん注目しています。

しかし、プログラムの要であるデータの入出力については、案外さらりと流してしまっているだけの人もいるのではないでしょうか?

Railsは他のプログラム言語と違ってフレームワークが暗黙のうちに作り出した変数などがあり、プログラムコードを読むだけでは理解が難しい部分もあります。

じつは、今回解説するparamsも、それらフレームワークが暗黙のうちに作り出したものの1つなのです。

そんなparamsについて、詳しく説明していきます。

paramsによるデータの受け取り

paramsにはハッシュ形式でデータが格納されており、Railsのページ遷移で情報をやりとりするときに使われています。

つまり、paramsを理解することで、Railsアプリケーションのページ遷移時のデータの流れを理解できるということです。プログラムはデータを扱う処理がほとんどですので、データの流れが分かれば、それはプログラムを理解したといっても過言ありません。

paramsはそれほど重要な、Railsの要なのです。

Railsアプリケーションへのアクセスというのは、基本的にはいくつかのリクエストに分けられます。

それらのリクエストのパターンをまとめて、パターンごとの動作を整理しているのがroutes.rbファイルです。

routes.rbの詳細は、「【Rails入門説明書】routesについて解説」で説明していますので、詳細は割愛しますが、今回はルーティングで呼び出される側の説明だと思えばイメージしやすいのではないでしょうか。

データの格納場所

Webアプリケーションの弱点は、ページ遷移するときの情報のやりとりにいくつかの手法が存在することです。

それは、URLの一部にデータを載せる方法やクエリ(URLの末尾に?を付けた後に記載して直接渡す方法)、POSTでのデータ送信など、できることもやり方も違う方法が存在しているのです。

そして、このどれかを選ぶのではなく、このすべてに対応することで、ユーザーの利便性が上がります。そのため、Webアプリケーションの作成は、それぞれのデータのやりとりについて検討し、実装しなければいけません。

Railsでは、そんな面倒なデータのやりとりの方法を意識することなく、データをハッシュ形式のparamsで送受信することができるのです。

環境構築

Railsのparamsを使ったデータのやりとりについては、ただ説明を読むよりも、実際に動きを見ながら手を動かした方が圧倒的に分かりやすくなります。

そのため、まずはテスト環境を作っておきましょう。

rails new params_test
cd params_test
rails generate scaffold User name:string age:integer
rake db:migrate
rails c
User.create(name:"Ryosuke",age:18)
User.create(name:"Daigo",age:23)
User.create(name:"Hiroshi",age:35)
exit

次に、リクエストの内容を確認できるように、ログを仕込んでおきます。(loggerについては、「【Rails入門説明書】loggerについて解説」を参照してください)
(app/controllers/application_controller.rb)

class ApplicationController < ActionController::Base
  before_action :http_header_log

  private
    def http_header_log
     logger.info("Request: #{request.headers}")
    end
end

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】

GETリクエスト

Railsアプリケーションへのもっとも単純なアクセスが、GETリクエストによるアクセスでしょう。

このとき、GETリクエストとともに渡すURLにパラメータを含めて渡すことができ、そのパラメータをparamsを経由して取得することができます。

具体的な動作を見てみましょう。

テスト環境のサーバを起動し、ブラウザのURL欄に「localhost:3000/users/1」と入力してみてください。

ここでURLの末尾にある「1」がパラメータです。このパラメータが「1」であるため、1つめに登録されたデータが表示されています。

ログも確認してみましょう。(以降、ログは必要な部分だけ抜粋して表示しています)

Started GET "/users/1" for 0.0.0.0 at YYYY-mm-DD HH:MM:SS +0900
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}

パラメータが「Parameters: {"id"=>"1"}」として渡されていることが分かります。

つまり、アクセスするURLを「/users/2」に変更すれば、「2」が渡されて、2つめに登録した「Daigo」が表示されることになるわけです。

(ログ)

Started GET "/users/2" for 0.0.0.0 at YYYY-mm-DD HH:MM:SS +0900
Processing by UsersController#show as HTML
  Parameters: {"id"=>"2"}

この動作を理解するため、まずは「rails routes」コマンドで、ルーティングを確認してみましょう。

   Prefix Verb   URI Pattern                Controller#Action
    users GET    /users(.:format)           users#index
          POST   /users(.:format)           users#create
 new_user GET    /users/new(.:format)       users#new
edit_user GET    /users/:id/edit(.:format)  users#edit
     user GET    /users/:id(.:format)       users#show
          PATCH  /users/:id(.:format)       users#update
          PUT    /users/:id(.:format)       users#update
          DELETE /users/:id(.:format)       users#destroy
           :

今回アクセスした「/users/1」は、以下のルーティングにマッチします。

     user GET    /users/:id(.:format)       users#show

ちょうど、「:id」のところに「1」を記載してアクセスしていますので、「Parameters: {"id"=>"1"}」になると考えれば、分かりやすいのではないでしょうか。

では次に、このルーティングによって実行されるコントローラのアクションメソッド「users#show」を確認しましょう。
(app/controllers/users_controller.rb)

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
   :
  def show
  end
    :
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end
    :

showメソッドそのものは何もしていませんので、処理の実体は、「before_action :set_user, only: [:show, :edit, :update, :destroy]」によって実行されているset_userメソッドです。

set_userメソッドは、「params[:id]」で絞り込んだレコードを取得して、@userへ代入しています。

そして、この「params[:id]」が、ログの「Parameters: {"id"=>""}」にあたり、「/users/1」でアクセスした場合は、「@user = User.find(1)」というコードと同等になるわけです。
※なお、「{"id"=>"1"}」というログの通り、取得できるのは文字列です。もし数値として処理するのであれば、「to_i」などで変換しなければいけませんので気を付けましょう。

クエリ

多くのサイトで使用されている「クエリ」でのパラメータ渡しについても、paramsを利用して取得することができるようになっています。

Viewファイルを少し修正して、確認してみましょう。
(app/views/users/show.html.erb)

<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>

<p>
  <strong>Age:</strong>
  <%= @user.age %>
</p>

<p><strong>Query val:</strong><%= params[:val] %></p>  <!-- (1) -->

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

(1)の1行を追記します。

その上で、ブラウザのURLに「http://localhost:3000/users/2?val=query_val」を入力してアクセスしてみましょう。

(ログ)

Started GET "/users/2?val=query_val" for 0.0.0.0 at YYYY-mm-DD HH:MM:SS +0900
Processing by UsersController#show as HTML
  Parameters: {"val"=>"query_val", "id"=>"2"}

このように、クエリを使っても、同じようにparamsにパラメータがハッシュ形式で設定されていることが分かります。

未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】

POSTリクエスト

POSTリクエストは、フォームからの入力で「送信」ボタンを押した場合などに発生するリクエストです。

そのため、POSTリクエストは、GETリクエストより多くのパラメータを送信することになります。

GETリクエストの場合と同様に、動作を確認してみましょう。

POSTの場合は、新規登録画面で「Create User」ボタンを押すところから見ていきます。

(localhost:3000/users/new)にアクセスして、フォームに入力して「Create User」ボタンを押します。

(「Create User」ボタン押下時のログ)

Started POST "/users" for 127.0.0.1 at 2018-11-06 22:03:27 +0900
Processing by UsersController#create as HTML
  Parameters: {.., "user"=>{"name"=>"Keito", "age"=>"25"}, ..}
    :

対象のルーティングは以下です。

          POST   /users(.:format)           users#create

つまり、実行されるコントローラのアクションメソッドは、「users#create」になります。プログラムコードを確認しましょう。
(app/controllers/users_controller.rb)

     :
  def create
    @user = User.new(user_params)

       (省略)
  end
      :
    def user_params
      params.require(:user).permit(:name, :age)
    end
      :

createメソッドでUserモデルをnewで生成しています。そのときに渡されている引数がparamsであり、ログに出力されている「{"name"=>"Keito", "age"=>"25"}」なのです。

ここでは、user_paramsメソッドが渡されていますが、その戻り値は[カラム名=>値,..]ですので、paramsと同じものになります。

例えば、以下のようにログを追記して確認すれば、同じであることが確認できるでしょう。
(app/controllers/users_controller.rb)

     :
  def create

    logger.info("user_params : #{params.require(:user).permit(:name, :age)}")
    logger.info("params : #{params[:user]}")

    @user = User.new(user_params)

       (省略)
  end
     :

(ログ)

    :
user_params : {"name"=>"Keito", "age"=>"25"}
params : {"name"=>"Keito", "age"=>"25"}
    :

ストロングパラメータ

user_paramsとparams[:user]が同じであれば、以下のように修正しても動作するように思えるのではないでしょうか。
(app/controllers/users_controller.rb)

     :
  def create
#    @user = User.new(user_params)
    @user = User.new(params[:user])

       (省略)
  end
      :

しかし、この修正を行って実行してみると、次のような「ActiveModel::ForbiddenAttributesError 」という例外が発生してしまうのです。

これは、Rails4から導入された「ストロングパラメータ」というセキュリティ対策のためで、テーブルに登録、更新するすべてのデータは、このストロングパラメータによる検証をクリアしなければ、登録できなくなっているのです。

そのため、直接paramsを与えても、上記のような例外が発生して、登録することができなくなっています。

この検証内容は、user_paramsメソッドの内容の通りです。
(app/controllers/users_controller.rb)

      :
    def user_params
      params.require(:user).permit(:name, :age)
    end
      :

user_paramsメソッドに記載のある1行は、「paramsが:userというキーを持っていて、かつparams[:user]が、:nameと:ageというキーを持つハッシュである」ことを確認しています。

そして、許可されたキーのハッシュが戻り値として返されます。

つまり、ストロングパラメータは、「モデルに含まれる登録可能なカラムを特定し、それ以外のカラムへのアクセスを禁止するしくみ」といえるでしょう。

ストロングパラメータの存在理由

そもそも、なぜこのように面倒な手続きを踏む必要があるかというと、それは「Mass-assignment」という脆弱性への対策です。

「Mass-assignment」というのは、テーブルにあるが、本来はユーザーが更新することができないカラム(user_idや識別子、削除フラグなど)を、フォームの入力欄にスクリプトタグなどを使って更新することができる脆弱性です。

ストロングパラメータの検証を利用することで、許可されたカラムしか登録、更新することができませんので、この問題を回避することができます。

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー

まとめ

今回は、paramsについて説明しました。

あまり目立った機能ではないかもしれませんが、paramsは、Railsの動作の要ともいえるものです。

そのため、paramsを理解するということは、Railsアプリケーションのデータの流れを理解するということになり、paramsを意識することで、Railsアプリケーションの理解がより深まります。

ただし、データの流れは、そのままでは目で見て確認することができませんので、今回紹介したように、loggerを活用して確認することをおすすめします。
(loggerについては、「【Rails入門説明書】loggerについて解説」を参照してください)

・paramsはデータのやりとりに使われるハッシュ
・paramsはハッシュ形式でデータを保持する
・paramsが使われるシーンは、ページ遷移時
・GETリクエストのクエリなどのパラメータを取得できる
・POSTリクエストのデータを取得できる
・POSTリクエストで受け取ったデータをそのままテーブルへ登録すると、「Mass-assignment」のリスクがあるため、必ずストロングパラメータの検証を行わなければいけない

DMM WEWBCAMPについて

DMM WEBCAMPは3ヶ月間で未経験から即戦力エンジニアを育成する転職保障付きのプログラミングスクールです。1ヶ月でプログラミング・Webデザインを学ぶ通い放題の「ビジネス教養コース」も展開しています。

DMM WEBCAMPを運営する株式会社インフラトップ では、「学びと仕事を通して人生を最高の物語にする」という理念で会社を経営しています。

キャリアアップを目指す方は、この機会に私達と一緒にプログラミングを学んでみませんか?

3月枠も残りわずか当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のDMM WEBCAMP(旧WEBCAMP PRO)。
2月受入枠は満員となっております。3月枠に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

▼未経験から1ヶ月でWEBデザイン・プログラミングを学びたい方はこちら!

 

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

おすすめの記事