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
テーブル分割で実現するdeviseの責務の分離と柔軟な削除機構
Search
なおと
October 30, 2023
Programming
1
940
テーブル分割で実現するdeviseの責務の分離と柔軟な削除機構
なおと
October 30, 2023
Tweet
Share
More Decks by なおと
See All by なおと
プロジェクトマネジメントとは? 経験から学ぶ視野と視座
naotocoding
0
770
Stripeノーコード挑戦記決済画面構築の山あり谷あり
naotocoding
0
16
大規模プロジェクトに学ぶ、新卒エンジニアの教訓
naotocoding
0
26
Other Decks in Programming
See All in Programming
Memory API: Patterns, Use Cases, and Performance
josepaumard
1
140
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
1.2k
Делим тесты между QA и разработчиком
mariyasaygina
0
530
AWS Lambda Web Adapterを活用する新しいサーバーレスの実装パターン
tmokmss
6
5.9k
ファーストペンギンBot @Qiita Hackathon 2024 予選
dyson_web
0
220
実践Dash - 手を抜きながら本気で作るデータApplicationの基本と応用 / Dash for Python and Baseball
shinyorke
2
260
CSC305 Lecture 01
javiergs
PRO
1
150
Beyond Laravel Octane - Hyperf for Laravel Artisans
albertcht
1
130
Cohesion in Modeling and Design
mploed
3
200
UnJSで簡単に始めるCLIツール開発 / cli-tool-development-with-unjs
aoseyuu
2
250
文化が生産性を作る
jimpei
3
550
PHPを書く理由、PHPを書いていて良い理由 / Reasons to write PHP and why it is good to write PHP
seike460
PRO
5
450
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
65
11k
Documentation Writing (for coders)
carmenintech
65
4.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
What's in a price? How to price your products and services
michaelherold
243
11k
Become a Pro
speakerdeck
PRO
24
4.9k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
25
660
It's Worth the Effort
3n
183
27k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Designing for Performance
lara
604
68k
Speed Design
sergeychernyshev
22
480
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
130k
Transcript
テーブル分割で実現する Deviseの責務の分離と柔軟な削除機構 Kaigi on Rails 2023 なおと 2023/10/28
⾃⼰紹介 • サーバーサイドエンジニア • Doorkeeperが好き • エンジニア2年⽣、初登壇 @NaotoCoding なおと
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
その前に。 Deviseにおけるusersテーブルの分割については、 jokerさんのブログ記事 「パーフェクトRails著者が解説するdeviseの現代的なユーザー 認証のモデル構成について」 を参照し、⾃分の中で噛み砕きながらDeviseのテーブル構造に ついて考えました。 https://joker1007.hatenablog.com/entry/2020/08/17/141621
1. Deviseにおけるusersテーブルの分割
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
• 認証機構を簡単に作成可能にするgem • サインイン • サインアップ • サインアウト • ユーザーの記憶
• gem Wardenがベース a. Deviseとは 引⽤: https://github.com/heartcombo/devise
• 様々なオプションが提供されている • メール確認機能 • ログイン複数回失敗時にロック • オプションもとても簡単に有効化可能 • テーブルにカラムを追加
• モデルクラスでモジュールを使⽤するだけ 引⽤: https://github.com/heartcombo/devise a. Deviseとは
とても便利で超有名なgem 新規アプリ開発時には毎回お世話になっている a. Deviseとは
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
b. Deviseをこんな⾵に使いたいな 1. 1つのモデルクラスが1つの責務を担当するようにしたい 2. 雑な独⾃実装で不要な情報露出を⾏わせない
Deviseはさまざまなオプション機能を提供している • メール確認 • ログイン複数回失敗時ににロック 1. 1つのモデルクラスが⼀つの責務を担当するようにしたい b. Deviseをこんな⾵に使いたいな
Deviseはさまざまなオプション機能を提供している → 機能を追加するためにUserクラスでモジュールを読み込む 1. 1つのモデルクラスが⼀つの責務を担当するようにしたい b. Deviseをこんな⾵に使いたいな
Deviseはさまざまなオプション機能を提供している → 機能を追加するためにUserクラスでモジュールを読み込む → Userクラスが提供する機能(責務)が多くなる 1. 1つのモデルクラスが⼀つの責務を担当するようにしたい b. Deviseをこんな⾵に使いたいな
認証⽤テーブル、クラスを使って責務を分担させたいな、、、 1. 1つのモデルクラスが⼀つの責務を担当するようにしたい b. Deviseをこんな⾵に使いたいな
オプション機能を追加するとカラムがusersテーブルに付与される 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
認証関連情報がusersテーブルに集約されているため Deviseが提供していない認証系機能を追加する際に usersテーブルにカラムを追加してしまう → 不要な情報の露出が⾏われるかも 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
例 : ソーシャルログインの追加 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
usersテーブルに以下のカラムを追加する⽅法がよく⾒られる 純粋なユーザー情報ではなく、認証⽤の情報であるため 本来別のテーブルに配置するべき情報だと考えている • provider:認証プロバイダーの名称 • uid:プロバイダーから受け取るuid 2. 雑な独⾃実装で不要な情報露出を⾏わせない b.
Deviseをこんな⾵に使いたいな
雑にレコードをrenderした時uidやproviderまで送信してしまう (これは明らかなヒューマンエラーである) 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
注意 あくまで不要な情報露出は 標準以外の認証系機能を追加した際に発⽣し得る懸念 Deviseが標準で⽤意している追加機能においては この点のセキュリティは担保されている (confirmed_atやencrypted_passwordなど) 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
不要な情報の外部送信はできる限り避けたいな、、、 usersテーブルは純粋なユーザーの情報だけ置きたいな 2. 雑な独⾃実装で不要な情報露出を⾏わせない b. Deviseをこんな⾵に使いたいな
実際にテーブル分割を⾏ってみた
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
c. テーブル分割⽅法の提案 テーブル分割を⾏う⼿法での⼀例として、以下の⼿順を提案する 1. 機能に必要なカラムのみを別テーブルに分割 2. モデルクラスで必要なモジュールのみを使⽤ 3. 挙動に合わせて設定
例 : メールアドレスとパスワードでのサインイン機能 ビューはDeviseのデフォルトを使⽤ c. テーブル分割⽅法の提案
サインインに必要なカラムはemailとencrypted_password 1. 機能に必要なカラムのみを別テーブルに分割 c. テーブル分割⽅法の提案
サインインに必要なカラムはemailとencrypted_password 1. 機能に必要なカラムのみを別テーブルに分割 c. テーブル分割⽅法の提案
UserDatabaseAuthenticationクラス database_authenticatable: パスワードの暗号化や認証 validatable: メールアドレス、パスワードのバリデーション 2. モデルクラスで必要なモジュールのみを使⽤ c. テーブル分割⽅法の提案
Userクラス authenticatable: セッション管理やメソッドの提供 2. モデルクラスで必要なモジュールのみを使⽤ c. テーブル分割⽅法の提案
Userクラス authenticatable: セッション管理やメソッドの提供 2. モデルクラスで必要なモジュールのみを使⽤ • authenticate_user! • user_signed_in? •
current_user c. テーブル分割⽅法の提案
Userクラス authenticatable: セッション管理やメソッドの提供 → 認証⽅法が複数存在してもセッション管理はUserクラスが担う 2. モデルクラスで必要なモジュールのみを使⽤ • authenticate_user! •
user_signed_in? • current_user c. テーブル分割⽅法の提案
ルーティング サインイン画⾯のビューをデフォルトで使⽤ 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
ルーティング サインイン画⾯表⽰⽤パスを作成するために、 emailとencrypted_passwordをもつ UserDatabaseAuthenticationモデルを devise_forの引数に指定する必要がある ※ devise_for : 指定されたモデルのためのルーティングを設定 3.
各種挙動に合わせて設定 c. テーブル分割⽅法の提案
ルーティング こんな感じ 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
アクション フォームからリクエストが送られるアクションの元実装 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
アクション sign_inメソッド:resourceとして渡されたオブジェクトのクラスが セッション開始を担っている時、セッション開始 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
アクション sign_inメソッド:resourceとして渡されたオブジェクトのクラスが セッション開始を担っている時、セッション開始 resourceはdevise_forに渡したUserDatabaseAuthenticationクラス のオブジェクトとなる 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
アクション sign_inメソッド:resourceとして渡されたオブジェクトのクラスが セッション開始を担っている時、セッション開始 resourceはdevise_forに渡したUserDatabaseAuthenticationクラス のオブジェクトとなる → Userクラスがセッション管理を担っていない 3. 各種挙動に合わせて設定 c.
テーブル分割⽅法の提案
アクション ブロックを渡すとこの部分で実⾏してくれる 特定の処理を差し込める 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
アクション usersレコード由来のオブジェクトをsign_inメソッドに渡す処理を createメソッドのオーバーライド時に差し込む 3. 各種挙動に合わせて設定 c. テーブル分割⽅法の提案
以上の⼿順によって テーブル分割を⾏った上でサインイン機構を構築できた c. テーブル分割⽅法の提案
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
• Userクラスがスッキリして嬉しい気持ちになれた d. テーブル分割して実装してみた感想
• Userクラスがスッキリして嬉しい気持ちになれた • 認証⽅法の追加時に新テーブル作成に思考が向きやすくなった d. テーブル分割して実装してみた感想
• Userクラスがスッキリして嬉しい気持ちになれた • 認証⽅法の追加時に新テーブル作成に思考が向きやすくなった • とても難しい、、、今回の紹介は⼀番簡単な例 d. テーブル分割して実装してみた感想
• Userクラスがスッキリして嬉しい気持ちになれた • 認証⽅法の追加時に新テーブル作成に思考が向きやすくなった • とても難しい、、、今回の紹介は⼀番簡単な例 • 未来の実装時間を使⽤している気持ちにもなった d. テーブル分割して実装してみた感想
2. テーブル分割による柔軟な削除機構
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
a. ユーザーの削除時に考慮したいこと ユーザーの削除機構の仕様決定時には多くを考慮する必要がある • ⼀度削除されたユーザーの復元が可能か • ユーザー削除時に関連するデータは残すか • プライバシー情報を削除しなければならないか
これもテーブル分割で対応できるのでは? • ⼀度削除されたユーザーの復元が可能か • ユーザー削除時に関連するデータは残すか • プライバシー情報を削除しなければならないか a. ユーザーの削除時に考慮したいこと
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
b. 柔軟な削除機構を実現するための分割⽅法 管理⽅法 usersテーブルにactive_usersテーブルを関連付ける → usersテーブルのレコードがactive_usersを持つ時 そのユーザーはアプリケーションを使⽤可能
ユーザーの削除時 関連するactive_usersテーブルのレコードを削除する b. 柔軟な削除機構を実現するための分割⽅法
active_usersテーブルを採⽤した⽅法は柔軟な削除機構 以下を決定できる • ⼀度削除されたユーザーの復元が可能か • ユーザー削除時に関連するデータは残すか • プライバシー情報を削除しなければならないか b. 柔軟な削除機構を実現するための分割⽅法
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
削除するデータ、残すデータはこのように決定可能 例1:プライバシー情報 プライバシーであり、ユーザー退会時に⼀緒に削除したいデータ はactive_usersテーブルに配置 c. テーブル分割による削除機構の使⽤⽅法
削除するデータ、残すデータはこのように決定可能 例1:プライバシー情報 プライバシーであり、ユーザー退会時に⼀緒に削除したいデータ はactive_usersテーブルに配置 → active_usersのレコードと共にデータは削除される c. テーブル分割による削除機構の使⽤⽅法
削除するデータ、残すデータはこのように決定可能 例2:ユーザーに関連するデータを残す c. テーブル分割による削除機構の使⽤⽅法
削除するデータ、残すデータはこのように決定可能 例2:ユーザーに関連するデータを残す → active_usersのレコード削除時に関連データ(posts)も 削除するか柔軟に変更可能 c. テーブル分割による削除機構の使⽤⽅法
ユーザーを「⼀時的にロックする」などのように状態を追加した い場合には新しく状態⽤のテーブルを作成する ⽅向に思考が向く → クラスの肥⼤化を防ぐ c. テーブル分割による削除機構の使⽤⽅法
⽬次 1. Deviseにおけるusersテーブルの分割 a. Deviseとは b. Deviseをこんな⾵に使いたいな c. テーブル分割⽅法の提案 d.
テーブルを分割して実装してみた感想 2. テーブル分割による柔軟な削除機構 a. ユーザーの削除時に考慮したいこと b. 柔軟な削除機構を実現するための分割⽅法 c. テーブル分割による削除機構の使⽤⽅法 3. まとめ
まとめ 1. Deviseのテーブルを分割するとUserクラスがスッキリする 2. テーブル分割によってユーザーの削除機構を柔軟にできる
ご清聴ありがとうございました