Plugin Authors: Toward a Better Future

Some of the biggest changes in Rails 3 involve how Rails expects plugins to behave.

Dependencies

If your plugin has dependencies, make it a gem and have your users install it using the Gemfile. This will ensure that Bundler properly calculates the dependencies alongside any other dependencies the user’s app has.

If You Override Something, Require It

If you need to override ActionController, ActiveRecord or other Rails frameworks, require them first, then override. Instead of assuming that Rails will require your gem plugin at a “correct” time, assume that the user will require your plugin extremely early.

This gives you the opportunity to hook in earlier to the initialization process, but it also means that you should explicitly require the dependencies you need.

# in your_lib.rb

require "active_record"
require "your_lib/extensions"

ActiveRecord::Base.class_eval { include YourLib::Extensions }

Use a Railtie, But Only if You Need To

Even though you can expect your gem to load very early, you might still need to hook into a later part of the initialization process. If you do, inherit from Rails::Railties. Inside of a Railtie, you can declare a block that Rails should run when it runs Rakefiles, specify initialization blocks, add a subscriber to the notification system, and specify generators to load.

class TestingFu < Rails::Railtie
  # This creates a config.my_plugin in the user's Application
  railtie_name :testing_fu

  rake_task do
    load "testing_fu/tasks.rake"
  end

  # specify the default generators for test frameworks
  config.generators.test_framework :testing_fu

  # you can also specify :before or :after to ensure that
  # your initializer block runs before or after another
  # initializer block
  initializer :setup_my_plugin do |app|
    # in here, I have access to the user's application,
    # which gives me access to app.config
  end
end

Make sure to require any railties that you intend to extend. For instance, if you want to run an initializer before one defined in ActionController, require “action_controller/railtie”

That said, don’t use a Railtie if your code does not need to hook into any part of the Rails lifecycle. When possible, simply create a standard Ruby library, requiring the parts of Rails you need to override.

Engines

Engines in plugins (vendor/plugins) work as they did in Rails 2. In a gem, you’ll need to provide a Rails::Engine subclass:

# lib/my_engine.rb
module MyEngine
  class Engine < ::Rails::Engine
    engine_name :my_engine
  end
end

Place your app directory next to the lib directory and Rails will pick it up. You can read the documentation for Railte, Engine, Plugin and Application, all in just one place, here: https://gist.github.com/af7e572c2dc973add221

Start a Conversation at railsplugins.org

In order to make this process easier, Engine Yard has put together railsplugins.org. If you’re a plugin author, please submit your plugins to that site. You can tell users whether or not you expect your plugins to work on Rails 3, whether or not your users can run them in threadsafe mode, and whether they run on JRuby.

Once you’ve put a plugin up there, users can say that they either agree that your plugin runs or disagree, with a comment about what is broken. You can reply to any such comments, and the user can change his mind if he just made a mistake. When you submit a new version, the site creates a whole new page, so comments about things not working on a previous version don’t clutter up the current version (users can still get at the old versions if they wish).

If we do this right, the Rails community will have a strong sense of what works on Rails 3 and what doesn’t. Have at it!

Rails 3.0: Beta release

You thought we were never going to get to this day, didn’t you? Ye of little faith. Because here is the first real, public release of Rails 3.0 in the form of a beta package that we’ve toiled long and hard over.

It’s surely not perfect yet, but we were out of blockers on the list, so here we go. Please give it a run around the block, try to update some old applications, try to start some new ones, and report back all the issues you find.

I’m really proud of this moment, actually. We’ve had more than 250 people help with the release and we’ve been through almost 4,000 commits since 2.3 to get here. Yet still the new version feels lighter, more agile, and easier to understand. It’s a great day to be a Rails developer.

There’s plenty to get excited about here. A few of the headliner features are:

  • Brand new router with an emphasis on RESTful declarations
  • New Action Mailer API modelled after Action Controller (now without the agonizing pain of sending multipart messages!)
  • New Active Record chainable query language built on top of relational algebra
  • Unobtrusive JavaScript helpers with drivers for Prototype, jQuery, and more coming (end of inline JS)
  • Explicit dependency management with Bundler

But please take a look at the full release notes and enjoy the latest!

To install:

gem install tzinfo builder memcache-client rack rack-test rack-mount erubis mail text-format thor bundler i18n
gem install rails --pre

Notes: The first line is required because RubyGems currently can’t mix prerelease and regular release gems (someone please fix that!).

Rails 3 Bugmash

RailsBridge has organized a Rails 3 Bugmash on January 16th and 17th. The idea is to try and upgrade your apps and favourite plugins/gems to work with Rails 3 and make the upgrade path as smooth as possible for everyone else by documenting the process and fixing the bugs you encounter. Rails core team and others will be around in #railsbridge to help out the participants during the bugmash. Check the RailsBridge announcement for more details.

Getting a New App Running on Edge

(cross-posted from Yehuda’s Blog)

So people have been attempting to get a Rails app up and running recently. I also have some apps in development on Rails 3, so I’ve been experiencing some of the same problems many others have.

The other night, I worked with sferik to start porting merb-admin over to Rails. Because this process involved being on edge Rails, we got the process honed to a very simple, small, repeatable process.

The Steps

Step 1: Install bundler (version 0.8.1 required)

$ sudo gem install bundler

Step 2: Check out Rails

$ git clone git://github.com/rails/rails.git
$ cd rails

Step 3: Bundle Rails dependencies

$ gem bundle --only default

Step 4: Generate a new app

$ ruby railties/bin/rails ../new_app --dev
$ cd ../new_app

Done

Everything should now work: script/server, script/console, etc.

When you execute rails APP_NAME --dev, it will create a new Rails application with a Gemfile pointing to your Rails checkout and bundle it right after.

Also notice that in Step 3 we pass --only default to the bundle command. This will skip bundling of both mysql and pg (for postgresql) gems.

Enjoy!

Updated on 01/15/2010 – Rewrote steps to include gem install bundler and use rails APP_NAME --dev.

Ruby on Rails 2.3.5 Released

Rails 2.3.5 was released over the weekend which provides several bug-fixes and one security fix. It should be fully compatible with all prior 2.3.x releases and can be easily upgraded to with “gem update rails”. The most interesting bits can be summarized in three points.

Improved compatibility with Ruby 1.9

There were a few small bugs preventing full compatibility with Ruby 1.9. However, we wouldn’t be surprised you were already running Rails 2.3.X successfully before these bugs were fixed (they were small).

RailsXss plugin availability

As you may have heard, in Rails 3 we are now automatically escaping all string content in erb (where as before you needed to use “h()” to escape). If you want to have this functionality today you can install Koz’s RailsXss plugin in Rails 2.3.5.

Fixes for the Nokogiri backend for XmlMini

With Rails 2.3 we were given the ability to switch out the default XML parser from REXML to other faster parsers like Nokogiri. There were a few issues with using Nokogiri which are now resolved, so if your application is parsing lots of xml you may want to switch to this faster XML parser.

And that’s the gist of it

Feel free to browse through the commit history if you’d like to see what else has been fixed (but it’s mostly small stuff).

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