Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rails 7.1 の新機能が使いたくて調べてみた
Search
Sho Ezawa
January 19, 2024
Programming
1
310
Rails 7.1 の新機能が使いたくて調べてみた
「【Techouse × Leaner共同開催】Ruby / Rails勉強会」での登壇資料
https://techouse.connpass.com/event/305572/
Sho Ezawa
January 19, 2024
Tweet
Share
More Decks by Sho Ezawa
See All by Sho Ezawa
デザインエンジニア?を模索している話
glico800
1
61
詳細度調整擬似クラスの使い所を考えてみた
glico800
1
1.1k
なぜスタートアップで部活をやるのか
glico800
0
460
Figmaで作る動くペーパープロトタイプ
glico800
0
600
弱いパスワードの作り方
glico800
1
160
Other Decks in Programming
See All in Programming
Interface vs Types ~型推論が過多推論~
hirokiomote
1
230
❄️ tmux-nixの実装を通して学ぶNixOSモジュール
momeemt
1
120
TypeScript だけを書いて Tauri でデスクトップアプリを作ろう / Tauri with only TypeScript
tris5572
2
530
ワンバイナリWebサービスのススメ
mackee
10
7.4k
AIにコードを生成するコードを作らせて、再現性を担保しよう! / Let AI generate code to ensure reproducibility
yamachu
7
6k
衛星の軌道をWeb地図上に表示する
sankichi92
0
250
ワイがおすすめする新潟の食 / 20250530phpconf-niigata-eve
kasacchiful
0
180
推論された型の移植性エラーTS2742に挑む
teamlab
PRO
0
150
メモリリークが発生した時にpprofを使用して原因特定した話
zono33lhd
0
100
AI時代のリアーキテクチャ戦略 / Re-architecture Strategy in the AI Era
dachi023
0
190
Blueskyのプラグインを作ってみた
hakkadaikon
1
280
UPDATEがシステムを複雑にする? イミュータブルデータモデルのすすめ
shimomura
0
170
Featured
See All Featured
A designer walks into a library…
pauljervisheath
205
24k
Java REST API Framework Comparison - PWX 2021
mraible
31
8.6k
Become a Pro
speakerdeck
PRO
28
5.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.2k
GraphQLとの向き合い方2022年版
quramy
46
14k
RailsConf 2023
tenderlove
30
1.1k
Optimizing for Happiness
mojombo
378
70k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Building a Modern Day E-commerce SEO Strategy
aleyda
40
7.3k
The World Runs on Bad Software
bkeepers
PRO
68
11k
Documentation Writing (for coders)
carmenintech
71
4.8k
Fireside Chat
paigeccino
37
3.5k
Transcript
Rails 7.1 の新機能が使いた くて調べてみた 【Techouse × Leaner共同開催】Ruby / Rails勉強会 2024/01/19
Fri. @glico800
登壇者情報 @glico800 Leaner Technologies Inc. デザインエンジニア フロントエンドの実装が中心 バックエンドも勉強中 TypeScript, React,
Ruby, Ruby on Rails 動物好き
ちょっと会社の話(1/2) Leaner Technologies Inc. は 調達DXの会社 Leaner見積とLeaner購買という2つのプロダクト
ちょっと会社の話(2/2) 私はLeaner購買の開発チーム Leaner購買は Rails 7.1.1
せっかくチームがアップデートを頑張ってくれているので Rails 7.1 の新機能が 使いたい!!
もくじ 1. ActiveRecord::Base.normalizes 2. 汎用の非同期クエリを対象とするActive Record API 3. まとめ 個人的に業務に使いそうな機能をピックアップ
1. ActiveRecord::Base.normalizes
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
正規化のタイミング (1/3) attribute の assign/update 1 user = User.find(1) 2
user.email = "
[email protected]
\n" 3 user.email # => "
[email protected]
" 4 5 user.update(email: "
[email protected]
\n") 6 user.email # => "
[email protected]
"
正規化のタイミング (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) 明示的に呼ぶ 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")
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
2. 汎用の非同期クエリを対象とする Active Record API
非同期クエリがサポート拡張 集計メソッド async_count , async_count_by_sql async_minimum , async_maximum async_sum async_average
検索メソッド async_pick async_find_by_sql async_pluck async_ids
使い方 非同期なカウント 同期的なカウント 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
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)
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
どんなときに使いそうか データ分析機能 重いクエリを複数実行する ActiveRecord::Relation を返さないメソッドが多い 集計期間が長い集計機能ほど恩恵が大きい 例:Leaner見積の年間コストインパクト等の算出 (↑ 開発合宿で実際にパフォーマンス向上に成功していた) 今回の非同期クエリの実装者は
Shopify のエンジニアさん (Shopify でも使っているのかも)
まとめ
Rails 7.1 でよく使いそうな新機能 ActiveRecord::Base.normalizes での正規化 before_validation を使って書くより簡単 キーワード引数以外の ActiveRecord::FinderMethods は正規化されない
normalizes の追加前に保存された値は正規化されない 汎用の非同期クエリを対象とする Active Record API load_async ではできなかった集計処理が非同期化できる async_query_executor の設定を忘れずに データ分析機能で活躍しそう
一緒に働くエンジニアを募 集しています! Leaner のプロダクトに興味があれば ぜひお声掛けください!🍖
おわり