Reputation: 6568
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
Upvotes: 1
Views: 210
Reputation: 6568
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.
Upvotes: 0
Reputation: 50057
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.
Upvotes: 1
Reputation: 1008
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)
Upvotes: 1