Category Archives: ruby on rails

Introducing Rails Routes TextMate bundle

I always have a problem parsing Railsnamed routes in my head. It usually takes me a lot of time and effort to decide which controller action or view file is responsible for given path. Of course, it’s easy to tell when you look at:

edit_user_path(@user)

that you probably should go to users_controller.rb and find edit action and views/users/edit.html.haml is the right view file. But when nested routes, prefixes and non-RESTful actions all come to play, you might end up with a monster like:

precreate_new_employer_employer_account_path

Don’t laugh, this is real. So, what’s going on here? What is the action name? Are those “employer” things prefixes or nested routes? Where do I find the view? To answer all these questions, the Rails Routes TextMate bundle was born.

Continue reading


Using assert’s message to boost your unit testing productivity

Here’s a quick tip for enhancing your test writing productivity: use assert‘s last parameter, the message. Virtually all assert_... methods accept it. You may have noticed in the docs that the last parameter is always message = nil or message = "". Too bad the docs don’t give examples on how to use this message. So, let me fix that.
Continue reading


Custom Shoulda macros — a tutorial

Shoulda gem is great not only because it provides you with a very clean and natural way of organizing tests with context and should building blocks, but it also comes with quite a large set of predefined macros that mirror Rails’ validations, relations etc. What’s even better — it’s very easy to create your own macros to further speed up test writing. Modern versions of Shoulda gem allow to do it in a clean and modular way. That’s great news if you are serious about TDD because for every substantial codebase you will end up with even bigger pile of testing code, so any tool helping in encapsulating common test logic or patterns is priceless.

This article is a tutorial on writing custom Shoulda macros: from very simple to quite complex.
Continue reading


TextMate shortcuts you should be using

This is my list of TextMate‘s keyboard shortcuts that are very useful for Ruby and Rails developers, but are not used as widely as they should (according to my very scientific observation on a very representative sample, i.e. my colleagues). I skipped all the obvious ones (like “open file”, “save file”, “go to next window”, “close window” etc.) that most people use anyway. My list includes shortcuts that are very useful but sometimes might be hard to grasp at first or might require a little explanation.
Continue reading


Finally getting GetText to work with Rails 2.2

I18n layer, introduced in Rails 2.2, is said to be “the simplest thing that ever could work”. Too bad they didn’t go for “the simplest thing that could be practical to use”. These two can be very far apart. I have a hard time imagining a real-world app using only bare Rails’ I18n engine.

Another unpleasant thing is that Rails 2.2 broke GetText compatibility, which prevents many projects from migrating to Rails 2.2 or later versions.

Well, not anymore. Thanks to clever guys Masao Mutoh and Michael Grosser, it’s finally possible to get Rails 2.2 running with GetText. Read on for details.
Continue reading


How to: turn off ANSI codes in Rails console

Small tip: when you happen to be running Rails in a console that doesn’t understand ANSI codes (those pesky ←[4;36;1m and ←[0;1m that clutter your display), like for example Windows’ cmd, you can turn them off with:

if RUBY_PLATFORM =~ /mswin32/
  ActiveRecord::Base.colorize_logging = false
end

Put this in config/environments/development.rb and restart script/server.

Took me a while to find it, so I thought I’d post it for posterity :)


Breadcrumbs II: the Internationalization

This is a quick followup to my breadcrumb solution. If your application is internationalized, I think you might be interested in the code presented below. If not, stick with the original version.

Continue reading


Easy and flexible breadcrumbs for Rails

Most projects I work on require some implementation of breadcrumbs. Unfortunately most solutions that I found take the very simplistic approach: they split the URL and present each part as a link. I really have a hard time imagining that this can be sufficient for any non-trivial app.

I also found session-based implementation, but according to the above mentioned Wikipedia article classification these are path-style breadcrumbs, while I need location-style with a little bit of attribute-style mixed in where needed. That is, the breadcrumbs should normally reflect the page’s location in some (virtual) website hierarchy. Sometimes, while browsing things that are naturally hierarchical (like forum threads/posts, category trees and so on), the breadcrumb trail should also reflect this hierarchy. Read on to see my take on this problem.

Continue reading


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


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


Rails plugins & svn:externals

Rails plugins are cool. Installing them as svn:externals is cool (mostly). What is not so cool is that some plugins have svn:externals incompatible URLs. In my current project there are two such plugins:

When you install them with script/plugin install -x, they are installed as for-1.2 and trunk, respectively. This is because Rails’ plugin installer takes the final part of a URL as the plugin name and apparently there is no way to change it.

Of course, names like trunk are not very good. In bigger projects with several plugins it may be difficult to remember which name points to which plugin. It’s also easy to imagine that someday we might want to use another plugin that has a URL ending with trunk.

You cannot change names of external directories with svn move and mv tool also doesn’t seem to work. Fortunately, I found other ways to fix this situation.
Continue reading


RESTful Rails: extending scaffold_resource generator

The scaffold_resource generator is quite cool, but lacks one feature that my team found quite useful. Sometimes we want to generate RESTful scaffold with different names for model and controller.

Why would we want that? Well, mostly because in some cases we want to have two separate controllers for one model. The first controller contains ordinary functionality and the second — stuff only an admin can use. We feel that this separation is helpful for maintenance.

For example, we want to have User model class, UsersController accessed as /users/... with methods for signup, user profile edition etc. and AdminUsersController accessed as /admin_users/... with administrative functionality like deleting, granting or revoking access rights etc.

Unfortunately, Rails’ standard scaffold_resource generator only accepts model name and derives all other names from that. So it’s either User and UsersController or AdminUser and AdminUsersController. One possible solution is to generate it both ways, then delete AdminUser and manually change AdminUserController and its views to use User instead. This requires editing several files which is tedious and error-prone.

‘There must be a better way’ we said to ourselves and indeed there is: write your own scaffold_resource generator.
Continue reading


Extending Rails’ magic finders

One of the many cool things of Ruby on Rails are magic finders, or Dynamic attribute-based finders as the documentation calls them. Thanks to them we can write:

User.find_by_login_and_status(some_login, 1)

instead of:

User.find(:first, ['login = ? and status = ?', some_login, 1])

The first form is shorter and easier for human to parse.

Unfortunately, we can only combine attributes using and operator, but the possibility to use or and not operators would also be nice. And, as always when using Ruby on Rails, when we find that library is lacking some feature, we can easily add it. Let’s see how to do it.
Continue reading


Self-referential many-to-many relations in Ruby on Rails

…or is my friend’s friend my friend too?

Recently I tried to implement a feature that is commonly used in social sites like Xing or Linked-in: a friends list, also known as buddy list or contacts list. Basically this means that a user can link to any other user to indicate that they are friends or know each other. Normally, the other party has to confirm the link proposition for the link to be established. Having a contact network, the site can implement various cool features, like finding the shortest path between two random users or telling you that there are ’820 contacts of your contacts’.

Implementing this proved not to be that easy in Ruby on Rails, partly because of lack of documentation and mostly because of my poor knowledge of Rails, so here’s a solution that works for me. It should be noted that this is rather a story of trial and error (although I will spare you visiting all the blind alleys with me) than an emanation of guru-like knowledge, so if anyone knows a better way, I’ll be glad to hear about it.
Continue reading


Follow

Get every new post delivered to your Inbox.