Rails I18n and 404/500 Error Pages

If you have a multilingual site it makes sense for your 404 and 500 error pages to be multilingual as well. Rails supports multilinguality by serving up error pages with a path like public/500.sv.html, where sv is the locale. In the case where Rails itself is fundamentally broken or fails to respond your webserver will respond with public/500.html, so we need that file as well. A way to achieve this is to keep your 404 and 500 pages as ERB templates with I18n.translate lookups under app/views/errors and have a Rake task that generates the static files under public:

That Rake task can then be invoked by Capistrano in an after_update_code deploy hook to make the pages available in production.

Simplest bit.ly API implementation possible?

To use an URL shortener in your project, I would strongly recommend bit.ly. It let you set a custom URL (name) and track traffic, clicks and conversations on micro blogs. But best of all, it should be super-fast and super-stable, since Twitter recently chose bit.ly as their default URL shortening service.
Using the bit.ly REST API is also super-easy! Here is how you do it in Rails:
  1. Sign up to get your API username/password here.
  2. Get HTTParty if you don’t already use it: sudo gem install httparty
  3. Copy the code:
    require 'httparty'
    class Bitly
      include HTTParty
      base_uri 'api.bit.ly'
      basic_auth 'username', 'password'
      format :json
      def self.shorten(url)
        response = get('/shorten', :query => required_params.merge(:longUrl => url))
        response['results'][url]['shortUrl']
      end
      def self.required_params
        {:version => "2.0.1"}
      end
    end
  4. Paste code into lib/bitly.rb. Usage: Bitly.shorten(”longurl”)
This is perfect for, as an example Tweeting your URL’s. (I will get back to our Twitter API implementation at Newsdesk.)
The complete bit.ly API docs are here: http://code.google.com/p/bitly-api/wiki/ApiDocumentation
To extend and share this class - use my Gist: http://gist.github.com/112191

We are off to @media, London!

Tomorrow, we are off to @media, London.

Hope to see you there! If you see someone looking like us - don’t hesitate to say hello!

We imagine London to be something like this:

Rails Development Database Setup Without Migrations

I think a lot of Rails developers have been using the db:migrate Rake task to setup new development databases. The problem with this is that over time migrations tend to grow out of sync with the code, especially if you use model classes in your migrations (which in some cases can be very convenient and DRY). A more robust approach to setting up a development database is to load the schema and seed it with data like the db:setup Rake task in Rails 3 does. Now there are a couple of issues for us in using this approach. First we are not on Rails 3 yet (obviously), second we use schema format SQL so the db:schema:load task doesn’t work (see my patch for fixing this), and third, we don’t have a proper db/seed.rb file yet for setting up all the data that so far has been set up by our migrations. To work around these issues I came up with a task like this. The db/development_data.sql file was created by invoking the db:structure:dump task and exchanging the -s option to pg_dump with -a for data only.

Microformats validator/transformator

Today I found an interesting service for Microformats validation/transforming that I found very useful. If you read my previous post about Newsdesk implementing Microformats for contact people you know that my favorite Microformats “tool/validator” so far is the Operator add-on for Firefox.

In a blog post from the Microformats team I read about an interesting service named Optimus that validates and transform your Microformats at a public URI and get the the data back as XML, JSON and JSON-P.

Choose an URI with a contact mark up at Newsdesk:
http://newsdesk.se/pressroom/newsdesk/contact_person/view/peter-ingman-administration-foeretagsledning-14

and just pass it as parameter to Optimus like this:

/?uri=http://newsdesk.se/pressroom/newsdesk/contact_person/view/peter-ingman-administration-foeretagsledning-14

As result you get a nicely formatted XML view with all Microformat information displayed.

<?xml version="1.0" encoding="UTF-8"?>
<microformats from="http://newsdesk.se/pressroom/newsdesk/contact_person/view/peter-ingman-administration-foeretagsledning-14" title="Newsdesk - Peter Ingman (Administration/företagsledning) - Newsdesk">
<description>Peter Ingman är en av grundarna och VD för Newsdesk.</description>
<hcard>
<email>pingman@newsdesk.se</email>
<fn>Peter Ingman</fn>
<org>Newsdesk</org>
<role>VD</role>
<tel>
<type>Work</type>
<value>08 644 89 51</value>
</tel>
</hcard>
<rel-nofollow>
<nofollow href="http://newsdesk.se/search/news">Sök i medier</nofollow>
<nofollow href="http://newsdesk.se/publish">Publicera</nofollow>
</rel-nofollow>
</microformats>

You can also easily get the response data as JSON and define an Callback function with just adding the parameters format=json and function=cbFunction.

/?uri=http://newsdesk.se/pressroom/newsdesk/contact_person/view/peter-ingman-administration-foeretagsledning-14&format=json&function=cbFunction

cbFunction({
"from": "http://newsdesk.se/pressroom/newsdesk/contact_person/view/peter-ingman-administration-foeretagsledning-14",
"title": "Newsdesk - Peter Ingman (Administration/företagsledning) - Newsdesk",
"hcard": {
"email": ["pingman@newsdesk.se"],
"fn": "Peter Ingman",
"org": ["Newsdesk"],
"role": "VD",
"tel": [{
"type": ["Work"],
"value": "08 644 89 51"
}]
},
"rel-nofollow": {
"nofollow": [{
"href": "http://newsdesk.se/search/news",
"value": "Sök i medier"
},
{
"href": "http://newsdesk.se/publish",
"value": "Publicera"
}]
}
});

Microformats Validation

The Optimus service also supports validation of Microformats. Pass your URI that includes Microformats mark-up and add the parameter format=validate and you will get a validator page with information about possible errors.

See Example here (/?format=validate&uri=http://newsdesk.se/pressroom/newsdesk/contact_person/list)

Microformats hCard and Rich Snippets - get started

As the semantic information of the Web keeps getting more important, the Web needs more structured information and machine-readable information to describe the content of the HTML markup in a better way. A big step forward for the Semantic Web is the recently announcement from Google with the release of “rich snippets” for reviews (hReview) and contacts (hCard) marked-up with either Microformats or RDFa. Yahoo in turn have indexed Microformats and RDFa for over a year, so now two large search engines have pushed the semantic web forward.

Microformats at Newsdesk

At Newsdesk we recently deployed our first Microformats implementation for more than 2800 contact people. The Microformats approach is an easy way to mark-up the existing HTML elements with specific class names and element attributes that still are valid HTML.

How can you see this in action?

The best tool I’ve found so far is the Operator add-on for Mozilla Firefox, simply install it and browse a contact at Newsdesk and you will get the possibility to download contact information to your computer, or simply add the contact to your Yahoo contacts.

Microformats hCard example with Firefox Operator add-on

Microformats at pressroom contacts listing displays a list of contacts marked up with Microformats hCard.

Microformats contact example

Microformats hCard contact with detailed information about the contact and possibility to download contact.

Example of Microformats hCard mark-up

<div id="hcard-Joakim-Westerlund" class="vcard">
<img src="http://newsdesk.se/files/123d405e0dfaf99b9c3cae178ca0e124/resources/ResourceWebImage/thumbnails/joakimwesterlund_small.jpg?1237881798" alt="photo of Joakim Westerlund" class="photo"/>
<a class="url fn" href="http://www.newsdesk.se">Joakim Westerlund</a>
<div class="org">Newsdesk</div>
<a class="email" href="mailto:joakim.westerlund@newsdesk.se">joakim.westerlund@newsdesk.se</a>
<div class="adr">
<div class="street-address">Bondegatan 21</div>
<span class="locality">Stockholm</span>,
<span class="postal-code">116 33</span>
<span class="country-name">Sweden</span>
</div>
</div>

And in HTML the Microformats hCard will be displayed like this:

photo of Joakim Westerlund
Joakim Westerlund

Newsdesk

Bondegatan 21

Stockholm,
116 33
Sweden

See more examples at the Microformats Wiki or use the Microformats creator to define your own hCard markup or visit for more information. Are you interested in using RDFa, have a look at RDFa for HTML authors.

Google Rich snippet

Google will not automatically detect your Microformats. When you have deployed an Microformats hCard or RDFa implementation to your site, you have to fill out a form at Google and submit examples of pages that have implemented the hCard or hReview to let them know you are interested in Rich snippet on Google with your Microformats/RDFa.

Rails bug fix: ActiveRecord::Base#exists? now compatible with include scopes

I was using a default scope for a model with :include and :order options and ran into an issue with the exists? method. We have now refactored the exists? method to invoke find_initial which handles scopes correctly. Thanks Michael for committing this!

Rails Gotcha: Global Methods can Cause ActiveRecord Attribute Methods to Never be Defined

I just ran into a sort of edge case gotcha in the interaction between the acts_as_taggable_on Rails plugin and RSpec. It turns out both libraries define a context method. In the RSpec case it is a global method (defined in Object) and in the plugin case it is the Tagging model context attribute. As you may know ActiveRecord uses method_missing to allow invocations such as Tagging.find_by_context(’foobar’). However, method_missing is also used to define attribute accessor methods (context, context= etc.) the first time you use them. The issue in my case was that the first Tagging model accessor that I invoked was context and since context was already defined in Object by RSpec, method_missing was never invoked and the attribute accessors never defined.

I haven’t had time yet to think this issue through thoroughly, and I am no expert on ActiveRecord, but the most obvious solution seems to be to have the attribute accessors defined when an ActiveRecord::Base class is first loaded. Are there any potential drawbacks to this solution?

Rails Gotcha: Eager Loading Application Classes to Make STI Work

Recent versions of Rails (2.2 and later I think) will eager load all application Ruby classes when booting up the server. However, because of issues with migrations this is not done if you are executing a Rake task that depends on the :environment task (such as db:migrate). It is also not done if cache_classes is set to true, a setting that you have by default in development to allow you to change your Ruby classes and not have to restart the server to see the result. It turns that the lazy loading of application classes in development can lead to breakage of ActiveRecords STI (Single Table Inheritance) support. In our case we had an STI with YouTubeChannel that inherits from ApiChannel and we ran into this behaviour:

>> ApiChannel.send(:subclasses)
=> []
>> ApiChannel.find(1)

# ApiChannel Load (2.5ms)   SELECT * FROM “channels” WHERE (”channels”.”id” = 1) AND ( (”channels”.”type” = ‘ApiChannel’ ) )
ActiveRecord::RecordNotFound: Couldn’t find ApiChannel with ID=1

>> YouTubeChannel
=> YouTubeChannel(…)
>> ApiChannel.send(:subclasses)
=> [YouTubeChannel...]
>> ApiChannel.find(1)

#  ApiChannel Load (0.9ms)   SELECT * FROM “channels” WHERE (”channels”.”id” = 1) AND ( (”channels”.”type” = ‘ApiChannel’ OR “channels”.”type” = ‘YouTubeChannel’ ) )
=> #<YouTubeChannel id: 1…

So what is happening here is that since YouTubeChannel hasn’t been loaded Rails doesn’t know that it exists and ApiChannel.subclasses is empty and ActiveRecord (construct_finder_sql - add_conditions! - type_condition) cannot construct the proper SQL condition.

I’m not sure what the reason is that classes are not eager loaded in development (other than the obvious tomake the server startup time shorter), but for now I have patched the Rails::Initializer like this:

Rails::Initializer.class_eval do
# Allows us to run rake jobs:work in development
def is_delayed_job_rake_task?
$0 =~ /rake$/ && ARGV.detect { |arg| arg =~ /^jobs:/ }
end

# Eager load application classes
def load_application_classes
return if ($rails_rake_task && !is_delayed_job_rake_task?)
if configuration.cache_classes
configuration.eager_load_paths.each do |load_path|
matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
Dir.glob(”#{load_path}/**/*.rb”).sort.each do |file|
require_dependency file.sub(matcher, ‘\1′)
end
end
end
end

New Rails Plugin to shell out with verbose error handling

I was annoyed with the fact that when you use Ruby backticks (i.e. `some_shell_command`) to shell out to an external program and the path to the program is wrong then no exception is raised. In addition, using system and backticks doesn’t allow you to capture standard error. I decided to write a little plugin called shell that allows you to do things like this:

status, output, error = Shell.run(”/opt/local/bin/curl http://example.com”)
# Raise exception on failure:
status, output, error = Shell.run!(”/opt/local/bin/curl http://example.com”)

It turns out some commands will indicate success with an exit code of 0 but still write to standard error. I have put in a special case in the Shell class that treats “No such file or directory” as a failure eventhough we have a zero exit code in that case.

I’m curious to hear from if there is a simpler and more idiomatic way to do this. It seems odd that I have to write a Rails plugin to invoke external programs in an elegant and convenient way.