Community Highlights

I’m always impressed by the continuous flow of innovation from the Rails community. Below are just a few of the highlights from the past month. These stories all came from the Ruby5 Podcast, which covers all the news from the Ruby and Rails community twice weekly.

Authentication

The talented Brazilian guys over at Plataformatec released the Devise gem this week, a new authentication option for your Rails app. Devise is a Rails Engine which sits on top of Warden, a Rack authentication framework. This makes Devise a little more flexible then other Rails authentication libraries, and is definitely worth a look.

On the otherhand if your application needs something more simple, check out Terry Heath’s OpenID Rails Engine. It should take you about 10 minutes to have an authentication system up and running, and you won’t have to worry about storing your users’ passwords.

Helpful Libraries

Thanks to Twitter’s new Streaming API we no longer have to poll every 5 seconds to discover new tweets. To start using it today check out the TweetStream Gem by Intridea.

With Rails 2.3 we gained the ability to utilize Rack Middleware in our Rails apps. If you don’t know what Rack middleware is yet go watch this screencast. Also, if you’d like some idea on how to use it, check out the CodeRack Middleware Contest, a competition to develop more useful and top quality Rack middleware.

A few weeks ago I heard about a javascript library called Validatious, which provides unobtrusive javascript for doing client side form validations. I know what you’re thinking though, “if I do both client side and server side validations I’ll have code which duplicates validation logic, and that makes me want to hurl.” Don’t hurl quite yet, first check out Jonas Grimfelt’s Validatious on Rails plugin which will auto-generate client-side validations using your existing model validations.

Optimization & Performance

If your Rails app needs to be able to handle many users uploading files at the same time (think Flickr), then you may want to look at ModPorter, an Apache module and Rails plugin created by Pratik Naik and Michael Koziarski. ModPorter parses incoming multipart requests storing the file to disk before it reaches your Rails app, so your Rails processes don’t get held up. We hear there is also support for nginx through a 3rd party module.

When you’re dealing with a database abstraction like ActiveRecord, it’s very important to ensure you’re writing optimal database queries. If you’re worried that your app may be doing more queries then it should or isn’t using eager loading properly, you may want to checkout the Bullet plugin by Richard Huang. Bullet can actually give you growl notifications when you’re missing an :include or should be using a counter cache.

Do you have mongrels that are consuming more then 150 Megs of RAM and you don’t know why? Do you suspect that it might be Ruby leaking all over the place? Then you’d probably be wrong, and Sudara Williams will tell you That’s not a Memory Leak, It’s Bloat. It’s more likely that you’re instantiating thousands of ActiveRecord objects, and Sudara gives you a few suggestions on how to find them.

Cleaning up code

The presenter pattern is very useful for encapsulating code that may be making your controller look fat, code that may not belong in your model. Dmyto Shteflyuk wrote up a great introduction to using presenters that’s worth a read if you’re not using them already.

Sending complex data-sets between Ruby and Javascript isn’t always easy. Don’t you wish there was a way to take that Ruby hash and just have it automatically transform into a javascript Map? If yes, then you may want to look at jsvars by Erick Schmitt, that’s what it does.

Deployment

You may already know about Chef (the system integration framework) but did you know that you can also deploy your Ruby app from chef using chef-deploy? Ezra Zygmuntovich created this gem which allows you to run your chef recipes and then if they pass (and only if they pass) deploy your code in a capistrano like fashion.

If you’re deploying a Rails cluster to Amazon EC2, then another solution aside from using Chef is a gem called rubber by Matthew Conway. Rubber keeps deployment a first class citizen, storing all your server configuration files inside your Rails app where they can quickly be tweaked under version control. It comes with many deployment best practices out of the box and can scale up or down at a moments notice.

Media

Have you ever wanted to run a Rails tutorial in your city, but you’re discouraged by the thought of writing all the course material? Then you need to checkout the Rails Bridge Open Workshop project where they have all the course material you’re going to need, for free! You have no excuse not to spread the word of Rails anymore.

Lastly, if you’re looking for additional Rails screencasts, you may want to checkout Teach Me To Code, and if you’re looking for additional Rails reading, then check out the past few issues of the Rails Magazine by Olimpiu Metiu.

Thanks for reading, and if you have any Ruby or Rails news you’d like to spread the word about, please send it into the Ruby5 podcast by emailing ruby5@envylabs.com.

Image Credit: Blue Sky on Rails by ecstaticist, Analog Solutions 606 Mod by Formication, Rainbow by One Good Bumblebee. Orange County Security by henning, Broom by fatman, remember by tochis, Darwin Was Right About Media Players! by Neeku.

What's New in Edge Rails

So, Edge Rails is still chugging right along. There are new and interesting fixes, changes, and refactors going on all of the time. So, lets take a look at just a few that’ve gone in since the last post (it’s been a while, I know, I’m sorry!).

ActionView and Helpers

XSS escaping is now enabled by default. This means that if you want to explicitly output HTML to your views, you’ll probably have to mark it as html_safe! before sending it through.

<%= 'my <a href="http://www.rubyonrails.org">safe</a> string'.html_safe! %>

Many of the built-in helpers have been updated for this change and if you see an issues with the Rails helpers being incorrectly sanitized, you should create a new ticket.

distance_of_time_in_words has gained ‘over’, ‘about’, and ‘almost’ keywords, thanks to Jay Pignata and John Trupiano. This provides you with an improved level of granularity when approximating the amount time passed. So, instead of just “2 years ago”, it can now also report “almost 2 years ago,” “about 2 years ago,” and “over 2 years ago,” depending on the proximity to being exactly 2 years old.

assert_equal "almost 2 years",  distance_of_time_in_words(from, to + 2.years - 3.months + 1.day)
assert_equal "about 2 years",   distance_of_time_in_words(from, to + 2.years + 3.months - 1.day)
assert_equal "over 2 years",    distance_of_time_in_words(from, to + 2.years + 3.months + 1.day)
assert_equal "over 2 years",    distance_of_time_in_words(from, to + 2.years + 9.months - 1.day)
assert_equal "almost 3 years",  distance_of_time_in_words(from, to + 2.years + 9.months + 1.day)

The HTML form helper, fields_for - generally used for nesting additional model forms - now allows for explicit collections to be used, thanks to Andrew France. So, instead of just including all of your blog.posts, you should have it only display your published blog.posts, for example. Or:

<% form_for @person, :url => { :action => "update" } do |person_form| %>
  ...
  <% person_form.fields_for :projects, @active_projects do |project_fields| %>
    Name: <%= project_fields.text_field :name %>
  <% end %>
<% end %>

API Change for content_tag_for: The third argument - being the optional CSS prefix - will now also affect the generated CSS class. This prefix will now be appended to the generated element’s CLASS attribute.

<%= content_tag_for(:li, @post, :published) %>
# => <li id="published_post_123" class="published_post">...</li>

ActiveResource and ActiveRecord

Taryn East has added update_attribute(s) methods to ActiveResource. These methods act very similarly to the ActiveRecord methods we already know and love.

Building or creating an object through a has_one association that contains conditionals will now automatically append those conditions to the newly created object, thanks to Luciano Panaro.

class Blog
  has_author :commit_author, :class_name => 'Author', :conditions => {:name => "Luciano Panaro"}
end

@blog.build_commit_author
# => #<Author name: "Luciano Panaro" ... >

Pratik Naik added a new option to ActiveRecord’s accepts_nested_attributes_for to :limit the number of records that are allowed to be processed. Also, while we’re covering accepts_nested_attributes_for, José Valim as renamed the _delete option to _destroy to better follow what is actually occurring. A deprecation warning has been added to _delete, for the time being.

Jacob Burkhart updated the new autosave option in Rails 2.3 to allow for an :autosave => false, which will disallow saving of associated objects, even when they are new_record?s.

Some Internals

Previously, CDATA elements could be ignored when converting from XML to a Hash, so now, thanks to John Pignata, Hash#from_xml will now properly parse and include CDATA elements values.

Josh Peek has relocated global exception handling into ActionDispatch::Rescue. So, this is now being handled at the Rack middleware level.

And finally, Yehuda Katz and Carl Lerche began work on a Rails::Application object to better encapsulate some of the application start up and configuration details. Also, a good bit of initialization has now gone on to move into this new object.

Remember, if you prefer to have a shorter audio summary of some of this content and more, you should check out the Ruby5 podcast over at Envy Labs; it’s released every Tuesday and Friday with the latest news in the Ruby and Rails community.

Photo: Clock Tower by Brian Taylor

RubyEnRails 2009

RubyEnRails 2009 goes down this 30/31 October in Amsterdam. Talks are in English and Dutch.

RubyEnRails has been all-volunteer for four years running, building on a history of sweet venues, good talks, and great company. It’s gradually grown from a local gathering to a full-fledged European event, and this year it’s also stepping up to fill the shoes of RailsConf EU.

Yehuda and I are speaking and will be mixing a potent batch of Rails 3 kool-aid. Please join us for a sip!

What's New in Edge Rails: The Security Edition

It’s been a bit over two weeks since the last WNiER (“winner”?) post and in the time since our last visit, Ruby on Rails 2.3.4 was released to fix some reported security issues. It is important that you try to upgrade your applications as soon as possible, or even just apply the provided patches if a full upgrade isn’t easily accomplished in your situation.

Along with this release, you’re also going to see several bug fixes and enhancements to the Rails framework, coming from many contributors, that have been discussed here over the previous weeks and even a few that are mentioned just below.

Security updates

Michael Koziarski posted fixes (here and here) for cleaning and verifying multibyte (unicode) strings. The problem was reported by Brian Mastenbrook and Manfred Stienstra provided input for the fix. These changes should disallow malformed unicode strings from getting past the HTML escaping logic provided by the form helpers.

Coda Hale reported and also added a patch to Rails, fixing a timing attack vulnerability in ActiveSupport::MessageVerifier. Although not likely to be exploited in the wild, the vulnerability may allow an attacker to forge the signatures which encode your application’s cookie store. If successfully broken, an attacker could modify their session objects without altering your application to the change.

There have been some issues reported around the Rails 2.3.4 release, specifically with regard to Ruby 1.9 support. While they have not all yet been fully substantiated, this certainly underscores the importance of having proper test coverage and both a staging and production environment for your applications.

Down to the metal

Yehuda Katz and Carl Lerche put in quite a bit of work around ActionController::Metal and Rack’s Middleware, recently. ActionController::Metal now acts as a Rack middleware and at the same time, there is a new ActionController::Middleware class that operates as normal Rack middleware.

And, if that wasn’t enough, Yehuda went on to add ActiveModel::Lint. ActiveModel::Lint allows you to determine whether or not an object is compliant with the ActiveModel API, via:

	ActiveModel::Compliance.test(object)

The output is similar to a Test::Unit output and will indicate with which portions of the ActiveModel API the given object is - or more importantly is not - compliant.

If Metal is your thing, you may want to take a look at Yehuda Katz’s recent blog post, How to Build Sinatra on Rails 3.

Pour some sugar on me

Quite a few changes, small and large, occurred around ActiveRecord and friends. Most of these cleaned up some existing functionality, either making it easier to use, perform more closely to what would be expected, or even adding some new features that will soon feel like old friends.

Taryn East added a little ActiveRecord-like love to ActiveResource. In this patch, ActiveResource received the familiar first, last, and all shortcut methods for wrapping the basic find method.

Proc and symbol support was added to the validates_numericality_of ActiveRecord validation, by Kane.

For those of you who use the :anchor option when generating URLs, you may notice that after this patch by Jeffrey Hardy, Rails will now execute the to_param method on the object provided as an :anchor.

	@post 		= Post.first
	@comment 	= Comment.first
	post_url(@post, :anchor => @comment) # => http://www.example.com/posts/1#comment-1

Well, something similar to that, anyway. :) This updates the :anchor options to follow a similar functionality as the other options provided when generating URLs.

José Valim cleaned up some bits in the Rails scaffold. The generated new and edit views will now reference a new _form partial. This is a much DRYer way to go about it, and more closely follows what would likely happen if you were to code it yourself. Also, while he was there, he removed a bit of inline CSS (specifically, a green flash message), in favor of a CSS class and updating the default scaffold stylesheet.

And, probably the most interesting change in this group is the addition of a new ActivRecord#previous_changes method, by Scott Barr. previous_changes allows you to see what changed before the last save in your local ActiveRecord object instance. This is particularly useful when calling after_save methods which might need to know what exactly had changed. I’ll let him give you a code sample:

	person 			= Person.find_by_name('bob')
  person.name = 'robert'
  person.changes 						# => {'name' => ['bob, 'robert']}
  person.save
  person.changes 						# => {}
  person.previous_changes 	# => {'name' => ['bob, 'robert']}
  person.reload
  person.previous_changes 	# => {}

Okay, let’s do it your way

While a lot of us prefer US English, we (begrudgingly) recognize that we aren’t always the center of the universe. As such, there are some more localization updates to report in Edge Rails:

Sven Fuchs added localization support to the ActiveRecord::RecordInvalid exception’s error message. Then, Akira Matsuda followed Sven with support for localizing the SELECT tag helper’s prompt text (the default being, “Please select”).

Finally, this is certainly a welcome addition and potentially a major player in localization support within Rails: Antonio Tapiador del Dujo added a patch which allows Rails plugins to define and maintain their own locale files. All that is necessary for the plugin developer to do is to provide a config/locales/ directory within their plugin and then create their own .rb or .yml files (i.e. en.yml). That means that plugins can now be much more responsible for their own localization support and do not have to modify the application’s locale files after installation.

Food for thought

Finally, just a small note that the default, preferred table collation for MySQL has been changed. Previously, Rails defaulted to utf8_general_ci when either the database or the table creation script did not dictate otherwise. Now, that has been changed to utf8_unicode_ci. Certainly worth a note with so many Rails applications using MySQL in their back-end.

Update: Set the attribution of previous_changes to Scott Barr. Sorry, Scott!

Photo: Security at the Hoover Dam by Alex E. Proimos

Ruby on Rails 2.3.4: Security Fixes

We’ve released Ruby on Rails 2.3.4, this release fixes bugs and introduces a few minor features. Due to the inclusion of two security fixes, all users of the 2.3 series are recommended to upgrade as soon as possible.

Security Fixes

2.3.4 contains fixes for two security issues which were reported to us. For more details see the security announcements:

Bug Fixes

Thanks to the success of the BugMash we have around 100 bug fixes as part of this release. Of particular not is the fix to reloading problems related to rack middleware and rails metals when running in development mode.

New Features

  • Support for bundling I18n translations in plugins, Rails will now automatically add locale files found in any engine’s locale directory to the I18n.load_path. commit
  • Added db/seeds.rb as a default file for storing seed data for the database. Can be loaded with rake db:seed commit

Timing Weakness in Ruby on Rails

There is a weakness in the code Ruby on Rails uses to verify message
digests in the cookie store. Because it uses a non-constant time algorithm to
verify the signatures an attacker may be able to determine when a forged
signature is partially correct. By repeating this process they may be able to successfully forge a digest.

Versions Affected:  2.1.0 and *all* subsequent versions.
Fixed Versions:     2.3.4, 2.2.3

Impact

Due to issues like network latency, non-deterministic GC runs and other
issues it is unlikely that this attack could be exploited in the wild
within a reasonable timeframe. However users should still upgrade as
soon as possible to remove the weakness.

Releases

The 2.3.4 and 2.2.3 releases will be made available shortly and will contain fixes for this issue amongst others.

Patches

In order to provide the fixes for users who are running unsupported
releases, or are unable to upgrade at present we have provided patches
against all affected stable release branches.

The patches are in a format suitable for git-am and consist a single
changeset which implements

Credits

Thanks to Coda Hale for reporting the bug to us, and helping us with the fixes.

XSS Vulnerability in Ruby on Rails

There is a vulnerability in the escaping code for the form helpers in
Ruby on Rails. Attackers who can inject deliberately malformed unicode
strings into the form helpers can defeat the escaping checks and inject
arbitrary HTML.

Versions Affected:  2.0.0 and *all* subsequent versions.
Not affected:       Applications running on ruby 1.9
Fixed Versions:     2.3.4, 2.2.3
Candidate CVE:      CVE-2009-3009

Impact

Due to the way that most databases either don’t accept or actively
cleanse malformed unicode strings this vulnerability is most likely to
be exploited by non-persistent attacks however persistent attacks may
still be possible in some configurations.

All users of affected versions are advised to upgrade to a fixed versions.

Releases

The 2.3.4 and 2.2.3 releases will be made available shortly and contain fixes for this issue.

Patches

In order to provide the fixes for users who are running unsupported
releases, or are unable to upgrade at present we have provided patches
against all affected stable release branches.

The patches are in a format suitable for git-am and consist of two
changesets. The code for cleansing multi-byte strings, and the
introduction of that code to the relevant helpers.

Please note that only the 2.2.x and 2.3.x series are supported at
present. Users of earlier unsupported releases are advised to upgrade
sooner rather than later as we cannot guarantee that future issues will
be backported in this manner.

Credits

Thanks to Brian Mastenbrook for reporting the vulnerability to us, and Manfred Stienstra from Fingertips for his work with us on the fix.

A Month in Rails

Lots of great content coming out of the community in the past month. Below you’ll find some of the most useful tutorials and libraries I’ve found over the past few weeks. These stories came directly from the Ruby5 podcast, which covers news from the Ruby and Rails community twice weekly.

Improving your Rails code

James Golick released a gem called Observational recently which provides you with a better way of using observers in Rails. Instead of creating one file per observer, this gem allows you to define multiple observed objects and specific methods to call for each object’s events.

If you want to develop a Rails app that takes advantage of Subdomains Taylor Luk has the recipe. He recommends using subdomain-fu, shows how to use a Proxy PAC file in development, and introduces a piece of Rack middleware he wrote which allows you to use full custom domains in your application.

If you like to TATFT like the rest of us, I have two libraries to tell you about. The first is a gem by the guys over at Devver called Construct which makes it easy to test code which interacts with your filesystem. The second is Blue Ridge by Larry Karnowski and Chris Redinger which makes it easy to write tests for your javascript. Blue Ridge has been out for a while, but this week Noel Rappin wrote a great introductory article to get you started.

Just yesterday Fabio Akita put together a screencast showing how the “Weblog in 15 minutes” code could be simplified using Inherited Resources, a gem by José Valim which helps reduce controller code duplication. The gem uses the same sort of technique you may have seen before with make_resourceful or resource_controller, but has improved syntactic sugar.

Libraries you should know about

Patrick McKenzie released A/Bingo, a gem/plugin for your Rails application that makes A/B Testing easy. It uses a fairly intuitive and simple interface for defining your tests and provides information on which sample performed best and by what margins.

Steve Richert released a gem called vestal_versions which allows you to keep a history of all of your ActiveRecord model changes in your database. It takes advantage of several newer features in Rails 2.2+ including recognizing dirty objects.

Railscast #176 by Ryan Bates covered Searchlogic by Ben Johnson, which makes it really easy to create advanced search forms in Rails.

David Bock released new gem called Crondonkulous which allows you to write crontab recipes in Ruby from within your Rails application. These recipes get automatically published to your server’s crontab when you deploy.

Security

James Harton released Lockbox and acts_as_lockbox, which provide a simple interface for securing sensitive data by managing RSA public key cryptography for your application. This allows you to define which attributes are sensitive and provides an application-wide locking and unlocking ability.

Hongli Lai wrote up a great article on keeping your user’s passwords secure. He writes about how to store passwords, hashing algorithms, salting, and more. Specifically, he recommends using Blowfish File Encryption, or “bcrypt,” because it’s a slower-running algorithm which will make it more difficult to crack.

In your Database

Mauricio Linhares released a plugin for Rails which allows you to do master / slave replication. Unlike masochism, master_slave_adapter works in conjunction with the Rails database connection pool and is implemented as a new database adapter. So, no monkey patching necessary.

Matt Jankowski provided a great article on properly indexing your database for your Rails application. He covers indexing validation and STI columns, state columns for state machines, association columns, and more.

The developers of xing created a plugin called FlagShihTzu. It’s not a dog.. or even a multiplayer game for your Tamagotchi. FlagShihTzu stores any number of ActiveRecord boolean model attributes as a single database field, using each bit as unique keys. But, the interesting part is that the interface remains exactly the same to the rest of your application.


Thanks for reading and if you have any news or libraries you’d like to get the word out about, feel free to drop me a line by submitting news over at Ruby5.

Image Credit: Blue Sky on Rails by ecstaticist, Analog Solutions 606 Mod by Formication, RailsConf Europe 2006 by Paul Watson, Rainbow by One Good Bumblebee. Orange County Security by henning

Gem Packaging: Best Practices

Understand Ruby’s Load Path

When you call load or require a new file, Ruby searches through the files in its load path. This allows you to require files relative to the load path without specifying the files full system path.

The initial load path contains paths for Ruby’s standard library. There are three aliases that point to Rubys global load path array: $:, $-I, $LOAD_PATH. You can append or prepend you own libraries to this list. The load path can also be modified from the command line with the -I flag.

Here is the initial load path on my Mac.

  >> $LOAD_PATH
  => ["/Users/josh/.rip/active/lib",
      "/Library/Ruby/Site/1.8",
      "/Library/Ruby/Site/1.8/powerpc-darwin9.0",
      "/Library/Ruby/Site/1.8/universal-darwin9.0",
      "/Library/Ruby/Site",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/powerpc-darwin9.0",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0",
      "."]

There are a few far-too-common mistakes people make with load paths.

Respect the global load path

When you package up your new rubygem to share with the world, you need to be careful with the files you place directly in lib/. Rubygems (and almost all other ruby package mangers) will add your gem’s lib/ to the load path. This means any file placed in the top level of lib/ will be directly requirable by anyone using the gem.

Bad gem example:
  `-- lib
      |-- foo
      |   `-- cgi.rb
      |-- foo.rb
      |-- erb.rb
      `-- set.rb

It may seem harmless to call files whatever you’d like in your package because you are “namespaced” in your own package. But if lib/ is prepended to $LOAD_PATH it will clobber Ruby’s built in erb and set libs. require 'erb' would no longer require Ruby’s builtin erb library, but this package’s version of it.

The safe (and correct) way would be to namespace your files under another directory. Its conventional to create a folder within lib with the same name as your gem. Then we would put all our dependency files under lib/foo/ instead of at lib/ root.

This is sort of a gray area. There is no strict rule that you must put all your files under a folder with your package name. It is okay to have multiple files at your root lib directory as long as you intend for people to require them separately. Namespace internal dependency files that you don’t expect for people to require directly.

Requiring other files relative to each other
  require File.join(File.dirname(__FILE__), "foo", "bar")
  # or
  require File.expand_path(File.join(File.dirname(__FILE__), "foo", "bar"))

If you’re using File.dirname(__FILE__) with require, you’re doing something wrong.

The fix is simple, require files relative to the load path.

  require "foo/bar" 

Its interesting that the 3 previous require examples are totally different. Ruby is only able to track which files it has required by the exact path you gave it. The first is relative your current directory (”./lib/foo/bar”), the second is the full expanded system path (”/usr/local/lib/ruby/gems/foo/lib/foo/bar”), and the third is relative to the load path (”foo/bar”). require treats each as a different file, so it may end up loading the file multiple times.

Depending on files outside the load path

This is a more severe case of the previous example.

  module Rack
    module Test
      VERSION = ::File.read(::File.join(::File.dirname(__FILE__), "..", "..", "VERSION")).strip
      # ...
    end
  end

Your gem’s folders may be separated and reorganized on install. If someone wants to “vendor” your library, they should only have to copy everything under lib/. Everything outside lib/ is not important for running the code. Never expect your lib or test folders to be one level up. A minimalist installer, such as rip, will only install your bin and lib directories. Any file your package needs to access should be under lib and properly namespaced in a folder to avoid collisions. If you try install this version of rack-test with rip, require 'rack/test' will fail because ../VERSION doesn’t exist.

Libs don’t need to mange $LOAD_PATH

Its not the package’s responsibility to setup and manage the load path. Instead rely on the package manger to set it up for. When rubygems activates a gem, it adds your package’s lib folder to the $LOAD_PATH ready to be required normally by another lib or application. Its safe to assume you can relative require any file in your lib folder.

  unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
    $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
  end

It should be safe to remove code like that.

TIP: Setup your test runner to configure your paths for local development

If your trying to develop your lib locally, dealing with all this load path stuff seems like a pain in the ass. This is where rake tests come in handy.

Rake’s test task will automatically push lib into your path when your test unit tests. So you don’t need File.join(File.dirname(FILE), ”..”, “lib”, “foo”) anywhere in your tests. You may want to consider adding the test directory to your path if you have “test_helper” that you need to require.

  Rake::TestTask.new do |t|
    t.libs << 'test'
  end

Unfortunately Rspec doesn’t even add lib to your path for you. You can fix this with:

  Spec::Rake::SpecTask.new do |t|
    t.libs << 'lib'
  end

If you want to run a single test, you can add lib to the $LOAD_PATH with a command line flag. (This started a long debate when the change was made to Rails)

  ruby -Ilib test/test_foo.rb
Provide a VERSION constant

If you release the Awesome gem, provide Awesome::VERSION. When using Rubygems, it’s possible to ask Rubygems for the version of the gem you’re using, but when using an alternate package manager, the only way to find out what version is loaded is by introspection into the Ruby code itself.

Don’t depend on rubygems

When I use your library, deploy your app, or run your tests I may not want to use rubygems. When you “require ‘rubygems’” in your code, you remove my ability to make that decision. I cannot unrequire rubygems, but you can not require it in the first place. – Ryan Tomayko

Its safe to remove require "rubygems" from your lib since code loading it probably did this already. It makes it harder (but not impossible) for people to use alternative ways of setting up the load path because there is no way to “unrequire” rubygems. There are many other package management solutions out there, like rip, bundler, or managing $LOAD_PATH by hand.

Avoid declaring rubygem dependencies in lib/. This means removing gem "foo". This creates a hard dependency on Rubygems when you should be specifying you gem dependencies in your gemspec. Rubygems already hooks into require and will automatically resolve these dependencies at runtime. A simple require will trigger the lookup via rubygems, or will just require it if it’s been added to the load path by another system. Moving dependency specification outside the lib is more flexible for other package managers can do so at install time.

In addition to removing gem, do not wrap your load checks with rescue Gem::LoadError or rescue Gem::Exception. If you need to gracefully skip over load errors, Gem::LoadError inherits from LoadError so replacing it with rescue LoadError will work.

  # Bad
  begin
    gem "rack" 
    require "rack" 
  rescue Gem::LoadError
    puts "Could not load 'rack'" 
    exit
  end

  # Good
  begin
    require "rack" 
  rescue LoadError
    puts "Could not load 'rack'" 
    exit
  end

Why should I care?

I wasn’t aware of any of these issues until Ryan wrote up his post on why requiring rubygems is wrong at the beginning of 2009. And I feel many other rubyists have just overlooked these issues since rubygems has been our only solution. The foundation of Ruby library management is built on the load path system and its important for every ruby gem author to understand how it works.

We’re working on it

Fixing every ruby library is easier said than done (There are 12,000+ hosted on RubyForge at the time of posting). Rails is currently in violation of a few of these rules. But we’re working hard to fix them. We also need to fix all the gems that we depend on. Ideally, we’d like Rails 3 to boot w/o rubygems and allow you use to whatever package management strategy you’d like.

Further reading

Rubygems Good Practice « Katz Got Your Tongue?
Why require ‘rubygems’ In Your Library/App/Tests Is Wrong

Three reasons to love ActionController::Responder

A couple weeks ago, I wrote about the newly added ActionController::Responder which summarizes your application behavior for a specified format in just one place. For example, the default html behavior is written as:


class ActionController::Responder
  def to_html
    if get?
      render
    elsif has_errors?
      render :action => (post? ? :new : :edit)
    else
      redirect_to resource
    end
  end
end

Here are three examples of the flexibility this new layer can provide.

1) HTTP Cache

A simple, but quite powerful use for responder is apply HTTP cache to all your resources easily. For simplicity, let’s cache just get requests that are not handling a collection:


module CachedResponder
  def to_html
    if get? && resource.respond_to?(:updated_at)
      return if controller.fresh_when(:last_modified => resource.updated_at.utc)
    end
    super
  end
end

2) I18n flash messages

Is a common practice that all controllers, when the create, update and destroy actions are handled with success, a flash message is shown to the user. We could easily remove the flash messages from our controllers and let them be handled by the responder with the help of the I18n framework. And it’s quite straightforward to accomplish:


module FlashResponder
  # If it's not a get request and the object has no errors, set the flash message
  # according to the current action. If the controller is users/pictures, the
  # flash message lookup for create is:
  #
  #   flash.users.pictures.create
  #   flash.actions.create
  #
  def to_html
    unless get? || has_errors?
      namespace = controller.controller_path.split('/')
      namespace << controller.action_name
      flash[:success] = I18n.t(namespace.join("."), :scope => :flash,
       :default => "actions.#{controller.action_name}", :resource => resource.class.human_name)
    end
    super
  end
end

The first question then arises: what if I don’t want to add a flash message in an specific situation? This can be solved using options, since all options sent to respond_with are sent to the responder, we could use it in our favor as well:


class MyResponder < ActionController::Responder
  def to_html
    unless get? || has_errors? || options.delete(:flash) == false
      namespace = controller.controller_path.split('/')
      namespace << controller.action_name
      flash[:success] = I18n.t(namespace.join("."), :scope => :flash,
       :default => "actions.#{controller.action_name}", :resource => resource.class.human_name)
    end
    super
  end
end

And we can invoke it as:


class PostsController < ApplicationController
  def create
    @post = Post.create(params[:post])
    respond_with(@post, :flash => false)
  end
end

3) Instant pagination

Some people already start a project with pagination from scratch, others add at some point. Nonetheless, pagination is more like a rule than a exception. Can that be handled by Rails 3? First, let’s check an index action with respond_with:


class PostsController < ApplicationController
  def index
    @posts = Post.all
    respond_with(@posts)
  end
end

Right now, when we call Post.all, it returns a collection of posts in an array, so the pagination should be done before the collection is retrieved. Thanks to Emilio and his work integrating ActiveRelation with ActiveRecord, Post.all will return an ActiveRecord::Relation that will be sent to the responder:


module PaginatedResponder
  # Receives a relation and sets the pagination scope in the collection
  # instance variable. For example, in PostsController it would
  # set the @posts variable with Post.all.paginate(params[:page]).
  def to_html
    if get? && resource.is_a?(ActiveRecord::Relation)
      paginated = resource.paginate(controller.params[:page])
      controller.instance_variable_set("@#{controller.controller_name}", paginated)
    end
    super
  end
end

However, the code above is definitely smelling. Set the paginated scope seems more to be a controller responsability. So we can rewrite as:


module PaginatedResponder
  def to_html
    if get? && resource.is_a?(ActiveRecord::Relation)
      controller.paginated_scope(resource)
    end
    super
  end
end

class ApplicationController < ActionController::Base
  def paginated_scope(relation)
    instance_variable_set "@#{controller_name}", relation.paginate(params[:page])
  end
  hide_action :paginated_scope
end

As previously, you could make use of some options to customize the default pagination behavior.

Wrapping up

All the examples above were contained in modules, that means that our actual responder has yet to be created:


class MyResponder < ActionController::Responder
  include CachedResponder
  include FlashResponder
  include PaginatedResponder
end

To activate it, we just need to overwrite the responder method in our application controller:


class ApplicationController < ActionController::Base
  def paginated_scope(relation)
    instance_variable_set "@#{controller_name}", relation.paginate(params[:page])
  end
  hide_action :paginated_scope

  protected
  def responder
    MyResponder
  end
end

While those examples are simple, they show how you can dry up your code easily using Responder. And you? Already thought in an interesting use case for it?