Railsガイドにきちんと目を通して新しい知識を得る - Action Controller の概要編 -

ドキュメントを読み込むのは大事、ということでRailsガイドを頭から読んでいく取り組みをしています。 各章ごとに、(Railsガイドにちゃんと書いてあるのに)知らなかった機能を雑にまとめていきます。

今回は、Action Controller の概要の章です。

railsguides.jp

wrap_parameters

リンクはこちら

パラメータを受け取るときに、パラメータがコントローラに応じたキー名でラップされるようになる。
これはデフォルトではJSONのリクエストの場合は機能するようになっているようです。

例えば、JSON{"title":"value1", "content":"value2"}を送ると、rails側で"book"=>{"title"=>"value1", "content"=>"value2"}のようにラップしてくれました。
ちなみに、falseを指定すると無効にできるみたいです。

class BooksController < ApplicationController
  wrap_parameters false
end

extract_value

リンクはこちら

Rails7.1から入ったメソッド。
複合主キーを持つモデルのため、1つのパラメータから値を配列にして返してくれます。

params
#=> #<ActionController::Parameters {"controller"=>"books", "action"=>"show", "id"=>"2_4"} permitted: false>

params.extract_value(:id)
#=> ["2", "4"]

permit!

リンクはこちら

パラメータのハッシュ全体を許可したい場合に使えます。
当然、セキュリティ面には注意する必要があります。

params
#=> #<ActionController::Parameters {"authenticity_token"=>..., "book"=>{"title"=>"本1", "content"=>"コンテンツ"}, "commit"=>"Create Book", "controller"=>"books", "action"=>"create"} permitted: false>
params.permitted?
#=> false

params.permit!
#=> #<ActionController::Parameters {"authenticity_token"=>..., "book"=>#<ActionController::Parameters {"title"=>"本1", "content"=>"コンテンツ"} permitted: true>, "commit"=>"Create Book", "controller"=>"books", "action"=>"create"} permitted: true>
params.permitted?
#=> true

flash.keep

リンクはこちら

flashを次のリクエストに引き継ぐ時などの使える、flashの寿命を伸ばすようなメソッドです。
scaffoldしたアプリで、showアクションにflash.keepと書いたら、createした後に何度リロードしてもフラッシュメッセージが表示されました。

before_actionのためのbeforeメソッドなど

リンクはこちら

例えばbefore_actionの処理内容を別クラスで実行するときにはbeforeという名前のクラスメソッドを、コントローラのインスタンスを引数に渡す形で作ってあげれば実行できるみたいです。
知らなかったですが、どこかで使える場面がありそうだなと思いました。

class Sample
  def self.after(controller)
    p 'after actionが実行された'
  end
end

以下のようにきちんと実行されていました。

Started GET "/books/1" for ...
Processing by BooksController#show as HTML
  Parameters: ...
  Rendering layout layouts/application.html.erb
  Rendering books/show.html.erb within layouts/application
  Rendered books/_book.html.erb (Duration: 1.3ms | Allocations: 179)
  Rendered books/show.html.erb within layouts/application (Duration: 6.8ms | Allocations: 1202)
  Rendered layout layouts/application.html.erb (Duration: 61.4ms | Allocations: 13927)
"after actionが実行された"
Completed 200 OK in 79ms (Views: 66.6ms | ActiveRecord: 3.4ms | Allocations: 18000)

authenticate_or_request_with_http_token

リンクはこちら

トークン所有の有無で認証するBearerトークンを利用可能にするもの。
Railsガイドのようにサンプルコードを書いて動かしたら、確かにアクセスできなくなりました。

HTTP Token: Access denied.

ライブストリーミング

リンクはこちら

ActionController::Liveを使うことでライブストリーミングを利用できるようになります。
例えば以下のように書いたら、1秒ごとに現在時刻が表示されました。

def show
  response.headers['Content-Type'] = 'text/event-stream'
    100.times {
      response.stream.write "#{Time.current}\n"
        sleep 1
      }
ensure
  response.stream.close
end

filter_parameters

リンクはこちら

ログに出力される情報をfilter_parametersで制御できます。
私がrails newした環境では、デフォルトでconfig/initializers/filter_parameter_logging.rbに以下のように記載されていました。

# Be sure to restart your server when you modify this file.

# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
# Use this to limit dissemination of sensitive information.
# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [
  :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
]

試しに、ここに:titleを追加してログを見てみたところ、以下のように[FILTERED]となっていました。
デフォルトの設定のままになっていることも多そうなので、一度自分のアプリケーションを見直してみても良さそうだなと思いました。

Started POST "/books" for ...
Processing by BooksController#create...
  Parameters: {"authenticity_token"=>"[FILTERED]", "book"=>{"title"=>"[FILTERED]", "content"=>"内容4"}, "commit"=>"Create Book"}
...