• 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
 

 RSpecで現在時刻に関連するテストをするときに、Rails4.1からはTimecopを使わなくても ActiveSupport::Testing::TimeHelpers の to_travel というメソッドを使って現在時刻を設定することができます。

 たとえば、下記のように現在時刻を返すメソッドがあるとします。

   1  class Foo
   2    def now
   3      Time.now
   4    end
   5  end

 正しく現在時刻を返しているかのテストは下記のように書けます。

   1  travel_to Time.new(2014, 11, 24, 9, 30, 0) do
   2    foo = Foo.new
   3    expect(foo.now).to eq(Time.new(2014, 11, 24, 9, 30, 0))
   4  end

 travel_toで現在時刻を設定しているので、expectで評価するときに決まった時間を書いて比較できます。

 ですがもしnowメソッドでDateTime.nowを返していると、to_travelでは対応できません。

   1  class Foo
   2    def now
   3      DateTime.now # <- to_travelで設定した時間ではなく現在時刻が返る
   4    end
   5  end

 その場合にはやはりTimecopを使う必要があります。Gemfileには下記のようにgemを追加。

   1  group :test do
   2    gem 'timecop'
   3  end

 テストは下記のように記述します。

   1  Timecop.freeze(Time.new(2014, 11, 24, 9, 30, 0)) do
   2    foo = Foo.new
   3    expect(foo.now).to eq(Time.new(2014, 11, 24, 9, 30, 0))
   4  end

 travel_to が対応しているのは Time.now と Date.today のみのようです。

 travel_to(date_or_time, &block)
 rails4.1からのtravel_toをrspecで使う

posted by Png akanuma on Tue 25 Nov 2014 at 00:00

環境変数によってRailsアプリの動作を切り替えたいことがあって、
nginx + Passenger で動かしているRailsアプリに環境変数を渡す方法を調べました。

nginx の起動スクリプト(/etc/init.d/nginx)に書いても、
/etc/default/nginx に書いてもうまくいかなかったのですが、
nginx の設定ファイルの location ブロックで
passenger_set_cgi_param で設定することで環境変数が設定できます。

   1  passenger_set_cgi_param HOGE fuga;

これでRailsアプリの中で ENV['HOGE'] で "fuga" という値が取得できるように なります。

参考ページ
16.3.5. Phusion Passengerが提供するアプリケーション
8.6.1. passenger_set_cgi_param

posted by Png akanuma on Sat 22 Nov 2014 at 14:13

Rails4で入力フォームから日時を選択できるように datetimepicker を使ったのですがちゃんと動くまでに軽くはまったのでメモ。

bootstrap3-datetimepicker-rails

まずはGemfileに下記エントリを追加して bundle install

   1  gem 'momentjs-rails'
   2  gem 'bootstrap3-datetimepicker-rails'

moment と datetimepicker のJavaScriptファイルを読み込むための設定を追加します。 私は coffeescript を使っているので application.js.coffee に下記エントリ を追加します。 bootstrapの設定が入っていない場合はあわせて追加します。

   1  #= require bootstrap
   2  #= require moment
   3  #= require bootstrap-datetimepicker

続いてstylesheetの設定も追加します。 私の場合は scss を使っているので、application.css.scss に下記を追加。 ちなみに順番もこの通りじゃないとちゃんと動きません。

   1  @import "bootstrap-sprockets";
   2  @import "bootstrap";
   3  @import "bootstrap-datetimepicker";

ここまででひとまずの下準備は終了なので、実際にdatetimepickerを適用したい部分の作業をします。 今回の対象のView部分は下記のような感じです。

   1  <div class="form-group">
   2    <div class="col-md-2">
   3      <%= f.text_field :start_datetime, value: @user.start_datetime, class:
   4  "form-control", id: "user_start_datetime" %>
   5    </div>
   6  </div>

f.text_field で出力される input タグに対して datetimepicker() メソッドを 実行します。 下記内容でcoffeescriptのファイルを別途作成して読み込みます。

   1  $ ->
   2    $('#user_start_datetime').datetimepicker()

これで入力ボックスを選択した時に日時選択用のポップアップが表示されるようになります。 また、日付のフォーマットのデフォルトは MM/DD/YYYY hh:mm A/PM なので、日本の形式に変更します。 inputタグに data-date-format 属性で指定するのですが、rails の text_field タグでは追加の属性を指定できないため、先ほどのcoffeescriptを変更して動的に属性を追加します。

   1  $ ->
   2    date_format = {'data-date-format': 'YYYY/MM/DD HH:mm'}
   3    $('#user_start_datetime').attr(date_format)
   4    $('#user_start_datetime').datetimepicker()

これで日付フォーマットが変更されます。 今回は一番シンプルな形で datetimepicker を使いましたが、オプションの指定で表示形式などは色々変更できますので、試してみてもらえると良いかと思います。

参考ページ http://eonasdan.github.io/bootstrap-datetimepicker/

posted by Png akanuma on Sat 22 Nov 2014 at 14:02

 Passenger + Nginx でアプリケーションを起動しようとしたときに、下記のようなエラーが出ました。

   1  git://github.com/nzifnab/msgpack-rails.git (at master) is not checked out. Please run `bundle install` (Bundler::GitError)

 もちろん bundle install は実行済みです。msgpack-rails を使用するために、Gemfile に下記のような記述をしてあるのですが、色々調べたところ、Passenger が git からインストールした gem を認識してくれないようです。

   1  gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'

 bundle install --deployment で解決するという情報も見つけたのですが、これは vendor ディレクトリにgemを持ってくるため結構な時間がかかります。デプロイでは世代管理していて、デプロイ時に新しいディレクトリを作成してデプロイしているので、開発環境のサーバへデプロイするたびに時間がかかるのはちょっと困るので他の方法を探したところ、bundle package でOKという情報を見つけました。これはgemのキャッシュを vendor ディレクトリに持つもので、すぐに終わります。ただオプションで --all を指定しないと git 経由のgemをキャッシュしてくれないようです。

   1  bundle package --all

とすることで、git からの gem も見つけてくれるようになりました。

(参考サイト)deploying rails3 apps with bundler and phusion passenger: .bundle dir not found

posted by Png akanuma on Wed 25 Dec 2013 at 06:01

 今まではネイティブのクライアントへJsonでレスポンスを返していたのですが、新しいサービスを開発する際に、レスポンスをMessagePackにしてはどうかとクライアントサイドから提案があったので検証してみました。

 ちなみにリクエストまでMessagePackにすると、リクエスト内容が簡単に参照できなくなってデバッグや問い合わせ時の調査が大変ということで、今回はレスポンスのみに使う想定です。

検証用アプリ


 構成は下記の通りです。

  • Nginx
  • Passenger
  • Ruby2.0
  • Rails4

 今回の検証はJson圧縮とMessagePack圧縮の比較です。アプリはRails4で実装します。また、JsonはデフォルトのJSONクラスよりもoj(Optimized JSON)が早いということなのでそちらを使用しています。MessagePackの方はMsgpackRailsを使います。Gemfileには下記を追加します。

(参考) JSONの替わりに使ったOJが速い
(参考) MsgpackRails

   1  gem 'oj'
   2  gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'

 Controllerは下記のように実装しました。

   1  class StaticPagesController < ApplicationController
   2  
   3    require 'oj'
   4  
   5    after_action :testcompress
   6  
   7    respond_to :json, :mpac
   8  
   9    SERIALIZE_TEST_RESPONSE = {(省略)}
  10  
  11    def serialize_test
  12      respond_to do |format|
  13        format.json { render :json => SERIALIZE_TEST_RESPONSE }
  14        format.mpac { render :text => SERIALIZE_TEST_RESPONSE.to_msgpack, :content_type => 'application/x-mpac' }
  15      end
  16    end
  17  
  18    def testcompress
  19      response.body = ActiveSupport::Gzip.compress(response.body)
  20    end
  21  
  22  end

  • oj が追加されていると、MultiJSONによって自動的に oj が選択されるようです。
  • シリアライズするHashデータを SERIALIZE_TEST_RESPONSE として定義しておきます。
  • 処理内容としてはテスト用のデータをシリアライズして返すだけです。
  • また、今回はシリアライズ+圧縮を試すのですが、Rails側で圧縮した場合と、Nginxで圧縮した場合も比較してみます。Rails側で圧縮する場合の処理を testcompress メソッドに定義しておいて、after_action で gzip 処理を行います。Nginx側で圧縮する場合は after_action をコメントアウトします。

 検証方法としては、JMeterサーバを3つ用意して、100スレッドから上記APIへかけられるだけ負荷をかけてみるというやり方です。Nginxで圧縮するケースではHTTPヘッダマネージャでAccept-Encodingヘッダを設定する必要があります。また、Nginxの設定ファイルで下記の設定を有効にします。

   1  gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-mpac;

 デフォルトでは application/x-mpac 以外が設定された状態でコメントアウトされていますので、コメントアウトを解除して application/x-mpac を追加してあります。

検証結果


検証結果は下記の通りです。

検証結果
種別圧縮サンプル数平均中央値90%LINE最小値最大値スループットKB/sec
JsonRails48626181618052002252258158.57306.30
MessagePackRails2713723173213565533889.051701.66
JsonNginx48824178517751988272206159.11393.07
MessagePackNginx33378324924827944661093.612395.42
MessagePack非圧縮34617524624627166101134.3319178.19

 Jsonの場合はCPUは常に振り切っている状態でしたが、MessagePackではCPUに余裕がありました。
 テスト結果のスループットとしてはMessagePack非圧縮のケースが一番速かったのですが、MessagePackのNginxでの圧縮の場合と大きな差はなく、実際のケースでは転送するデータ量を少なくすることによるメリットも大きいので、今回はMessagePackのNginx圧縮パターンを採用することにしました。

posted by Png akanuma on Sat 21 Dec 2013 at 18:28

production環境などでログ自体を無効化するには config/environments/production.rb あたりで

   1  RAILS_DEFAULT_LOGGER = Logger.new("/dev/null")

すればok.

posted by Png genki on Sun 18 Dec 2011 at 08:45

my.cnfの中で、clientとserver両方max_allowed_packet を適当に大きな数値に指定する。

   1  max_allowed_packet = 16M

config/database.yml でコネクション切断時に再接続する設定をする。

   1  production:
   2    reconnect: true

これで多分大丈夫。

posted by Png genki on Sat 11 Jun 2011 at 10:05

昔は mysql_retry_lost_connection というものがあったのですが、最近 (Rails-2.3以降) は config/database.yml の中で

   1  production:
   2    reconnect: true

とやるだけで、接続が切れた場合に再接続してくれるようです。 まあ、ここまで用意するならデフォルトでそうなってても良いと思うんですけどね。

posted by Png genki on Sat 11 Jun 2011 at 07:06

Rails-2.3.11用のExceptionNotificationプラグインは以下にあるようです (via @a_matsuda

基本的にはこれを script/plugin install -r 2-3-stable すれば良いのですが、ConsiderLocalの実装にバグがあるので 直す必要があります。

具体的には、以下のファイルの self.included の場所をConsiderLocalモジュールの直下に移動します。

あとはREADME通りに設定して、ConsiderLocalをApplicationControllerからincludeすればok

posted by Png genki on Sat 11 Jun 2011 at 06:51

GitリポジトリのRailsプラグインをインストールするときに、 標準では master ブランチがインストールされますが、 特定のブランチの内容をインストールしたい場合には、以下のように -r オプションを使用します。

   1  script/plugin install --force https://github.com/rails/exception_notification.git -r 2-3-stable

上記の例では 2-3-stable ブランチをインストールします。

posted by Png genki on Sat 11 Jun 2011 at 05:21