Rails でユーザーのサインアップ時にタイムゾーンを自動で判定して保存

ユーザーがサインアップする際に、ユーザーのタイムゾーンをフォームで選択してもらうのではなくて、自動で設定したいと考えました。これからサインアップするユーザーには、できるだけフォーム入力の負担をかけたくありませんので。

スポンサーリンク

— 環境 —
rails-4.0.1
devise-3.2.2

【追記 2014/03/09】
やはり、Thread.current[:request] を用いて、モデルから request 変数にアクセスする方法は良い設計ではないと思いまして、別エントリーで実装をリファクタリングしました。

ユーザーのタイムゾーンを自動で保存するコードをリファクタリング | EasyRamble
【追記ここまで】

detect_timezone_rails, jquery-cookie-rails をインストール

調べたところ、detect_timezone_rails という便利そうな gem を発見。サインアップ時に、この gem で自動判定されクッキーに保存されたユーザーのタイムゾーン値を、users テーブル(User モデルのテーブル)に保存します。

Gemfile に以下を書いて、bundle install。

Gemfile

timezone.js.coffee を作成

アセットパイプラインで読み込まれるように、以下を指定。

app/assets/javascripts/application.js

timezone.js.coffee を作成します。CoffeeScript で timezone という名前の cookie をセット。

app/assets/javascripts/timezone.js.coffee

Devise::RegistrationsController#build_resource をオーバーライドしてタイムゾーンを設定

認証エンジンとして Devise を使っていますので、Devise::RegistrationsController#build_resource をオーバーライド。User モデルの table に time_zone というカラムを作成して、それにユーザーのタイムゾーン値を保存します。build_resource はユーザーがサインアップでフォーム送信後、create アクション実行時に呼ばれるメソッドです。

app/controllers/users/registrations_controller.rb

User モデルに get_user_timezone を実装

User モデルに get_user_timezone クラスメソッドを実装しますが、ここで問題が一つ。モデルでは、cookies メソッドが使えず、そのままでは cookie を取得できません。これを回避するため、まず先に以下のコードを ApplicationController に書きました。

app/controllers/application_controller.rb

スレッドローカル変数に request を保持しておく。そして、モデル内で次のように書くと、timezone.js.coffee でセットした timezone クッキーを取得できます。

最後に、User.get_user_timezone を実装しました。

app/models/user.rb

メソッドの後半でごちゃごちゃやってるのは、timezone.js.coffee に書いた detect_timezone_rails の get_timezone メソッドでクッキーにセットされたタイムゾーン値を、Rails の ActiveSupport::TimeZone.MAPPING で得られるものと対応させるため。

get_user_timezone メソッドは、controller(registrations_controller.rb)に定義すべきかもしれません。モデルが request(HTTPリクエスト情報の変数)を持つのは、あまり良い設計とは思えませんので。controller に定義するのであれば、普通に cookies メソッドでタイムゾーンのクッキーを取得できるので、スレッドローカル変数も不要になります。

なんか結構面倒くさくて、ベストな方法ではない感じがするのが気になります…。

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)

Leave Your Message!