はじめに
個人開発の中で学んだことを備忘録としてまとめます。
※間違いがありましたらご教授お願い致します!
今回ユーザーが気軽にお試しでアプリを使えるようにゲストログインを実装することにしました。設計段階でゲストのユーザーをどのように管理するのか悩みました。
開発環境
Ruby on Rails7
環境構築 Docker
Devise導入済み
疑問点
・ゲストユーザーをDBに保存させてしまうとサーバーに負担になるのではないか
・使われなくなったゲストユーザーのDBが大量に残ってしまうのではないか
・LocalStorageを使用し、ブラウザにデータを保存した方が軽い実装になって良いのではないか
結論
はじめは
localStorageなら簡単に作れるのでは?
と思っていました。
しかし実際は:
- ViewでもJSで分岐が必要
- バリデーションもJS
- データ引き継ぎが複雑
- メンテナンスがしにくい
- Railsらしさが消える
クライアント側であるlocalStorageに責務を持たせると、ビュー・バリデーション・状態管理が分散し、設計が複雑になります。
ゲストの時だけJavaScriptで分岐を書く必要があり、実装や保守の負担が増えると気づきました。
結果、
Railsアプリでは、DBに寄せた方が設計が自然でした。
という結論になりました。
実装
ゲストログインするたびにユーザーをDBに作ってしまうと
ゴミが沢山できそうなので、同じブラウザなら同じユーザーを使うようにcookieを利用するようにしました。
# 通常ログイン
devise_for :users, controllers: { sessions: 'users/sessions' }
root "top#index"
get "/home", to: "home#index"
resources :breads, only: [:new, :create, :destroy]
# ゲストログイン
devise_scope :user do
post "guest_sign_in", to: "guest_sessions#create"
end
devise_scope を使うことで Deviseのセッション機構を流用できます
class GuestSessionsController < Devise::SessionsController
def create
# ブラウザから送られた guest_user_id を取得
guest_user_id = cookies.signed[:guest_user_id]
if guest_user_id.present?
user = User.find_by(id: guest_user_id, guest: true)
end
# 見つからなければ新規作成
unless user
user = User.create_guest
cookies.signed[:guest_user_id] = {
value: user.id,
expires: 1.month.from_now # 有効期限は任意
}
end
sign_in(user)
redirect_to root_path, notice: "ゲストログインしました"
end
end
処理の流れ
- cookieから guest_user_id を取得
- そのIDのゲストユーザーを検索
- なければ新規作成
- cookieに保存
- Deviseの sign_in でログイン
# ゲストユーザーを作成して返すメソッド
def self.create_guest
create!(
email: "guest_#{Time.now.to_i}@example.com",
password: SecureRandom.hex(10),
guest: true
)
end
ポイント
- ランダムメール生成
- guestフラグで区別
- パスワードはランダム
今後の課題
1.ゲストログインから本登録時にデータを引き継ぐ
試してみてもっと使いたいと感じたユーザーが本登録をした時に、データが引き継がれるとUXとして便利だと思います。
2.使われなくなったゲストのDBを定期的に削除する処理
本番環境では、使用されなくなったゲストデータが
サーバーリソースやバックアップ容量を圧迫する可能性があります。
そのためActiveJobやcronを使った定期削除の設計も必要になります。
まとめ
実装の部分はAIもありますし調べれば意外とわかりますが、(表面的に)
今回のように設計部分の選択においてはどの方式を選ぶのがベストなのかまだまだ分からない部分があると感じました。
それから意外だったのは、Devise自体にゲストユーザー専用の特別な仕組みがあるわけではなく、
Userモデルにguestフラグを追加し、アプリケーション側で条件分岐を行うことでゲストユーザーを扱える点でした。
また、ユーザーIDは自動採番されるため、
自分でIDを管理する必要がないことも改めて理解できました。
ランダムなメールアドレスやパスワードもSecureRandomを使えば簡単に生成でき、
「思ったよりシンプルに実装できる」という発見がありました。
今後はゲストユーザーはDBに蓄積され続ける可能性があるため、一定期間利用されていないゲストユーザーを定期的に削除するActiveJobの導入も検討しています。セキュリティ面やメンテナンス性などを考慮しつつ、ブラッシュアップしていきたいと思います。