トップ «前の日記(2006-11-27) 最新 次の日記(2006-12-01)» 編集

3 日坊主日記


2006-11-28 [長年日記]

_ [第五] 本日のリンク元が寂しくなってる

けどなんでなのか分からない。

追記: 以前の日記へのリンク元 に出るということか。 でも本日のリンク元にupdate.rbが出るのはなんでだろう。

追記: plugin.defaultのほうをupしてなかった。これでどうかな。

_ 聖剣1

久しぶりにGB電源入れたらまだ動いた。コンティニューしたらどこなのか分からない(かなり始めのほうぽい)。音楽にほのぼの。

_ [Ruby] るびま0017号

リンク。

_ [Rails] Time.nowの固定

以前るびまで書いたように、時刻を扱うテストではテストデータを動的に変えるかTime.nowを固定する。 ここではTime.nowを固定する方法だけを見る。

参考になるのはActiveRecordのテストに出てくる方法。

# activerecord/test/mixin_test.rb:
# Let us control what Time.now returns for the TouchTest suite
class Time
  @@forced_now_time = nil
  cattr_accessor :forced_now_time

  class << self
    def now_with_forcing
      if @@forced_now_time
        @@forced_now_time
      else
        now_without_forcing
      end
    end
    alias_method_chain :now, :forcing
  end
end

class TouchTest < Test::Unit::TestCase
  fixtures :mixins

  def setup
    Time.forced_now_time = Time.now
  end

  def teardown
    Time.forced_now_time = nil
  end

  def test_time_mocking
    five_minutes_ago = 5.minutes.ago
    Time.forced_now_time = five_minutes_ago
    assert_equal five_minutes_ago, Time.now

    Time.forced_now_time = nil
    assert_not_equal five_minutes_ago, Time.now
  end
  #...
end

自分のテストでもこれを使えばok。

さて、このTime.nowを固定する方法は、実際にウェブサーバ上で動してみるときにも使いたいことがある。 例えば日付ごとに内容が変わるページがあるとして、動作確認のためだけに日付パラメータを渡すように実装するのは面倒くさいし、その日の分だけ出力するなら要らないはずの、過去未来に対するアクセス制限とか余計なことに時間がかかる。

単純に先のTimeクラス定義をconfig/environment.rbに置き、 適当なアクションを用意すれば

require 'time'

  def forced_time
    Time.forced_now_time = params[:time] ? Time.parse(params[:time]) : nil
    redirect_to :action => 'index'
  end

アプリでTime.now固定が使えるわけだけど、 実際にはこれだと影響が大きすぎる。 例えば、ログのタイムスタンプも動いてしまう。

なので、別のクラスTimelineを用意しよう。

# app/models/timeline.rb:
class Timeline
  @@forced_now_time = nil
  cattr_accessor :forced_now_time

  def self.now
    @@forced_now_time || Time.now
  end
end
  def forced_time
    Timeline.forced_now_time = params[:time] ? Time.parse(params[:time]) : nil
    self.class.logger.info("Timeline.now: #{Timeline.now}")
    redirect_to :action => 'index'
  end

しかし、クラス変数はセッションを跨いで保持されないので (少なくともmongrelでは) これはうまくいかない。

なので、@@forced_now_timeをDBに格納する。Settings pluginを使う。

class Timeline
  def self.now
    forced_now_time || Time.now
  end

  def self.forced_now_time
    Settings.forced_now_time
  end

  def self.forced_now_time=(time)
    Settings.forced_now_time = time
  end
end

_ [Rails] segv

$ rake
...
C:/ruby-1.8.5/bin/ruby -Ilib;test "C:/ruby-1.8.5/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb"
C:/ruby-1.8.5/bin/rake:18: [BUG] Segmentation fault
ruby 1.8.5 (2006-08-25) [i386-mswin32]

なんか出た。見なかったことにしよう。

直後にもう一回

$ rake

しても再現しないしな。

[]