This project is archived and is in readonly mode.

#4960 ✓invalid
Caleb Perkins

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

    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

    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

    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

    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

    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

    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

    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 }
    
  • Jeremy Kemper

    Jeremy Kemper October 15th, 2010 @ 11:01 PM

    • Milestone set to 3.0.2

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>

Pages