Tag Archives: ruby on rails

Multilingual page caching in Ruby on Rails

There is plenty of stuff written about caching in Ruby on Rails. You can easily cache anything from objects returned by a query to fragments or even whole pages. Especially storing full pages (known as page caching) in a directory when Apache1 can grab them is really efficient. And there are quite decent tutorials about it.

Sadly, most of the tutorials assume that you live in a small, cozy, speak-english-or-die type of world and your only contact with foreign languages is when you order “pommes frites” at MacDonald’s.2 The rest of us, working on multilingual applications, might have a lot of problems with implementing page caching. Fortunately, it’s not that difficult. Read on to see for yourself.

Continue reading

Advertisements

Cookie handling in multi-domain applications in Ruby on Rails

My team is working on a multilingual multinational application in Rails (I know this sounds incredibly pushy but bear with me). The application is at susuh.de if you want to have a look at it, but it’s still alpha version.

In practice, this multi-multi-blah-blah means that we want to use both various national domains (like susuh.at, susuh.pl — those links don’t function yet, they are only examples) and various subdomains (like pl.susuh.de or en.susuh.pl). The national domains will filter content only to respective country (so susuh.de will only have content from Germany) and the subdomains will be used to change the default language for the national domain (so if you are an English-speaking person living in Germany, en.susuh.de is your place to go). The subdomain will also be important in multilingual countries like Switzerland.

Trying to implement this scheme we’ve run into problems with cookie domain handling in Rails. And cookie problems lead to session problems for users, like being erroneously logged out or loosing other settings.

Cookie Monster
Mandatory Cookie-monster reference (you wouldn’t believe how many hits from Google this provides).

It seems that there are two official (normal) ways of handling this — at least that’s what Google says. Either you set your default session options in environment.rb like this:

ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_domain] = 
  '.susuh.de'

Or you don’t set it at all.

The former lets you set cookies for any subdomain of susuh.de, like pl.susuh.de, but no other domain. The latter sets cookie independently for each subdomain, causing different cookies for pl.susuh.de, en.susuh.de and susuh.pl. Neither is what we really want.

Spice Girls
So tell me what you want, what you really really want?

What we really want is to have the same cookie for any subdomain of susuh.eu and a different one for any subdomain of susuh.pl and so on. Nota bene, I’m not talking about a Single Sign-On problem, this is on much more basic level. We tried experimenting with setting DEFAULT_SESSION_OPTIONS “on the fly” in before_filter, but found out that this is too late (basically, this sets cookie domain for next request).

Fortunately, all is not lost. If all else fails, start reading code. And that’s what I did. The “entry point” for Rails is defined in dispatcher.rb file. Glancing over the code, I noticed something new for me: a before_dispatch callback. Google agreed that this may be a way to go, giving us link to http://m.onkey.org/2007/10/16/dispatcher-callbacks, among others.

Here’s our solution:

require 'dispatcher'
module ActionController
  class Dispatcher
    def set_session_domain
      ApplicationController.session_options.update(
        :session_domain => "#{@request.host.gsub(/^[^.]*/, '')}"
      )
    end
    
    before_dispatch :set_session_domain
  end
end

Does stubbing make your tests brittle?

Stubbing and mocking in unit tests is generally considered a Good Thing. It can make your tests run faster, it helps you not to cross boundaries. But it also makes your tests more brittle.

The reason for this is simple. If you want to stub out some method, you have to do it very precisely. You have to know the underlying implementation and choose a very concrete instance and method for stubbing. This makes your test very tightly coupled to the implementation details of tested class. And tightly coupled is brittle. Let’s look at some trivial example:

Continue reading


Make your tests run 25% faster

How?

By turning off the use_instantiated_fixtures feature.

But why?

Because they’re slow! Didn’t you read the comment in your test_helper.rb? Yes, this one:

# Instantiated fixtures are slow, but give you @david where otherwise you 
# would need people(:david).  If you don't want to migrate your existing 
# test cases which use the @david style and don't mind the speed hit (each 
# instantiated fixtures translates to a database query per test method), 
# then set this back to true.

But what about those nice @david variables?

They must be gone. Sorry. The tests are slow because of them. The above comment explains why.

Continue reading


Looping in a no man’s land

…or: how to put class scope to use

The class scope, i.e. the space inside class declaration, but outside method definitions, is a no man’s land in many languages (particularly in Java). By this I mean that you can define methods, variables, and other classes there and you can even execute some code (in variable initializations) but nothing more. Fortunately, in Ruby empty space between method definitions can be filled with all kinds of useful, executable code. Let’s check a few examples.

Continue reading