Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails 7.1 の新機能が使いたくて調べてみた

Sho Ezawa
January 19, 2024

Rails 7.1 の新機能が使いたくて調べてみた

「【Techouse × Leaner共同開催】Ruby / Rails勉強会」での登壇資料
https://techouse.connpass.com/event/305572/

Sho Ezawa

January 19, 2024
Tweet

More Decks by Sho Ezawa

Other Decks in Programming

Transcript

  1. ActiveRecord::Base.normalizes で正規化 before after 1 class User < ActiveRecord::Base 2

    before_validation :normalize_email 3 4 private 5 6 def normalize_email 7 email.strip.downcase 8 end 9 end 1 class User < ActiveRecord::Base 2 normalizes :email, with: -> email { email.strip.downcase } 3 end
  2. 正規化のタイミング (2/3) ActiveRecord::FinderMethods 1 User.find_by(email: "[email protected]").count # => 1 2

    3 # キーワード引数には適用される 4 User.find_by(email: "\[email protected] ").count # => 1 5 User.where(email: "\[email protected] ").count # => 1 6 User.exists?(email: "\[email protected] ") # => true 7 8 # プレースホルダには適用されない 9 User.where(["email = ?", "\[email protected] "]).count # => 0 10 User.exists?(["email = ?", "\[email protected] "]) # => false
  3. 正規化のタイミング (3/3) 明示的に呼ぶ Model.normalize_value_for から呼ぶことも可 see: activerecord/lib/active_record/normalization.rb 1 # normalizes

    の追加前に保存された値は正規化されない 2 legacy_user = User.find(1) 3 legacy_user.email # => " [email protected]\n" 4 5 # 明示的に呼ぶことで正規化 6 legacy_user.normalize_attribute(:email) 7 legacy_user.email # => "[email protected]" 8 legacy_user.save 1 User.normalize_value_for(:email, " [email protected]\n")
  4. nil の扱い apply_to_nil オプションを付けると nil のときも正規化される nil のときは正規化は適用されないのでエラーにはならない 1 class

    User < ActiveRecord::Base 2 # デフォルトでは nil 考慮は不要 3 normalizes :email, with: -> email { email.strip.downcase } 4 end 3 normalizes :email, with: -> email { email&.strip&.downcase }, apply_to_nil: true 1 class User < ActiveRecord::Base 2 # nil の考慮が必要になる 4 end
  5. 使い方 非同期なカウント 同期的なカウント 1 published_count = Post.where(published: true).count # =>

    10 2 3 # 他の処理たち... 4 5 published_count 1 # <ActiveRecord::Promise status=pending> を返す 2 promise = Post.where(published: true).async_count 3 4 # 他の処理たち... 5 6 promise.value # => 10
  6. load_async との違い 逆に ActiveRecord::Relation を返さないメソッドでは load_async は使えない ActiveRecord::Relation を返すメソッドでは load_async

    が使える 1 orders = Order.where(user_id: user.id).load_async 2 requisitions = user.requisitions.approved.load_async 1 # NG => undefined method `load_async' for ... 2 ng_count = Order.shipped.count.load_async 3 ng_requisition_ids = Requisition.approved.pluck(:id).load_async 4 5 # OK 6 count = Order.shipped.async_count 7 requisition_ids = Requisition.approved.async_pluck(:id)
  7. config/application.rb 1. async_query_executor これを設定しないと非同期クエリが流れない 2. global_executor_concurrency async_query_executor が :global_thread_pool のときの並行実行数上限

    上限アップの際はサーバーリソースと要相談 1 # 設定値は :global_thread_pool or :multi_thread_pool ( 初期値: nil) 2 config.active_record.async_query_executor = :global_thread_pool 1 # ( 初期値: 4) 2 config.active_record.global_executor_concurrency = 5
  8. Rails 7.1 でよく使いそうな新機能 ActiveRecord::Base.normalizes での正規化 before_validation を使って書くより簡単 キーワード引数以外の ActiveRecord::FinderMethods は正規化されない

    normalizes の追加前に保存された値は正規化されない 汎用の非同期クエリを対象とする Active Record API load_async ではできなかった集計処理が非同期化できる async_query_executor の設定を忘れずに データ分析機能で活躍しそう