Radiant released: Content Management Simplified

John Long has announced the initial release of Radiant, the simple and elegant CMS that is planned to eventually power the redesigned reincarnation of the official Ruby website, ruby-lang.org.

You can take a look at some screenshots, check out the demo, read the source, subscribe to the mailing list, and follow along on the weblog.

Underneath the sheets, John is using his custom templating library Radius, on top of which he’s implemented his so called Behaviors. To help you dig into such features, John has provided some starting points for learning Radiant as well as a quickstart for Radius. If you want to jump aboard and help the development, he’s providing some tips on how you can contribute.

svn co http://dev.radiantcms.org/svn/radiant/trunk/radiant/

Things called a CMS are notoriously complex. Cheers for keeping it simple.

Agile Web Development with Rails goes second edition

It’s back. Agile Web Development with Rails is now available in a 50%-done beta version of its second edition. Pretty much everything is getting a major overhaul. All the cool stuff we’ve added in Rails 1.1 is covered in the same structure that people so liked from the first version.

It’s wonderful to be able to present a version two of the primary title that has helped so many people get into Rails. And through the wonders of PDFs and agile publishing, to have it available so soon.

So if you’re interested in getting the latest scoop on everything from RJS, to join models, to migrations, to RESTful interfaces, to Capistrano, this is most definitely the book to get.

P.S.: Just so you don’t feel buyers remorse two days after getting a PDF of the first edition, anyone that bought that PDF on or after April 1st gets a free upgrade to the second edition.

Both Dave Thomas and I covered the announcement in additional detail.

Associations aren't :dependent => true anymore

Up until the 1.1 release, the way to automatically destroy has_many associations when the owner was itself destroyed was to either use the :dependent or :exclusively_dependent option when declaring the has_many.

class Account < ActiveRecord::Base
  has_many :members, :dependent => true


class Brand < ActiveRecord::Base
  has_many :products, :exclusively_dependent => true

The :dependent option instantiated all the associated objects and called destroy on each one. Destroy in turn triggers the callbacks defined on that associated model, such as those declared with before_destroy and after_destroy.

The :exclusively_dependent option, on the other hand, did not instantiate all the associated objects. Rather, it just generated a single SQL statement which deleted the associated records without first creating objects for each one. This buys you efficiency when you have no need for the flexibility of triggering model callbacks.

Since 1.1, the API for garbage collecting associated records has been consolidated into the :dependent option. Rather than saying :dependent => true, you now pass one of several symbols to the :dependent option which describes how the association is dependent on the owner.

Declaring the has many as :dependent => :destroy is the same as what used to be declared as :dependent => true. When the owner is destroyed, all the associated records are instantiated and destroyed.

class Account < ActiveRecord::Base
  # Deprecated
  # has_many :members, :dependent => true
  # In favor of
  has_many :members, :dependent => :destroy

The new way to achieve the now deprecated :exclusively_dependent configuration is to use :dependent => :delete_all rather than :dependent => :destroy.

class Brand < ActiveRecord::Base
  # Deprecated
  # has_many :products, :exclusively_dependent => true

  # In favor of
  has_many :products, :dependent => :delete_all

The :destroy and :delete_all option symbols are so named because they correspond with the behavior achieved by calling destroy versus delete on a model object. One triggers callbacks, the other just generates the delete SQL statement.

As an aside, another valid option is :dependent => :nullify which is similar to :dependent => :delete_all except rather than deleting the associated records, it just sets their foreign keys to NULL. This effectively removes the association, without removing the associated records from the database table.

As always, the semantics of :dependent => :destroy and :dependent => :delete_all are mutually exclusive, which this new API makes a bit more apparent.

It should be noted that declaring dependencies is not required when setting up has many associations. It is simply an option for when you desire such functionality.

Keep in mind that for now :dependent => true and :exclusively_dependent => true will still be supported, but they have been marked as deprecated and could be taken out in the future.

New in Rails: Module#alias_method_chain

Though not an outward facing feature, changeset 4276 introduces a nice method to DRY up and encapsulate the common pattern of aliasing a method so that you can build behavior on top of it.

All over the internals of Rails you’ll find code like this in a module:

  module Layout #:nodoc:
    def self.included(base)
      base.class_eval do
        alias_method :render_with_no_layout, :render
        alias_method :render, :render_with_a_layout

  1. … etc

This makes it so that when the module is included into the base class, it adds behavior onto some method in that class without the method having to be aware of the fact that it’s being enhanced. In this case, the render method of ActionController::Base is enhanced to wrap its output in a layout.

The new Module#alias_method_chain wraps up this pattern into a single method call. The above example, once refactored to use Module#alias_method_chain, would simply be:

alias_method_chain :render, :layout

This will be used to refactor quite a bit of Rails internals which may not be of immediate relevance to what you do, but it serves as a nice example of the mechanisms Ruby provides for software organization. Small victories.

Finding programmers and designers for Rails projects

The Signal vs Noise Job Board is a new alternative for finding good programmers and designers to work on Rails projects (among other things). It puts your job pitch in front of the tens of thousands of people reading the Signal vs Noise weblog. It comes at a price of $250 for a posting of 500 words visible for 30 days.

CNET, Fleck, and NYTimes.com are all using it to advertise developers with Ruby and Rails experience. If you’re just looking for programming positions, you can subscribe to the RSS for the programming section.

As you might have noticed from the URLs, this job site is using the new Simply Restful plugin. Our playground for RESTful living on Rails.

Use params, not @params

I still frequently see people in the #rubyonrails channel using @params in their code. For a while now @params has been deprecated in favor of simply params. For those who just skim these blog posts:

Use params, not @params

Why? When you use the params method, it allows for the implementation details of the parameter hash to be changed without breaking existing code. If the implementation of params changed you wouldn’t have to change your code at all because the single point of access for the parameters would just remain the params method. So, the details of what is happening behind the scenes don’t matter. If, though, you use the @params instance variable directly, you’ve broken encapsulation and consequently the ability for the implementation to be easily modified. Methods can be refactored, but instance variables can’t. Today the params method just wraps the @params instance variable, so still using @params works, but that’s not guaranteed to always remain the case.

Same goes for request, response, session, headers, template, cookies and flash.

Basically, a good rule of thumb here is don’t use an instance variable in your controller or view unless you created that instance variable.

Even the old @content_for_layout in the layout is deprecated in favor of just using yield in its place. Also content_for('some_fragment') is now accessed with yield :some_fragment rather than @content_for_some_fragment.

EastMedia jumps into the Rails training arena

Matt Pelletier’s EastMedia, a Rails-centric firm out of New York City, has announced that they are offering two Rails classes in the near future.

The first is a one day course in New York City on April 29th taught by Matt Pelletier and Francis Hwang, the founder of the NYC Ruby user group, humanist and author of, among other things, Lafcadio and MockFS. Francis has been building websites in Ruby for over 4 years now. Up until recently he was the primary developer for http://rhizome.org/. You can sign up here for $395.

For those on the other side of the pond, they are also offering a three day course in London , May 5 – 7 taught also by Matt as well as Dr. David Black of Ruby for Rails fame. That one is £1200 GBP and you can sign up here.

UPDATE: Jeremy Voorhis of PLANET ARGON and Globalize fame will also be one of the instructors at the London gig.

habtm vs has_many :through

Of late the ActiveRecord association code has been getting a lot of love. One of the high profile additions are polymorphic associations which turned into one of the big features of the 1.1 release. Amongst all the commotion, some may not have noticed that there is an enhanced way to do many to many associations other than with has_and_belongs_to_many.

For some time people have been skipping out on has_and_belongs_to_many in favor of setting up two has_many associations so that they get the benefits of a full join model and what that brings with it. With 1.1’s new :through association option, a two way has_many just got even sweeter. So if there are two ways to do a many to many relationship, what are the differences, and which approach should you take?

Josh Susser has been digging deep into the association code lately and has emerged from the thicket with a point by point comparison of habtm and has_many :through, a dance-off if you will, between the two approaches. This would be a good time to add him to your RSS reader if you haven’t already.