This project is archived and is in readonly mode.
Scopes cached in production mode
Reported by Caleb Perkins | June 24th, 2010 @ 09:56 PM | in 3.0.2
In Rails 3 beta 4....
class Auction < ActiveRecord::Base
scope :started, lambda { where("starting_at <= ?", Time.now) } # same problem if I use proc instead of lambda
end
If I start the server in production mode and create with an auction with the current starting time, the auction does not appear when I call "Auction.started". It seems Time.now in the scope is evaluated when the server is started and used for all further calls. In development mode the scope seems to return the proper results. Are there any workarounds?
Comments and changes to this ticket
-
Neeraj Singh June 24th, 2010 @ 10:50 PM
ticket #4708 has same issue. I fixed that issue by not caching the arguments. That patch never got picked up. However Pratik did patch the code by caching the arguments.
I am working on a patch for this ticket.
-
Neeraj Singh June 24th, 2010 @ 10:56 PM
@Caleb in script/console in production mode I am getting new value every single time.
class User < ActiveRecord::Base scope :recent, lambda { where("created_at <= ?", Time.now) } end ruby-1.8.7-p249 > User.recent User Load (0.3ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-24 21:55:06.057378') => [] ruby-1.8.7-p249 > User.recent User Load (0.3ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-24 21:55:07.225097') => [] ruby-1.8.7-p249 > User.recent User Load (0.2ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-24 21:55:07.792841') => []
-
Caleb Perkins June 25th, 2010 @ 01:23 AM
Yes, in console mode you get the correct values. However, if you put the code in your controller and use a web server, you do not.
-
Neeraj Singh June 25th, 2010 @ 02:19 AM
Here is my code for rail3 app.
class User < ActiveRecord::Base scope :recent, lambda { where("created_at <= ?", Time.now) } end def index User.recent.all.inspect User.recent.all.inspect render :text => 'done' end
I changed the log settings for production mode to see sql statement.
I started server in production mode. This is the sql statements I got.User Load (0.2ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-25 01:15:31.495205') User Load (0.2ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-25 01:15:31.510747')
When I refresh the page I get this sql
User Load (0.2ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-25 01:15:39.042884') User Load (0.2ms) SELECT "users".* FROM "users" WHERE (created_at <= '2010-06-25 01:15:39.044806')
Could it be possible that some other gem/plugin is interfering with the behavior.
-
Caleb Perkins June 25th, 2010 @ 06:54 AM
I must apologize; the code snippet I posted wasn't the line not working properly. I have found the source of the issue, after disabling all Gems/plugins. The problem is in chaining scopes.
In the following code, Auction.active returns new results depending on the time:
class Auction < ActiveRecord::Base scope :started, lambda { where("starting_at <= ?", Time.now) } scope :unfinished, lambda { where("ending_at > ?", Time.now) } scope :active, lambda {where("ending_at > ?", Time.now).where("starting_at <= ?", Time.now) } end
However, in this code the result of Auction.active is the same from server start:
class Auction < ActiveRecord::Base scope :started, lambda { where("starting_at <= ?", Time.now) } scope :unfinished, lambda { where("ending_at > ?", Time.now) } scope :active, started.unfinished end
-
Neeraj Singh June 25th, 2010 @ 04:27 PM
I did not even know what one could do something like that -- define a scope which in turn depends on other scope.
-
José Valim July 13th, 2010 @ 07:30 PM
- Milestone cleared.
- Assigned user set to José Valim
- State changed from new to invalid
- Importance changed from to Low
You can chain scopes, but they will be evaluated at the moment you call them. That said, when you call started, it will execute the lambda, so it will have a frozen Time.now. In other words, chaining lambda scopes will likely give you the wrong result.
You need to wrap the scope :active in a lambda as well.
scope :active, lambda { started.unfinished }
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>