Routing parameters with a dot

Posted by Andreas on Tuesday, May 05, 2009 at 16:35 (CEST)

Last week I received an interesting bug report for an application I’m working on at the office. It has a controller with an index action that displays a list of items which can be filtered by tags. A tester reported that every time he chooses to filter the list by a tag that contains a dot, the site returns an error. First this seems strange since tags with a dot worked perfectly fine in tests.

But after digging deeper, I found a surprising reason for this strange error: To make URLs look nicer, I defined an extra route like this:

1 map.things 'things/:tag', :controller => 'things', :action => 'index',
2   :tag => nil

The intention was, to have /things/foo instead of /things&tag=foo as the URL. This actually worked fine – except for cases when the tag contained a dot.

Read more »

Testing Cookies in Rails 2.3

Posted by Andreas on Tuesday, March 31, 2009 at 00:37 (CEST)

While moving some applications to Rails 2.3 recently, I stumbled across some problems with testing cookies. E.g. this blog uses cookies to remember your name, email address and web url if you leave a comment. This way, you don’t need to re-enter these information the next time you leave a comment. These cookies are set by the controller action that creates new comments (in CommentsController#create):

1 cookies['blog_visitor_name'] = { :value => @comment.name, :expires => 1.year.from_now }

This is the extended form of setting a cookie (a hash is used to not only set the cookies value but also the expiration time. There are several more hash options available which are described in the ActionController#cookies documentation. The basic form (which only sets a simple session cookie that is valid until the visitor closes the browser) uses a simple string:

Read more »

CSS Naked Day 2009: a Rails plugin

Posted by Andreas on Saturday, February 28, 2009 at 22:01 (CET)

On April 9th 2009, the fourth CSS Naked Day event will take place. The idea behind this event is to promote web standards (like proper semantic markup and a good hierarchy structure). On April 9th, participants are encouraged to completely remove all stylesheets from their site, stripping it entirely of its design. If your site has proper semantic markup, it’ll stay well usable and understandable even without styles. If not, you better hide and don’t take part in this event :)

To make it as easy as possible, I created a little Rails plugin that, once installed to an app, simply disables the stylesheet_link_tag helper for the duration of the event. It’s as easy as install and forget (assuming that you used stylesheet_link_tag in your layouts and didn’t add inline styles or stylesheet links manually).

So let’s see how many sites will join this funny but yet expressive event this year. It’s time to show off your <body> ;-)

Let browsers cache static files to greatly speed up your site

Posted by Andreas on Thursday, January 22, 2009 at 23:06 (CET)

There are many factors that determine how long a page takes to show up in a browser. When a page is requested by a browser, the server needs some time to compute the page contents (controller, model/database, view) and returns HTML to the browser. Besides network latency and throughput (which can be optimized by choosing a good hosting provider), there are several ways to speed up the page generation itself (like memoization, action/fragment/query-caching, using memcached, and so on).

But even after the HTML page itself has been transferred to the browser, the page is not necessarily ready to display yet. A page usually references more resources like stylesheets, javascripts and images that need to be requested and transferred. These are mostly static files (located in the public folder of a Rails application) and are directly served by the webserver without invoking the Rails application. So these files takes very little computation time on the server, but they still need some time and bandwith to transfer, which can be optimized.

Read more »

Selecting the locale for a request

Posted by Andreas on Friday, January 09, 2009 at 18:35 (CET)

Rails I18N gives you a way to translate your views and easily switch between different languages. However, you still need to set the locale for each request, i.e. you have to choose a method to select the right locale for a request. This can be done in various ways, depending on how you perfer it to behave. Here are some examples.

  1. by browser-setting
  2. by toplevel domain
  3. by subdomain
  4. by manual selection
Read more »

Email address scrambling methods compared

Posted by Andreas on Saturday, December 27, 2008 at 20:46 (CET)

A while ago, I wrote about different methods in JavaScript to prevent spam harvesters from recognizing an email address. These methods work by placing a scrambled version of the email address into the page source so that a spam harvester cannot recognize it as an email address. Using JavaScript, the scrambled text is unscrambled and displayed as usual to human visitors. Usually, the “scrambling” is based on replacing characters of the email address with its hex-entities (Rails’ mail_to helper does so if using :encode => :hex or :encode => :javascript). My theory was/is, that using hex-entities is not sufficient anymore nowadays, since they can be easily reversed with simple search-and-replace operations.

So I came up with the idea to use a scrambling method that cannot be easily reversed. I assumed that spam harvesters probably can decode hex-entities, but still aren’t able to execute JavaScript. However since this was just an assumption, I started a simple test over the last 6 months to find out how good or bad the different scrambling methods perform.

Read more »

How to use i18n string interpolation

Posted by Andreas on Monday, December 01, 2008 at 13:13 (CET)

Since Rails 2.2 has been released last week, lots of people are beginning to translate their applications — or, at least, many people seem to prepare their applications for later translation by replacing strings in views with t() calls.

If you’re modifying your application to be i18n-ready, or if you’re creating a new multilingual application, here’s a useful guideline to remember: translate meanings, not words.

Read more »

Running Rails 2.2 with i18n

Posted by Andreas on Thursday, November 27, 2008 at 23:33 (CET)

Just a quick note that this blog is now running Rails 2.2 and makes use of the new i18n framework. Although this site is completely in English, the same application is also serving another blog in German. Moving the blog application from ruby-gettext translations to Rails i18n was quite a bit of work since the i18n simple backend works differently and after all, I had to recreate all translation files.

In the end, it works very well and reliable. While working with i18n views, I had some small ideas for improving translation handling in views – maybe I can come up with some minor improvements after thinking about it some more.

The main difference between gettext and Rails i18n is the usage of translation keys. With gettext, you place full strings of the “master language” (usually English) into the views. With Rails i18n, you build up a hierarchical structure of translation symbols (like “sidebar.latest.title”) and associate them with real text in translation files. Currently there’s no tool to extract symbols used in views to assist you to keep translations complete (like rgettext does for gettext), but I guess helpers will appear soon.

For my translations, I used the i18n simple backend, which comes with Rails and stores translation strings in simply .yml files. However, the Rails i18n framework actually is much more than just translations in .yml-files. It allows translation backends to hook into the Rails core with a documented interface, which promises to be more stable and reliable than monkeypatching solutions (e.g. like ruby-gettext does). In theory, it should be possible to create an i18n backend that utilizes gettext — which certainly is still very interesting e.g. to upgrade existing applications or for large applications with many translators (since the gettext format is widely supported by a lot of tools and services).

Recursive git: rgit

Posted by Andreas on Thursday, October 30, 2008 at 11:24 (CET)

Here’s a little helper that runs a git command on every repository found in subdirs. Put the following ruby code into a file called rgit, make it executable and save it to a bin directory, like /usr/local/bin:

1 #!/usr/bin/env ruby

if ARGV.empty?
STDERR.puts “usage: #{File.basename($0)} <cmd> …”
STDERR.puts " Runs git <cmd> in every repository found in subdirs"
exit
end

dirs = Dir.glob(‘**/.git’).map { |d| d.chomp(‘/.git’) }

dirs.each do |dir|
puts “→ #{dir}”
Dir.chdir(dir) do
system ‘git’, *ARGV
end
end

I’m using rgit pull or rgit fetch every morning to retrieve the latest code changes and rgit push every evening to make sure all my changes get pushed to the server. rgit repack -a -d is useful to cleanup all local repositories.

Todo: git submodules should be filtered out. Currently, they are processed like normal repositories, which probably is not what you want.

Why I'm starting to like JRuby even though I dislike Java

Posted by Andreas on Saturday, September 27, 2008 at 01:36 (CEST)

Among my friends, it’s not a secret that I personally don’t like Java. During my time at the university, I had to deal with it for some courses, but somehow nobody could convince me to really like the language. With Ruby, it was the exact opposite – I saw a few code examples, read some articles about it and I immediately started to like the language and its charming way of doing OO like I always wanted it to be.

When I discovered JRuby, I therefore didn’t take it serious and overlooked its potential. Today, I’m starting to like JRuby. Why? Because JRuby is actually pretty cool. It runs code of my favorite language (Ruby) on a wide-spread and highly optimized platform (the Java Virtual Machine, aka JVM). You can use JRuby to run Ruby code without even knowing a single bit about Java – but it runs on the JVM (which has several advantages as stated below).

Read more »