Railsでの時間管理はUTCで

RailsのTimeクラスは拡張されているので,zoneメソッドが利用できます.
※標準のTimeクラスでは,undefined method でエラーがでます.

irb:0> Time.zone
=> (GMT+00:00) UTC

これは,config/application.rbで,
config.time_zone = 」で指定するのですが,デフォルトは「UTC」です.
ここで,「Tokyo」とかに変えても良いのですが,ActiveRecordによって,DBに保存される日時はUTCみたいなのです...

どうやら,Railsで日時はUTCで管理した方が良さそうで,表示する際にローカル時刻(JST)に変換するというやり方の方が良さそうです.

例えば,users テーブルに,「start_time」というDATETIME型のフィールドを作成されているとき,

user = User.find(1)
user.start_time = Time.now.utc.to_s(:db)
user.save

と,強制的にUTCで “2013-01-16 05:30:00” というようにデータベースの日付型に合わせた形で現在のUTC日時を代入します.

irbにて,テーブルのフィールドの値を確認すると...

irb:0> user = User.find(1)
irb:0> user.start_time
=> Wed, 16 Jan 2013 05:30:00 UTC +00:00

ちゃんとUTCで入っています.
そして,このオブジェクト型は,何なのかを確認します.

irb:0> user.start_time.class
=> ActiveSupport::TimeWithZone

Timeクラスでは無いんですね...

んでもって,ローカル時間に変換したい場合はその都度,in_time_zoneメソッドを使用するようにします.

irb:0> user.start_time.in_time_zone('Tokyo')
=> Wed, 16 Jan 2013 14:30:00 JST +09:00

時間計算も記録も全てUTCで,表示するときだけJSTに変換する,そういう方針で行きたいと思います.

広告

CentOS 6.2のrbenvな環境でPassengerを動かしてみる(続)

前回,SELinuxな環境下でPassengerを動かしてみるという記事を掲載しました.

CentOS 6.2のrbenvな環境でPassengerを動かしてみる

そのときの設定では,Apacheのバーチャルホスト(VirtualHost)は利用せず,次のようにApacheのデフォルトドキュメントルート(DocumentRoot)にRailsアプリ先ディレクトリのシンボリックリンクを作成し,「RackBaseURI」でRailsアプリの場所をしているだけでした.

# cd /var/www/html
# ln -s /home/hoge/rails/sample/public ./sample

そうすると, CSSのbackgroundで指定した背景画像ファイルが上手く表示されないのです.画像ファイルの場所を,絶対的にも相対的にもパスをしてしてもダメで,Railsアプリのpublicフォルダの場所をどうしてもDocumentRootに指定しないとダメみたいなのです...

-----------------------
#
# Passenger.conf
#

LoadModule passenger_module modules/mod_passenger.so
PassengerRoot /usr/local/rbenv/..(略)../lib/ruby/gems/1.9.1/gems/passenger-3.0.15
PassengerRuby /usr/local/rbenv/..(略)../bin/ruby

RackBaseURI /sample

<VirtualHost *:8000>
    ServerName host.example.com
    DocumentRoot /home/hoge/rails/sample/public
    <Directory /home/hoge/rails/sample/public>
        AllowOverride all
        Options -MultiViews
    <Directory>
<VirtualHost>
Listen 8000

というように,Apacheのバーチャルホスト指定をします.すると,次のようなURLでブラウザでアクセスすれば,Railsアプリが表示されます.

http://host.example.com:8000/

今回は,エイリアスホスト名をDNSサーバにホスト登録しないで,ポート番号を変えることで対応しました.

そんでもって,httpdサービスを再起動させると...

# service httpd restart
httpd を停止中:                                            [  OK  ]
httpd を起動中: Warning: DocumentRoot [/home/hoge/rails/sample/public] does not exist
                                                           [  OK  ]

というようなWarningが出ちゃいました.当然,URL叩いてもブラウザからもエラーが表示されます.
SELinuxを無効(setenforce 0)にすれば問題なく動くので,やはりSELinuxの設定が悪さをしているようです.(というか,私がきちんと設定していないからダメなのです.)

ということで,前回のようにaudit.logからaudit2allowでモジュールを作って,semoduleでセットして...とやってみても,やっぱり上手くいかない...

色々,ググってみますと,次のサイトにちゃんと紹介されてました!

Apache Warning: DocumentRoot does not exist | Jan

” As it turned out, after running audit2allow on my audit.log file, access was denied because the root folder for the vhosts are in most of my cases also home directories for local users, so that when I add them, my local vsftpd install allows them to connect using their credentials and by setting their home directories to their vhost, their ftp user enters at that folder level. All I needed was just a SELinux setting that allows httpd to read user’s home dirs:

setsebool -P httpd_enable_homedirs 1

確かに,

# getsebool -a | grep httpd

で確認すると,

 : 
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
 :

「httpd_enable_homedirs」がoffになっている...

でもって,そのサイトで記載されているとおり,on(有効)にしますと...

# setsebool -P httpd_enable_homedirs 1

あら,上手くいきましたわ(・∀・)