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
1.3k
テーブル分割で実現するdeviseの責務の分離と柔軟な削除機構
なおと
October 30, 2023
Tweet
Share
More Decks by なおと
See All by なおと
プロジェクトマネジメントとは? 経験から学ぶ視野と視座
naotocoding
0
1.1k
Stripeノーコード挑戦記決済画面構築の山あり谷あり
naotocoding
0
27
大規模プロジェクトに学ぶ、新卒エンジニアの教訓
naotocoding
0
52
Other Decks in Programming
See All in Programming
AIでLINEスタンプを作ってみた
eycjur
1
230
実用的なGOCACHEPROG実装をするために / golang.tokyo #40
mazrean
1
250
1から理解するWeb Push
dora1998
7
1.8k
Namespace and Its Future
tagomoris
6
700
Design Foundational Data Engineering Observability
sucitw
3
190
Amazon RDS 向けに提供されている MCP Server と仕組みを調べてみた/jawsug-okayama-2025-aurora-mcp
takahashiikki
1
110
AI時代のUIはどこへ行く?
yusukebe
17
8.8k
プロパティベーステストによるUIテスト: LLMによるプロパティ定義生成でエッジケースを捉える
tetta_pdnt
0
300
2025 年のコーディングエージェントの現在地とエンジニアの仕事の変化について
azukiazusa1
22
12k
意外と簡単!?フロントエンドでパスキー認証を実現する WebAuthn
teamlab
PRO
2
720
そのAPI、誰のため? Androidライブラリ設計における利用者目線の実践テクニック
mkeeda
2
260
Kiroの仕様駆動開発から見えてきたAIコーディングとの正しい付き合い方
clshinji
1
210
Featured
See All Featured
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Building Adaptive Systems
keathley
43
2.7k
Speed Design
sergeychernyshev
32
1.1k
Statistics for Hackers
jakevdp
799
220k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
810
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
139
34k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
GraphQLの誤解/rethinking-graphql
sonatard
72
11k
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. テーブル分割によってユーザーの削除機構を柔軟にできる
ご清聴ありがとうございました