Jacob Swanner Development Blog

What’s new in Rails 3.0 Beta 2

On April 1st, Rails 3.0 Beta 2 was released, I thought I’d take this opportunity to highlight some of the changes between the Beta 1 and Beta 2 releases.  According to GitHub, there are 2,691 new, unique commits – contributed by 244 authors – that were included in the Beta 2 release.  I’ve picked some of the changes that I felt were important from the perspective of someone using Rails to build a web application and those that build plugins and other extensions for Rails.

The changes are separated by each of Rails’ individual components:

ActionMailer

You can now register interceptors and observers that will be called before and after an email is sent, respectively.  The interceptor object must implement the delivering_email method, while the observer object must implement delivered_email. Here’s a simple example:

class MyInterceptor
  def self.delivering_email(mail)
    # do something before sending the email
  end
end

class MyObserver
  def self.delivered_email(mail)
    # do something after sending the email
  end
end

ActionMailer::Base.register_interceptor(MyInterceptor)
ActionMailer::Base.register_observer(MyObserver)

ActionPack

Block helpers now return Strings, so you can use <%= form_for @foo do |f| %>. <% form_for @foo do |f| %> still works but will give you a deprecation notice.

The way that send_file works has changed, it now defers to a Rack middleware called Rack::Sendfile. With that, the following options have been removed from send_file: :stream, :buffer_size, and :x_sendfile. The header used to send the file is configurable via config.action_dispatch.x_sendfile_header – which defaults to “X-Sendfile” – , and servers can configure this setting as well by setting the “X-Sendfile-Type” header. Hopefully, hosting companies specializing in Rails deployments will set this header, so that it will work transparently for those deploying there. If you do need to set it manually, for say Lighttpd, here’s an example:

class MyApp < Rails::Application
  config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File'
end

ActiveModel

For those creating libraries that they want to conform with ActiveModel, there has been some changes to ActiveModel::Lint – a module of tests that you can include in your tests to ensure your library conforms to ActiveModel. #new_record? and #destroyed? were removed, use #persisted? instead. For those of you that are curious, ActiveRecord’s implementation of persisted? is as follows: A model is persisted if it’s not a new_record? and it was not destroyed?.

In addition, #to_key was added to ActiveModel::Lint, this is used to generate DOM IDs for ActiveModel objects.

ActiveRecord

You can now prefix the table names all of the models in a module, you just need to define self.table_name_prefix on the module:

module Prefixed
  def self.table_name_prefix
    'prefixed_'
  end

  class ModelName < ActiveRecord::Base
  end
end

ActiveSupport

There are new assertions you can use in your tests: assert_blank and assert_present. Here they are used in a simple example:

assert_blank [] # => true
assert_present {:data => 'x' } # => true

yajl-ruby was added as a JSON parsing backend; and is the preferred backend, if available. There was an interesting discussion about using ActiveSupport::JSON.encode over #to_json on the patch’s Lighthouse ticket.

Session store configuration has changed. The cookie_verifier_secret has been deprecated and it is now assigned through Rails.application.config.cookie_secret instead and moved into it’s own file: initializers/cookie_verification_secret.rb. Also, session_store configuration has also been changed from ActionController::Base.session to Rails.application.config.session_store and has been moved to initializers/session_store.rb.

If you were building a plugin that inherited from Rails::Railtie, you were probably setting railtie_name and/or engine_name, well both of them have been deprecated. You can now add any object to the configuration object: config.your_plugin = {}. To see how the Rails internals switched to this new configuration approach, view the commit.