Rails Writ Large

Ruby on Rails 1.1 and the paradox of how constraints can lead to greater freedom.
Easy Web Services

The third big category of changes in Rails 1.1 involves creating Web services—specifically, embracing certain aspects of the HTTP protocol so that REST-style APIs can be implemented very easily.

The first piece of the equation is a new method for your actions, respond_to. This method parses the HTTP Accept header sent from the client, so that one action can return multiple response formats. For example:


class MessagesController < ActionController::Base
  def list
    @messages = Message.find :all
      respond_to do |type|
                              type.html # using defaults, which will render messages/list.rhtml
                              type.xml  { render :xml => @messages.to_xml } # generates XML and sends it with the right MIME type
                              type.js   # renders index.rjs
    end
  end
end

In this example, a typical browser requesting /messages/list will get the HTML version of the data back, as usual. But an Ajax request for the same URL might send an Accept header of application/javascript—triggering the RJS template to be used instead. Yet another client might want to interact with your application as a Web service API, so it requests application/xml, and the same action handles that format as well. If you've wondered how hard it would be to add an API to your Web application, it's never been easier.

The above example includes a new option for the render method, :xml. It works just like render(:text => text), but sets the content-type to application/xml and the charset to UTF-8. You can specify the content-type header manually with the :content_type option. For example:

render :action => "atom.rxml", :content_type => "application/atom+xml"

Arrays, hashes and ActiveRecord now have a to_xml method, and every object has to_json. These powerful additions mean that providing machine-readable versions of your application data can be accomplished with a few keystrokes. For example:


message.to_xml
message.to_xml(:skip_instruct => true, :skip_attributes => [ :id, bonus_time, :written_on, replies_count ])
firm.to_xml :include => [ :account, :clients ]

[1,2,3].to_json => "[1, 2, 3]"
"Hello".to_json => "\"Hello\""
Person.find(:first).to_json => "{\"attributes\": {\"id\": \"1\", \"name\": \"Scott Raymond\"}}"

The above examples demonstrate how easily you can enable a read-only API, but what if you want to accept input from the API as well? Well, it's remarkably simple:


class MessagesController < ActionController::Base
  def create
    @message = Message.create params[:message]
    redirect_to :action => :show, :id => @message.id
  end
end

But wait—isn't that the same code as the non-API version of the action? Indeed, Rails now examines the HTTP content-type header of the incoming POST and parses the input accordingly into the params object—just as if the data came from a Web form. By default, requests submitted with the application/xml content type are handled by creating an XmlSimple hash with the same name as the root element of the submitted XML. XML data is handled automatically, but what if you want to handle other formats as well? Enter pluggable parameter parsers:

ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data|
  node = REXML::Document.new data
  { node.root.name => node.root }
end

There's (a Lot) More Where That Came From

Clearly we've barely scratched the surface of the new features in Rails 1.1—to say nothing of Rails as a whole. But you should now have a taste of Rails' latest additions. For more in-depth information and community (including books, screencasts, documentation, tutorials, demo applications, Weblogs, mailing lists and IRC channels), head to rubyonrails.com.

Scott Raymond is a contributor to the Rails project and a professional Rails developer and consultant. He has been creating Web applications for ten years—in every role from Intern to IT Director, for clients ranging from indie-rock bands to Fortune 100 multinationals. He writes at scottraymond.net, is speaking at RailsConf in June 2006 and will release a book with O'Reilly later this year. Scott holds a BA in Linguistics from the University of Kansas.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

toggle's code doesn't work for me

Bart's picture

point 8) code doesn't work for me. Browser (FF/IE) complains with RJS error (RerefenceError:'blind_down' is not defined). Here are my *.rjs files

caused problem:
page.visual_effect :toggle_blind, 'element', :effect => 'blind_down'

works fine:
page.visual_effect :toggle_blind, 'element'

Bart

Minor bug in RJS sample

Bill Mitchell's picture

www.iconbuffet.com/products/amsterdam

Click "add to cart", then click "remove from cart". Now try to click "add to cart." You can't because the buttons still say "remove." Buttons fail to refresh after removing from cart. Must reload page to see the add to cart button again.

This page displays too wide, requires horizontal scrolling for e

Randy Kramer's picture

This page displays too wide, requires horizontal scrolling for each line. I haven't tried to pinpoint the cause of the trouble.

You should limit lines to something around 80 characters, and/or make them (lines) wrap to the width of the page.

This page displays too wide

Keith Daniels's picture

I can't replicate this problem. I tested at 800x600 resolution and though the gray code blocks had horizontal scroll bars none of the body text was outside of the screen.

What browser are you using, what screen resolution and what operating system. It would also help if you would check that you have not changed any of you browser settings so that they override the style sheets on the web site.

Webmaster
Linux Journal

All the new OSs and windowing systems are oriented towards content consumption instead of content production.

--Steve Daniels 2013

print version runs off the line

bumparocky's picture

too wide for printing also....
print preview in the latest firefox, of the printer friently version, shows the lines getting chopped off

rocky

print version runs off the line

Keith Daniels's picture

Re: too wide for printing also....

Does the "also" imply that the horizontal scroll bars appear as well -- during regular viewing?

I too have the latest version of FireFox and the priter friendly version looks fine in FireFox's print preview.

The print preview of the regular web page does look funny but I think that is a FireFox problem dealing with complex multi column pages instead of a site problem.

Are you using the Windows version of FireFox? If not which Linux version are you using and what is the FireFox version?

All the new OSs and windowing systems are oriented towards content consumption instead of content production.

--Steve Daniels 2013

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix