フォームの入力を一部記憶してユーザーの入力作業を省力化する

英語レッスンで知らない単語がひとつ以上出てきた場合

Rails で個人用の英単語帳アプリを開発しています。開発環境は Rails 7.0.4 + Ruby 3.2.2 です。

オンライン英会話レッスンではインターネットの記事を教材にすることが多いです。その場合、同記事中に出現する複数の英単語を連続で単語帳に登録することになります。復習時に使用されていた文脈を辿れるようにするため、登録時にその単語の「出自(source)」となる記事の URL を保存するようにしています。

1 つ目の単語の登録時のフォーム画面

2 つ目の単語の登録時のフォーム画面(URL は入力する必要がない)

ユーザーが単語に出会った場所 入力例
レアジョブの教材の場合 https://www.rarejob.com/dna/2023/04/14/paris-aims-to-keep-olympians-cool-without-air-conditioners/
オフラインの小説や書籍の場合 Harry Potter and the Philosopher's Stone p.68

記事 URL や書籍のページ情報はどこに保存するべきか

HTTP はステートレスなので、どこかに情報(この場合は Source フィールドに入力する URL) を保存する必要があります。Rails では ActionDispatch::Session Module 配下のいくつかのクラスを 利用して保存先を選択できます。CookieStore, CasheStore, ActiveRecordStore, MemCacheStore のどれかを選択可能ですが、ここではデフォルトの CookieStore クラスを利用して Cookie に保存します。

RailsGuides > Action Controller Overview > 5. Session

5 Session

Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and the view and can use one of several of different storage mechanisms:

  • ActionDispatch::Session::CookieStore - Stores everything on the client.
  • ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
  • ActionDispatch::Session::ActiveRecordStore - Stores the data in a database using Active Record (requires the activerecord-session_store gem).
  • ActionDispatch::Session::MemCacheStore - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).

All session stores use a cookie to store a unique ID for each session (you must use a cookie, Rails will not allow you to pass the session ID in the URL as this is less secure).

ただ、今回の記事の URL や書籍のページ情報といった情報であれば CookieStore ではなく CacheStore を使うという選択肢もあるかもしれません。変更は config/initializers/assets.rb で Rails.application.config.session_store でクラスを指定するだけで、コード上の session (ハッシュのようにも見えるがインスタンスメソッド) は変わらず内部で切り替わるようです。このへんはフレームワーク様々でしょうか。

If your user sessions don't store critical data or don't need to be around for long periods (for instance if you just use the flash for messaging), you can consider using ActionDispatch::Session::CacheStore.

なお、JavaScript を使う場合は localStorage への保存も選択肢にあがりそうです。localStorage は セキュリティやパフォーマンス上からは使用を控えるべき ですが、今回のようなセンシティブではない情報では検討してもよさそうです。

よりよい実装を求めて

同じことを JavaScript やフレームワークの機能を使ってもっとスマートに実装できる方法がありそうですが... フロントエンドのスキルが低いためこのような実装をしています (^_^;

参考情報