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

"I have always wished that my computer would be as easy to use as my telephone.
My wish has come true. I no longer know how to use my telephone."
-- Bjarne Stroustrup

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?

"I have always wished that my computer would be as easy to use as my telephone.
My wish has come true. I no longer know how to use my telephone."
-- Bjarne Stroustrup

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState