ユーザーのタイムゾーンを自動で保存するコードをリファクタリング

スポンサーリンク

昨日のエントリー、Rails でユーザーのサインアップ時にタイムゾーンを自動で判定して保存 | EasyRamble で書いたコードがどうにも気持ち悪いので、リファクタリングを行いました。

【お知らせ】 英単語を画像イメージで楽に暗記できる辞書サイトを作りました。英語学習中の方は、ぜひご利用ください!
画像付き英語辞書 Imagict | 英単語をイメージで暗記
【開発記録】
英単語を画像イメージで暗記できる英語辞書サービスを作って公開しました
スポンサーリンク

自動でユーザーのタイムゾーンを設定するために、モデルから request 変数にアクセスするために書いたコードだったのですけど、やはりモデルが request 変数にアクセスする設計はどう考えても良くないですので。

request をスレッドローカル変数にする部分を削除

app/controllers/application_controller.rb

以上の部分のコードは削除しました。

タイムゾーンのクッキーを引数で渡すように変更

タイムゾーンが保存されているクッキーを、User.get_user_timezone に引数で渡すように変更しました。

app/controllers/users/regsitrations_controller.rb

controller からなので、普通に cookies で timezone クッキーを取得できます。

User.get_user_timezone の実装を変更

User.get_user_timezone メソッドが、timezone_cookie を引数で受けとるように変更。

app/models/user.rb

引数で渡された timezone クッキーを使うように、User.get_user_timezone メソッドの実装を変更しました。

当初の Thread.current[:request] を用いた実装は、OmniAuth で Twitter/Facebook で認証したユーザーを保存するクラスメソッドの兼ね合いから、ああいう実装にしていました。詳しくは、以下エントリーの User.find_for_twitter_oauth, User.find_for_facebook_oauth を参照。

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

cookie だけをスレッドローカル変数にせず、request をスレッドローカル変数にしていたのは、他に request.env[‘HTTP_ACCEPT_LANGUAGE’] にもアクセスするため。タイムゾーンとともに、ユーザーの言語も HTTP_ACCEPT_LANGUAGE で判定して自動で保存するコードを書いていましたので。

なので、Twitter/Facebook の OAuth 認証ユーザーにもタイムゾーンを自動で保存する場合は、User.find_for_twitter_oauth, User.find_for_facebook_oauth がタイムゾーンを保存したクッキーを引数に取るように変更する必要があります。ユーザーの言語も自動設定する場合は、request.env[‘HTTP_ACCEPT_LANGUAGE’] も引数渡しにする。

cookie や HTTP_ACCEPT_LANGUAGE を controller から引数で渡して、model に定義したメソッドを呼び出すことになるので、Thread.current[:request] を用いるより、コードが若干ごちゃごちゃになってしまいます。しかし、モデルから request にアクセスするという気持ち悪さは解消できます。どちらが良いか断定できませんので、ベストプラクティスを知りたいところです。

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
 
スポンサーリンク

Leave Your Message!