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.

Committing to Rails Core

In our last post we talked about upgrading to Rails 2.3, and the issues we encountered. One bug we found was that multiple POST requests issued in a test didn’t reset the post parameters between requests. The patch Peter submitted is now part of the Rails core, and we are very happy about it.

Perhaps not because we Saved the Rails Community with this minor feature, but our ambition at Newsdesk has always been to contribute actively to the open source community. And this is our first contribution to Rails!

Peter talks more about this in his private blog.

Upgrading to Rails 2.3

We just upgraded our app from Rails 2.2.2 to Rails 2.3.2 and were able to get all our tests passing after having ironed out a number of deprecations, upgraded a few plugins, and patched a few others. Here is an outline of the changes we had to make:

- Rails has an issue with tests that issue multiple POST requests. We created a patch for this.

- Changed patch of request object to use new class Rack::Request
- Renamed app/controllers/application.rb to app/controllers/application_controller.rb
- Changed Test::Unit::TestCase in test/test_helper.rb to ActiveSupport::TestCase. Changed Test::Unit::TestCase in test/unit/*.rb to ActiveSupport::TestCase and in test/functional/*.rb to ActionController::TestCase.
- Upgraded will_paginate gem from 2.3.5 to 2.3.8
- Removed session :disabled => true since sessions are lazy loaded now
- Upgraded rspec and rspec-rails to 1.2.0, see http://wiki.github.com/dchelimsky/rspec/configgem-for-rails
- Patched the acts_as_bitfield plugin. The ActiveRecord::Base#attribute_condition method now takes two arguments.
- Added a bunch of new I18n keys:

+  support:
+    array:
+      last_word_connector: “, and ”
+      sentence_connector: and
+      skip_last_comma: false
+      two_words_connector: ” and ”
+      words_connector: “, ”
+  time:
+    am: am
+    formats:
+      default: “%a, %d %b %Y %H:%M:%S %z”
+      long: “%B %d, %Y %H:%M”
+      short: “%d %b %H:%M”
+    pm: pm

- Fixed a failing test related to cookie handling.
- Fixed test of Array#to_sentence that uses different I18n keys now

All in all we spent 2-3 hours or so on the upgrade so it wasn’t too bad, baring any severe issues that we haven’t found yet…

New rake task for the Tranlsate plugin: Google Translate

We just pushed the latest addition to the Translate plugin which adds a new rake task: “rake translate:google FROM=sv TO=en”. This will translate all keys in sv.yaml using Google Translate into english and store them in en.yaml.

This is a very convinient way of testing your application in a translated state, and look for strings that were left un-extracted. Actually, I would say 80% of our application’s strings were translated correctly by Google, so less translation work for us!

The only drawback by this solution is the interpolated strings in yaml (”{{variable}}”) that is handled quite dodgy by Google. Sometimes the returned value would be “variable (())”, sometimes “(()) variable” and sometimes even “((var iable))”, with a broken variable name. Therefore we skip those strings for now. If you have a better solution for this, feel free to fork our repository over at Github and submit a patch!

Have a look at the massive language support at: http://translate.google.com/

This rake task depends on the HTTParty gem by John Nunemaker. Thank you John for making HTTP requests sexy!

Rake Tasks for the Translate Plugin

We’ve added two Rake tasks to the Translate plugin. The lost_in_translation rake task helps find I18n keys in lookups in your code that are missing from your default locale YAML file (i.e. config/locales/sv.yml in our case). The merge_keys Rake task is used in conjunction with Sven Fuchs’s Rails I18n Textmate bundle to move extracted keys and texts into their config/locales YAML file. Those two rake tasks have been quite helpful in our I18n work here at Newsdesk so we figured that we should share them with the community.

swedish_pluralize plugin: Swedish pluralization rules for Rails

For those of you looking for Swedish pluralization for Rails, I just refactored this module of ours into a plugin. You can find it on GitHub: http://github.com/newsdesk/swedish_pluralize/tree/master

It’s extracted from the old swe_rails plugin by Ola Bini, which did a bit more than just pluralize in Swedish. So if pluralize is all you want to do, check out the plugin.

It adds an string inflector like so:

>> “bok”.swedish_pluralize
=> “böcker”

Happy pluralizing!