世界を旅して暮らしたい放浪エンジニアブログ

timezoneを意識してRails開発をしよう

「今更改めて Ruby On Railsの開発を行う 〜 Part8」です。複数カ国にサービス展開する場合やアメリカのようなtimezoneが複数存在する国では、サービスとしてtimezoneを設定できるようにする必要が出てきます。Railsでtimezoneを意識した開発を行う場合のノウハウをまとめます。

[ 目次 ]

はじめに

こんにちは、香港に住んでいるWEBデベロッパーのなかむ(@nakanakamu0828)です。

この記事は過去に運用していたブログからの移行記事になります。

今回はtimezoneについて学んでいきます。
日本向けにサービスを展開している際は、Asia/Tokyoに固定してしまうかと思います。
phpならphp.ini、Ruby On Railsならapplication.rbに設定を記述しますね。

複数の国に対してサービス展開する際は、

  • アクセス元からデフォルトとなるtimezoneを設定
  • ユーザーにtimezoneを設定させる

というように利用者によってtimezoneを変える必要が出てきます。
まずは、アクセス元からtimezoneを取得する方法を学んでいきましょう。

cjheath/geoip というライブラリを利用してIPアドレスから位置情報を取得します。
そして、位置情報から適したtimezoneを設定してみましょう。

cjheath/geoipインストール

Gemfilecjheath/geoipを追加します。

# Gemfile
gem "geoip"

続いてbundle installコマンドを実行し、ライブラリをインストールしてください。

$ bundle install
or
$ bundle install --path=vendor/bundle

※ 環境に合わせてプロジェクト配下にインストールするかどうかでコマンドを選択してください。

GeoIP.datファイルのセットアップ

Geoのデータベースファイルとして、GeoIP.datが用意されています。
そちらをダウンロードしてプロジェクト内にセットアップしていきましょう。

$ mkdir -p data/geoip
$ cd data/geoip
$ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
$ gzip -d GeoIP.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
$ gzip -d GeoLiteCity.dat.gz

※ 今回はCityの情報をメインで利用しますが、GeoIP.dat.gzも合わせてダウンロードしておきましょう。

rails cでGeoIPを確認

rails cでコンソールを起動し、GeoIPを利用してホスト/IPアドレスの位置情報を取得してみます

$ rails c
irb(main):001:0> c = GeoIP.new('data/geoip/GeoLiteCity.dat').city('www.yahoo.co.jp')
irb(main):002:0> c.timezone
=> "Asia/Tokyo"

こちらは、Yahoo(www.yahoo.co.jp)のホスト名からtimezoneを取得した例になります。

WEBサイトの初期アクセス時にtimezoneを設定する

続いてはWEBサイト側で実装していきましょう。
どの画面にアクセスがあっても判定させたいので、app/controllers/application_controler.rbに処理を記載します。
以下のように変更してください。

# app/controllers/application_controler.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  prepend_view_path Rails.root.join("frontend")

  before_action :init_category
  before_action :init_timezone

  def init_category
    @categories = Category.where(state: true).where(parent: nil).order(id: :asc)
  end

  # 
  # セッションにtimezoneが設定されていない場合、GeoIPを利用してアクセス元のIPアドレスからtimezoneを設定する
  # 
  def init_timezone
    if session[:timezone].blank?
      c = GeoIP.new('data/geoip/GeoLiteCity.dat').city(request.remote_ip)
      Time.zone = c.timezone unless c.nil?

      session[:timezone] = Time.zone.name
    end
  end
end

将来的には、init_timezoneメソッド内でユーザーのログインチェックを行い、ログインしている場合はユーザーが設定したtimezoneを反映という形に変更していきく予定です。

今回の実装はローカル環境では、timezoneの切り替えが確認できません。
開発サーバーを用意した際に確認してみましょう。
一旦、実装までをまとめさせて頂きました。

今回の成果物は こちら をご確認ください。

前のページ

次のページ

Profile

なかむ🇭🇰Webデベロッパー

なかむ🇭🇰Webデベロッパー

香港在住4年目になるWEBエンジニアのなかむです。 現在は、LaravelやRailsを利用したWEB開発を中心にエンジニアをしています。 顧客は全て日本の企業になります。リモート開発にて各企業様の支援を行なっております

プロフィール詳細はこちら

Latest Posts