1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】ゲストログインをlocalStorageで作ろうとしてすぐやめた話 〜設計で気づいたこと〜

1
Posted at

はじめに

個人開発の中で学んだことを備忘録としてまとめます。
※間違いがありましたらご教授お願い致します!

今回ユーザーが気軽にお試しでアプリを使えるようにゲストログインを実装することにしました。設計段階でゲストのユーザーをどのように管理するのか悩みました。

開発環境

Ruby on Rails7
環境構築 Docker
Devise導入済み

疑問点

・ゲストユーザーをDBに保存させてしまうとサーバーに負担になるのではないか
・使われなくなったゲストユーザーのDBが大量に残ってしまうのではないか
・LocalStorageを使用し、ブラウザにデータを保存した方が軽い実装になって良いのではないか

結論

はじめは

localStorageなら簡単に作れるのでは?

と思っていました。

しかし実際は:

  • ViewでもJSで分岐が必要
  • バリデーションもJS
  • データ引き継ぎが複雑
  • メンテナンスがしにくい
  • Railsらしさが消える
    クライアント側であるlocalStorageに責務を持たせると、ビュー・バリデーション・状態管理が分散し、設計が複雑になります。
    ゲストの時だけJavaScriptで分岐を書く必要があり、実装や保守の負担が増えると気づきました。

結果、

Railsアプリでは、DBに寄せた方が設計が自然でした。

という結論になりました。

実装

ゲストログインするたびにユーザーをDBに作ってしまうと
ゴミが沢山できそうなので、同じブラウザなら同じユーザーを使うようにcookieを利用するようにしました。

routes.rb
  # 通常ログイン
  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のセッション機構を流用できます

guest_sessions_controller.rb
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

処理の流れ

  1. cookieから guest_user_id を取得
  2. そのIDのゲストユーザーを検索
  3. なければ新規作成
  4. cookieに保存
  5. Deviseの sign_in でログイン
user.rb
  # ゲストユーザーを作成して返すメソッド
  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の導入も検討しています。セキュリティ面やメンテナンス性などを考慮しつつ、ブラッシュアップしていきたいと思います。


参考にした記事

HTML5のLocal Storageを使ってはいけない(翻訳)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?