Poziom: 0 | Kategoria: Komputerowo-internetowo, Ruby, Ruby on Rails, Techblog.
Czasem, szczególnie podczas pisania testów, zachodzi potrzeba manipulowania czasem, np. podczas testowania metod, które mają zwracać posortowane względem czasu utworzenia obiekty ActiveRecord.
W ostatnim projekcie podczas pisania spec-ów modeli korzystałem z takiego tworu:
describe SomeClass do
describe "by_date" do
it "should return objects sorted by creation date" do
Time.advancing_by_days(-1) do
@earlier = SomeClass.new(:some => "values")
end
@normal = SomeClass.new
Time.advancing_by_days(1) do
@later = SomeClass.new(:some => "other value")
end
SomeClass.by_date.should == [@later, @normal, @earlier]
end
end
end
O ile mi wiadomo, Railsy nie mają standardowo wbudowanych klas do manipulowania czasem, czy metodą Time.now.
Stworzenie metod realizujących powyższą funkcjonalność jest bardzo proste. Wystarczy stworzyć plik, np. time_extensions.rb z poniższą zawartością:
require 'time'
if !Time.respond_to?('old_now')
Time.class_eval {
@@advance_by_days = 0
@@advance_by_minutes = 0
cattr_accessor :advance_by_days, :advance_by_minutes
class << Time
alias old_now now
def now
if Time.advance_by_days != 0
return Time.at(old_now.to_i + Time.advance_by_days * 60 * 60 * 24 + 1)
elsif Time.advance_by_minutes != 0
return Time.at(old_now.to_i + Time.advance_by_minutes * 60)
else
old_now
end
end
def advancing_by_days(days=0)
Time.advance_by_days = days
yield
Time.advance_by_days = 0
end
def advancing_by_minutes(minutes=0)
Time.advance_by_minutes = minutes
yield
Time.advance_by_minutes = 0
end
end
}
end
Jak widać korzystamy z możliwości, jakie daje monkey pathing i modyfikujemy standardową metodę Time.now, uprzednio tworząc do niej alias. W powyższym kodzie oprócz zmiany czasu o zadaną liczbę dni, możemy zmieniać go o zadaną liczbę minut.
Aby korzystać z powyższych metod w spec-ach aplikacji railsowej, wystarczy wrzucić plik z powyższym kodem do katalogu spec aplikacji i dopisać do pliku spec_helper.rb linijkę:
require 'time_extensions'
Testowanie czegoś, gdzie czas jest ważny jest dla mnie czasem dość kłopotliwe. Kolejny przykład na to, że otwartość klas jest fajna
05 lipca 2008 o 11:43:54