default scoping confusion

UPDATED: I am setting default scope for some models in a runtime which seems working locally in my development env and my code is given below.

SET_OF_MODELS = [Event, Group, User]
@account = Account.find_by_subdomain(account_subdomain)
SET_OF_MODELS.each { |m| m.set_default_scope(@account.id) }
def set_default_scope(account_id)
 default_scope :conditions=> { :account_id => account_id }
end

If I execute this code in ruby console with say @account1, User.first returns @account1 user whereas if I repeat the code with @account2 then User.first returns @account1 user instead of @account2. And this problem is not revealed while running app in local server but in staging server.

My guess is towards their states if they are really cached but not sure. Can someone explain in depth.

Thanks in advance

Answers


default_scope will save state in its class. It's harmful in concurrent environment because it leads to race condition. So you must isolate scope state between requests.

You can use around_filter

class ApplicationController < ActionController::Base
  around_filter :set_default_scope
  def set_default_scope
    @account = Account.find_by_subdomain(account_subdomain)
    opts = :condition => {:account_id => @account.id}
    Event.send(:with_scope, opts) do 
      Group.send(:with_scope, opts) do 
        User.send(:with_scope, opts) do
          yield
        end
      end
    end
  end
end

You can refactor .send(:with_scope, opts) to a class method like with_account_scope(account_id)


Development differs from production. In production all classes are loaded once and cached, so you can't redefine the default scopes on each request. In development the classes are loaded on each request, to allow easy development: each change you do in the code is visible/active on the next request.

If you really want to, you can disable this behaviour in production. This will make your complete site slower, but maybe that is not really an issue. To turn this off, you have edit your config/environments/production.rb, find the line containing

config.cache_classes = true  

and switch that to false.

Hope this helps.


There is nothing wrong with the above code but the problem was with the server used i.e. thin server. It worked perfectly after replacing thin with mongrel. I think thin wasn't allowing to execute set_default_scope more than once except after loading the application.


Need Your Help

Grab next item in a list based on a field with LINQ

c# linq list

I have a list of employee's, and I'd like to select the next person in the list based on their status. I don't have my source code on hand, but basically my list is formed like this.

Having issue with number of taps in UITapGestureRecognizer

objective-c uitapgesturerecognizer tvos apple-tv

I am trying to run a method by 2 times tapping on tv remote, consider tapping not clicking, but the touch surface does't recognize the taps. Instead, clicking two times runs the doubleTapping metho...