Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work with database now() :) #7

Closed
szymon-przybyl opened this issue Aug 21, 2011 · 7 comments
Closed

Does not work with database now() :) #7

szymon-przybyl opened this issue Aug 21, 2011 · 7 comments

Comments

@szymon-przybyl
Copy link

Hi!

I was trying to test my expiring activeness of product (just scope in activerecord):

scope :active, where('expires_at > now()')

but Delorean only travels in ruby time, not in db time :) I know it is highly impossible to mock db time. but maybe somebody have some idea about it? maybe it is better not to use database specific methods, such as random() or now(), but pass for example Time.now converted to database date format? something like this:

scope :active, where("expires_at > #{Time.now}")
@szymon-przybyl
Copy link
Author

Actually i've tried to pass Time.zone.now like this:

class Product < ActiveRecord::Base
  scope :active, where('expires_at IS NOT NULL AND expires_at > ?', Time.zone.now)
end

but it looks like it something breaks Delorean, becouse this code:

puts Product.active.to_sql
Delorean.jump(7.days) { puts Product.active.to_sql }

gives me:

SELECT "products".* FROM "products" WHERE (expires_at IS NOT NULL AND expires_at > '2011-08-21 20:54:10.003969')
SELECT "products".* FROM "products" WHERE (expires_at IS NOT NULL AND expires_at > '2011-08-21 20:54:10.003969')

but with normal use of Time.zone.now:

def active?
  expires_at.present? and expires_at > Time.zone.now
end

Delorean works fine. Any ideas why scope with Time.zone.now disables Delorean time changes? I'm using postgres.

@cavalle
Copy link
Contributor

cavalle commented Aug 22, 2011

It might be the case that Delorean mocks Time.now but not Time.zone.now.

Patches welcomed :)

@cavalle
Copy link
Contributor

cavalle commented Aug 22, 2011

BTW, I don't think Delorean will ever be able to mock database's "now()" function

@szymon-przybyl
Copy link
Author

I'm using Time.zone.now and it looks like Delorean mocks it fine, the problem appears when I pass Time.zone.now to database query - then mocking does not work for some reason.

I'm using Time.zone.now instead of Time.now, becouse it looks like my database is using UTC time for timestamps, and as far as i know Time.zone.now returns UTC time, am I right? Or maybe my database is storing timestamps in my local time and Time.now returns UTC?

@cavalle
Copy link
Contributor

cavalle commented Aug 22, 2011

Ok. That's because Time.zone.now in your example is executed in initialization time which probably is not what you want. You can try using a lambda:

scope :active, lambda { where('expires_at IS NOT NULL AND expires_at > ?', Time.zone.now) }

I'm closing this issue since no changes in Delorean are required

@cavalle cavalle closed this as completed Aug 22, 2011
@szymon-przybyl
Copy link
Author

Even that does not work, that Time.zone.now in that scope seems to be frozen somehow :| It does not changes within time_travel_to block of Delorean.

I've just substracted some days from my product's expires_at date :)

@pierrea
Copy link

pierrea commented Oct 18, 2014

Few years later I faced with this issue.
I came up with this workaround to be able to test my query with Delorean:

(...) .where("expires_at > ?::timestamp", Time.now)

This is a trivial example but I had to manipulate times in Postgres with now(). I couldn't just inject my ruby time instead without casting it with ::timestamp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants