views:

46

answers:

2

Hi,

I have a named_scope in my model and want a different condition, based on the locale. On the development this code works perfect, after switching to production the named_scope doesn't work and I get every time the first condition ("de"). I think it's a caching problem? I'm working with 2.3.5. and env settings out of the box.

named_scope :public, 
    :conditions => I18n.locale == "de" || I18n.locale == :de ? ["published=? AND trash=?", true, false] : ["published_#{I18n.locale} =? AND trash=?", true, false]
A: 

Yes, it's a "problem" with the class caching of rails. In production the class is loaded and then cached, since the condition is evaluated in class context this should be the value of I18n.locale when the class was loaded.

To solve the problem you could simply turn it off by setting

config.cache_classes = false

in your 'config/enviroments/production.yml', but this slows down response time.

A better solution would be to use a lambda and pass in the locale

named_scope :public, lambda {|l| 
  if l == :de or l == 'de'
    {:conditions => ["published=? AND trash=?", true, false]}
  else
    {:conditions => ["published_#{l} =? AND trash=?", true, false]}
  end
}

Then you can use it like this:

Article.public(I18n.locale)
gregor
+2  A: 

The value for the conditions option is evaluated during class loading. In the development mode class is loaded for every request. Hence your code works in the development mode.

Create the named scope using a parametrized lambda:

named_scope :published, lambda { |*args| { 
                 name = "_de" if (args.first||"").to_s == 'de'
                 :conditions => ["published#{name} =? AND trash=?", true, false]
                }
              }

You can the lambda as follows:

Post.published # no locale passed
Post.published(locale)  # with locale passed
KandadaBoggu