Skip to content

Instantly share code, notes, and snippets.

@willnet
Last active January 21, 2025 00:31
Show Gist options
  • Save willnet/14656af4998047b853353e6be8009836 to your computer and use it in GitHub Desktop.
Save willnet/14656af4998047b853353e6be8009836 to your computer and use it in GitHub Desktop.
Rails8.0のマイナーフィーチャーで気になったところ

これはなに

Railties

scriptディレクトリが復活した

rails gでモデルを作るときにnot null制約を指定できる方法が追加された

permission policyのテンプレートが消えた

rails newしたときにapp/channels/* が生成されないようになった

lib/assets の廃止

Railsにおける正規表現実行時間のデフォルトの上限が1秒になった

rails notesの結果がブラウザでも確認できるようになったぞ

デフォルトのエラーページのデザイン変更

/upはログ出力の対象外にする

rails statsの対象を増やす公式apiが追加された

Action Dispatch

config/routes.rbの読み込みが遅延されるようになった

get "/users" => "users#index"のような記法がdeprecatedになった

Action Controller

ETagとLast-Modifiedが両方指定されたときの振る舞いが変わる

Cache-Control immutable の対応がはいった

allow_browserのオプション拡張

strong parameter用のメソッド改善

user_params = params.require(:user).permit(:name, :age)
  • userは必須で、そこから先のnameとageだけフィルタリングする
  • しかしこの書きかただと、↓のようなクエリで4xxではなく500になってしまう
/path?user=string
  • params.require(:user) #=> "string"になってしまうため、後続のpermitでNoMethodErrorになる
  • 主にこれを解決するために新しいメソッドであるexpectが導入された
user_params = params.expect(user: %i[name age])
  • これだと、先程のクエリではNoMethodErrorではなくActionController::UnpermittedParametersになり、(適切にエラーハンドリングしていれば)4xxになる
  • 1メソッドだけですむので学習コストも下がる
  • 追加機能として、パラメータ中に配列が含まれているときの判定が厳密になる、というのもある
# Hash is expected with `permit`
Parameters.new(user: { name: "Martin" }).permit(user: [:name]).require(:user)
# => {"name"=>"Martin"}
Parameters.new(user: [{ name: "Martin" }]).permit(user: [:name]).require(:user)
# => [{"name"=>"Martin"}]

# Hash is expected with `expect`
Parameters.new(user: { name: "Martin" }).expect(user: [:name])
# => {"name"=>"Martin"}
Parameters.new(user: [{ name: "Martin" }]).expect(user: [:name])
# => param is missing or the value is empty: user (ActionController::ParameterMissing)
  • permitだと、nameが配列でもそうでなくてもOKになっているけど、expectの場合は配列だとエラーになる
  • 配列を指定したい場合はParameters.new(user: [{ name: "Martin" }]).expect(user: [[:name]])のように書く
  • 今後はrequireとpermitよりexpectを推奨
    • requireやpermitがdeprecatedになる、というのは今のところ予定にない

rate_limitを同一コントローラに複数定義できるようになった

  • Add ability to use multiple rate limits per controller by fatkodima · Pull Request #52960 · rails/rails
  • rate_limitでカウンタとして利用するキーはコントローラごとに基本同一なものが使われているため、例えば同一コントローラ中のshowアクションとcreateアクションで別々のrate limitをかけたい、という要求に答えられなかった
  • ↓のようにnameオプションを指定すると、それがキーの一部として使われるのでこの問題を解決できる
class SessionsController < ApplicationController
  rate_limit to: 3, within: 2.seconds, name: "short-term"
  rate_limit to: 10, within: 5.minutes, name: "long-term"
end

Active Model

外部APIからモデルに値を渡しているときに、APIの戻り値が変わってもエラーにしないができるようになった

  • Introduce ActiveModel::AttributeAssignment#attribute_writer_missing by seanpdoyle · Pull Request #52417 · rails/rails
  • ActiveModel::AttributeAssignmentによって生えるassign_attributesは、単に渡されたキーと値でアサインしていくメソッド
  • hoge: 'fuga'が渡されたらmodel.hoge = 'fuga'が実行される
  • なので属性として定義していないものが渡されるとエラーになる
    • ActiveModel::UnknownAttributeError
  • しかし外部APIを叩いて戻り値をモデルにアサインするようなケースでは、外部APIの仕様変更でいきなりエラーになる可能性がある
    • 困る
    • attribute_writer_missingというメソッドを上書きすることで、ActiveModel::UnknownAttributeErrorを発生させずログやSentryに通知するだけで済ませることができるようになる
class Rectangle
  include ActiveModel::AttributeAssignment

  attr_accessor :length, :width

  def attribute_writer_missing(name, value)
    Rails.logger.warn "Tried to assign to unknown attribute #{name}"
  end
end

rectangle = Rectangle.new
rectangle.assign_attributes(height: 10) # => Logs "Tried to assign to unknown attribute 'height'

Active Record

validationを実行するコンテキストを決めるonの逆バージョンのexcept_onが追加された

関連先を取得するクエリを非同期に発行する

sqlite3で全文検索エンジンをやりやすくなった

dbconsole時のクライアントツールを変更できるようになった

Rails.application.configure do
 config.active_record.database_cli = { postgresql: "pgcli" }
end

バッチ処理で主キー以外を使えるようになった

Product.in_batches(cursor: [:shop_id, :id]) do |relation|
  # do something with relation
end
  • これまで主キーで順番にやっていたのが、主キー以外も指定できるようになった
  • in_batchesだけじゃなくてfind_each, find_in_batchesでも同様
  • 順番に意味がある(positionみたいなカラムがある)ようなケースで有用

Active Support

class_attributeで定義した変数へのアサインが高速化された

Action View

check_box -> checkbox

text_area -> textarea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment