はじめに
Rails 6 に追加された新機能を試す第119段。 今回は、filter_parameters
編です。
Rails 6 では、 filter_parameters で proc を使って、フィルターしたときに、パラメータが配列になっているときに、フィルターされないというバグが修正されています。
Ruby 2.6.5, Rails 6.0.2.1, Rails 5.2.4.1 で確認しました。 (Rails 6.0.0 でこの修正が入っています。)
$ rails --version
Rails 6.0.2.1
今回は、User を2つ登録する画面を作って、その動作を確認します。
なお、 filter_parameters
の動作を確認するための手抜き実装になってます。
Rails プロジェクトを作る
Rails プロジェクトを新たに作成します。
$ rails new rails_sandbox
$ cd rails_sandbox
User モデルを作る
name
を持つ User モデルを作成します。
$ bin/rails g model User name
Controller と View を作る
User の controller と View を作ります。 View は手抜き実装で、 一覧画面 (index) と 登録画面 (new) だけです。
$ bin/rails g controller Users index new
routes を定義する
User 用にルーティングを定義します。 これまた、手抜き実装で、 index
, new
, create
の3つだけにします。
Rails.application.routes.draw do
resources :users, only: %i[index new create]
end
一覧画面 (index) を作成する
一覧画面を作成します。これまた、 table
タグも使わない手抜き実装です。
User
の name
を1件ずつ表示します。
画面の下に、登録画面へのリンクを表示します。
<h1>Users#index</h1>
<% @users.each do |user| %>
<p>
<%= user.name %>
</p>
<% end %>
<%= link_to 'New', new_user_path %>
登録画面 (new) を作成する
登録画面を作成します。ここで、今回の機能を試すためにパラメータの値が配列になるようにします。
(結果として2件のデータを登録することになります。)
パラメータが配列となるように、form.text_field
の引数が name="names[]"
としていることに注意してください。
これが、今回の機能を試すために必要なことの1つです。
<h1>Users#new</h1>
<%= form_with url: users_path do |form| %>
<p>
<%= form.text_field name="names[]" %>
</p>
<p>
<%= form.text_field name="names[]" %>
</p>
<%= form.submit %>
<% end %>
UsersController を完成させる
今回の機能を確認するために、完成させる必要は無いのですが、一応、動作するように実装します。
これまた、手抜き実装です。
index
メソッドでは、全データを取得します。
create
メソッドでは、パラメータを元にして User をデータベースに保存し、一覧画面にリダイレクトします。
class UsersController < ApplicationController
def index
@users = User.all
end
def new
end
def create
params[:names].each do |name|
User.create(name: name)
end
redirect_to users_path
end
end
filter_parameters を指定して、 names パラメータの値がフィルタリングさせる
いよいよ、今回の機能を確認するために、 filter_parameters
で names
パラメータの値をフィルタリングさせます。
proc を追加していることに注意してください。
...
module App
class Application < Rails::Application
...
config.filter_parameters << lambda do |key, value|
if key =~ /names/
value.replace('[FILTERED]') if value.respond_to?(:replace)
end
end
end
end
マイグレーションを実行する
$ bin/rails db:create db:migrate
rails server を実行して、登録画面から登録する
bin/rails s
を実行し、 http://localhost:3000/users/new
にアクセスし、2つのフィールドに適当に入力して、 Save
ボタンを押します。
このとき、コンソールでは、 names
パラメータが、 [FILTERED]
となっていることに注意してください。
Started POST "/users" for 192.168.16.1 at 2020-01-25 02:48:55 +0000
Processing by UsersController#create as JS
Parameters: {"authenticity_token"=>"..., "names"=>["[FILTERED]", "[FILTERED]"], "commit"=>"Save "}
(0.2ms) BEGIN
Rails5 では
Rails 5.2.4.1 では、 フィルターされず、そのまま画面で入力した値が表示されてしまいます。
Started POST "/users" for 192.168.0.1 at 2020-01-25 01:42:25 +0000
Processing by UsersController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"..., "names"=>["aaa", "bbb"], "commit"=>"Save "}
あくまで手抜きのコードです
実際のアプリでは、複数のデータを1つの画面で登録する場合には、 Form オブジェクトを使ったり、Validation を追加したり、Strong Paramters を使ったりすると思います。
今回は、あくまでも、機能の確認のための実装なので、そういった点は、すっとばして、手を抜いてます。
このままコードを再利用することはオススメしません。
試したソース