<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Ryan's Scraps - Blog</title>
  <id>tag:ryandaigle.com,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  
  <link href="http://ryandaigle.com/" rel="alternate" type="text/html" />
  <updated>2009-08-11T02:15:37Z</updated>
  <geo:lat>37.544746</geo:lat><geo:long>-77.400851</geo:long><link rel="self" href="http://feeds.feedburner.com/RyansScraps" type="application/atom+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-08-11:9095</id>
    <published>2009-08-11T02:13:00Z</published>
    <updated>2009-08-11T02:15:37Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/32yB6CGjWKU/what-s-new-in-edge-rails-independent-model-validators" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Independent Model Validators</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is schedule for: Rails v3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;ActiveRecord validations, ground zero for anybody learning about Rails, got a lil’ bit of decoupling mojo today with the &lt;a href="http://github.com/rails/rails/commit/22f339825329e2d4463a4130e9fa68baf9d27eb6"&gt;introduction of validator classes&lt;/a&gt;.  Until today, the only options you had to define a custom validation was by overriding the &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations.html#M002158"&gt;validate&lt;/a&gt; method or by using &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002161"&gt;validates_each&lt;/a&gt;, both of which pollute your models with gobs of validation logic.&lt;/p&gt;


	&lt;h1&gt;ActiveRecord Validators&lt;/h1&gt;


	&lt;p&gt;Validators remedy this by containing granular levels of validation logic that can be reused across your models.  For instance, for that classic email validation example we can create a single validator:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;EmailValidator&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Validator&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;validate&lt;/span&gt;()&lt;tt&gt;
&lt;/tt&gt;    record.errors[&lt;span class="sy"&gt;:email&lt;/span&gt;] &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;is not valid&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      record.email =~ &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;^([^@&lt;/span&gt;&lt;span class="ch"&gt;\s&lt;/span&gt;&lt;span class="k"&gt;]+)@((?:[-a-z0-9]+&lt;/span&gt;&lt;span class="ch"&gt;\.&lt;/span&gt;&lt;span class="k"&gt;)+[a-z]{2,})$&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Each validator should implement a &lt;code&gt;validate&lt;/code&gt; method, within which it has access to the model instance in question as &lt;code&gt;record&lt;/code&gt;.  Validation errors can then be added to the base model by adding to the &lt;code&gt;errors&lt;/code&gt; collection as in this example.&lt;/p&gt;


	&lt;p&gt;So how do you tell a validator to operate on a model?  &lt;code&gt;validates_with&lt;/code&gt; that takes the class of the validator:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_with &lt;span class="co"&gt;EmailValidator&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h1&gt;Validation Arguments&lt;/h1&gt;


	&lt;p&gt;This is all well and good, but is a pretty brittle solution in this example as the validator is assuming an &lt;code&gt;email&lt;/code&gt; field.  We need a way to pass in the name of the field to validate against for a model class that is unknown until runtime.  We can do this by passing in options to &lt;code&gt;validates_with&lt;/code&gt; which are then made available to the validator at runtime as the &lt;code&gt;options&lt;/code&gt; hash.  So let’s update our email validator to operate on an email field that can be set by the model requiring validation:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;EmailValidator&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Validator&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;validate&lt;/span&gt;()&lt;tt&gt;
&lt;/tt&gt;    email_field = options[&lt;span class="sy"&gt;:attr&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    record.errors[email_field] &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;is not valid&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      record.send(email_field) =~ &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;^([^@&lt;/span&gt;&lt;span class="ch"&gt;\s&lt;/span&gt;&lt;span class="k"&gt;]+)@((?:[-a-z0-9]+&lt;/span&gt;&lt;span class="ch"&gt;\.&lt;/span&gt;&lt;span class="k"&gt;)+[a-z]{2,})$&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And to wire it up from the user model:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_with &lt;span class="co"&gt;EmailValidator&lt;/span&gt;, &lt;span class="sy"&gt;:attr&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:email_address&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Any arguments can be passed into your validators by hitching a ride onto this options hash of &lt;code&gt;validates_with&lt;/code&gt;.&lt;/p&gt;


	&lt;h1&gt;Options &amp; Notes&lt;/h1&gt;


	&lt;p&gt;There are also some built-in options that you’ll be very familiar with, namely &lt;code&gt;:on&lt;/code&gt;, &lt;code&gt;:if&lt;/code&gt; and &lt;code&gt;:unless&lt;/code&gt; that define when the validation will occur.  They’re all the same as the options to built-in validations like &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002164"&gt;&lt;code&gt;validates_presence_of&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_with &lt;span class="co"&gt;EmailValidator&lt;/span&gt;, &lt;span class="sy"&gt;:if&lt;/span&gt; =&amp;gt; &lt;span class="co"&gt;Proc&lt;/span&gt;.new  { |u| u.signup_step &amp;gt; &lt;span class="i"&gt;2&lt;/span&gt; },&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="sy"&gt;:attr&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:email_address&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;It’s also possible to specify more than one validator with &lt;code&gt;validates_with&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_with &lt;span class="co"&gt;EmailValidator&lt;/span&gt;, &lt;span class="co"&gt;ZipCodeValidator&lt;/span&gt;, &lt;span class="sy"&gt;:on&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;While this might seem like a pretty minor update, it allows for far better reusability of custom validation logic than what’s available now.  So enjoy.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5yCtiLqC9mtoCfQ3tANz7pau4GY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5yCtiLqC9mtoCfQ3tANz7pau4GY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5yCtiLqC9mtoCfQ3tANz7pau4GY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5yCtiLqC9mtoCfQ3tANz7pau4GY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=32yB6CGjWKU:QhVDKBqai_4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=32yB6CGjWKU:QhVDKBqai_4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=32yB6CGjWKU:QhVDKBqai_4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=32yB6CGjWKU:QhVDKBqai_4:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=32yB6CGjWKU:QhVDKBqai_4:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/32yB6CGjWKU" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/8/11/what-s-new-in-edge-rails-independent-model-validators</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-08-10:9084</id>
    <published>2009-08-10T13:39:00Z</published>
    <updated>2009-08-10T16:36:41Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/iT4r-h2mmqk/what-s-new-in-edge-rails-default-restful-rendering" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Default RESTful Rendering</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is schedule for: Rails v3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;A few days ago I wrote about the new &lt;a href="http://ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with"&gt;&lt;code&gt;respond_with&lt;/code&gt; functionality&lt;/a&gt; of Rails 3.  It’s basically a clean way to specify the resource to send back in response to a RESTful request.  This works wonders for successful &lt;code&gt;:xml&lt;/code&gt; and &lt;code&gt;:json&lt;/code&gt; requests where the default response is to send back the serialized form of the resource, but still presents a lot of cruft when handling user-invoked &lt;code&gt;:html&lt;/code&gt; requests (i.e. ‘navigational’ requests) and requests where error handling is required.  For instance, consider your standard &lt;code&gt;create&lt;/code&gt; action:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# Have to always override the html format to properly&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# handle the redirect&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;      flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User was created successfully.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:created&lt;/span&gt;, &lt;span class="sy"&gt;:location&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;        format.html { redirect_to &lt;span class="iv"&gt;@user&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# Have to send back the errors collection if they exist for xml, json and&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# redirect back to new for html.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;.errors, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:unprocessable_entity&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;        format.html { render &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:new&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Even with the heavy lifting of &lt;code&gt;respond_with&lt;/code&gt; you can see that there’s still a lot of plumbing left for you to do – plumbing that is mostly the same for all RESTful requests.  Well &lt;a href="http://blog.plataformatec.com.br/"&gt;José&lt;/a&gt; and the Rails team have a solution to this and have &lt;a href="http://github.com/rails/rails/commit/aed135d3e261cbee153a35fcfbeb47e2e02b12e4"&gt;introduced controller responders&lt;/a&gt;.&lt;/p&gt;


	&lt;h1&gt;Controller Responders&lt;/h1&gt;


	&lt;p&gt;Controller responders handle the chore of matching the &lt;span class="caps"&gt;HTTP&lt;/span&gt; request method and the resource format type to determine what type of response should be sent.  And since &lt;span class="caps"&gt;REST&lt;/span&gt; is so well-defined it’s very easy to establish a default responder to handle the basics.&lt;/p&gt;


	&lt;p&gt;Here’s what a controller utilizing responder support (now baked into &lt;code&gt;respond_with&lt;/code&gt;) looks like:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.create(params[&lt;span class="sy"&gt;:user&lt;/span&gt;]))&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;edit&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:id&lt;/span&gt;]))&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;update&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt;.update_attributes(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The built-in responder performs the following logic for each action:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;If the &lt;code&gt;:html&lt;/code&gt; format was requested:
	&lt;ul&gt;
	&lt;li&gt;If it was a &lt;code&gt;GET&lt;/code&gt; request, invoke &lt;code&gt;render&lt;/code&gt; (which will display the view template for the current action)&lt;/li&gt;
		&lt;li&gt;If it was a &lt;code&gt;POST&lt;/code&gt; request and the resource has validation errors, &lt;code&gt;render&lt;/code&gt; &lt;code&gt;:new&lt;/code&gt; (so the user can fix their errors)&lt;/li&gt;
		&lt;li&gt;If it was a &lt;code&gt;PUT&lt;/code&gt; request and the resource has validation errors, &lt;code&gt;render&lt;/code&gt; &lt;code&gt;:edit&lt;/code&gt; (so the user can fix their errors)&lt;/li&gt;
		&lt;li&gt;Else, redirect to the resource location (i.e. &lt;code&gt;user_url&lt;/code&gt;)&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
		&lt;li&gt;If another format was requested, (i.e. &lt;code&gt;:xml&lt;/code&gt; or &lt;code&gt;:json&lt;/code&gt;)
	&lt;ul&gt;
	&lt;li&gt;If it was a &lt;code&gt;GET&lt;/code&gt; request, invoke the &lt;code&gt;:to_format&lt;/code&gt; method on the resource and send that back&lt;/li&gt;
		&lt;li&gt;If the resource has validation errors, send back the errors in the requested format with the &lt;code&gt;:unprocessable_entity&lt;/code&gt; status code&lt;/li&gt;
		&lt;li&gt;If it was a &lt;code&gt;POST&lt;/code&gt; request, invoke the &lt;code&gt;:to_format&lt;/code&gt; method on the resource and send that back with the &lt;code&gt;:created&lt;/code&gt; status and the &lt;code&gt;:location&lt;/code&gt; of the new created resource&lt;/li&gt;
		&lt;li&gt;Else, send back the &lt;code&gt;:ok&lt;/code&gt; response with no body&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Wading through this logic tree you can see that the default logic for each RESTful action is appropriately handled, letting your controller actions focus exclusively on resource retrieval and modification.  And with that cruft out of the way your controllers will start to look even more similar – I suspect we’ll be seeing a solution for this coming around the bend shortly as well…?&lt;/p&gt;


	&lt;p&gt;So, just to recap the basics, here are a few action implementations side by side (the first being before responders and the latter being after):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Old&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;    format.html&lt;tt&gt;
&lt;/tt&gt;    format.xml { render &lt;span class="sy"&gt;:xml&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    format.json { render &lt;span class="sy"&gt;:json&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# New&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_with(&lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Old&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;    flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User successfully created&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to &lt;span class="iv"&gt;@user&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.xml { render &lt;span class="sy"&gt;:xml&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt;, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:created&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="sy"&gt;:location&lt;/span&gt; =&amp;gt; user_url(&lt;span class="iv"&gt;@user&lt;/span&gt;) }&lt;tt&gt;
&lt;/tt&gt;      format.json { render &lt;span class="sy"&gt;:json&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt;, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:created&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="sy"&gt;:location&lt;/span&gt; =&amp;gt; user_url(&lt;span class="iv"&gt;@user&lt;/span&gt;) }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { render &lt;span class="sy"&gt;:new&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.xml { render &lt;span class="sy"&gt;:xml&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.errors, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:unprocessable_entity&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.json { render &lt;span class="sy"&gt;:json&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.errors, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:unprocessable_entity&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# New&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;  flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User successfully created&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;  respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Oh yeah, that’s getting real lean.&lt;/p&gt;


	&lt;h1&gt;Overriding Default Behavior&lt;/h1&gt;


	&lt;p&gt;If you need to override the default behavior of a particular format you can do so by passing a block to &lt;code&gt;respond_with&lt;/code&gt; (as I wrote about in the &lt;a href="http://ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with"&gt;original article&lt;/a&gt;):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# Override html format since we want to redirect to the collections page&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# instead of the user page.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User successfully created&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to users_url }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h1&gt;Nested Resources&lt;/h1&gt;


	&lt;p&gt;It’s quite common to operate on resources within a nested resource graph (though I prefer to go one level deep, at most).  For such cases you need to let &lt;code&gt;respond_with&lt;/code&gt; know of the object hierarchy (using the same parameters as &lt;a href="http://api.rubyonrails.org/classes/ActionController/PolymorphicRoutes.html#M000486"&gt;&lt;code&gt;polymorphic_url&lt;/code&gt;&lt;/a&gt;):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# In this case, users exist within a company&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@company&lt;/span&gt; = &lt;span class="co"&gt;Company&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:company_id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="iv"&gt;@company&lt;/span&gt;.users.build(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;User successfully created&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="iv"&gt;@user&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# Ensure that the new user location is nested within @company,&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# for html format (/companies/1/users/2.html) as well as&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# resource formats (/companies/1/users/2)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@company&lt;/span&gt;, &lt;span class="iv"&gt;@user&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you have a singleton resource within your resource graph just use a symbol instead of an actual object instance.  So to get &lt;code&gt;/admin/users/1&lt;/code&gt; you would invoke &lt;code&gt;respond_with(:admin, @user)&lt;/code&gt;.&lt;/p&gt;


	&lt;h1&gt;Custom Responders&lt;/h1&gt;


	&lt;p&gt;While there’s no facility to provide your own responder classes, it will no doubt be added shortly.  If you look at the &lt;a href="http://github.com/rails/rails/blob/600a89f2082beadf4af9fe140a1a2ae56386cd49/actionpack/lib/action_controller/metal/responder.rb#L81"&gt;current responder class definition&lt;/a&gt;, it’s a very simple &lt;span class="caps"&gt;API&lt;/span&gt; essentially only requiring a &lt;code&gt;call&lt;/code&gt; method (more intuitively take a look at the &lt;a href="http://github.com/rails/rails/blob/600a89f2082beadf4af9fe140a1a2ae56386cd49/actionpack/lib/action_controller/metal/responder.rb#L111"&gt;&lt;code&gt;:to_html&lt;/code&gt;&lt;/a&gt; and &lt;a&gt;&lt;code&gt;:to_format&lt;/code&gt;&lt;/a&gt; methods).&lt;/p&gt;


	&lt;p&gt;Stay tuned here for further refinements to this very handy functionality – you’re going to see a lot more tightening in the coming weeks.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-k0njxd8g8Ik5_APtZ_iystjG3M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-k0njxd8g8Ik5_APtZ_iystjG3M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-k0njxd8g8Ik5_APtZ_iystjG3M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-k0njxd8g8Ik5_APtZ_iystjG3M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=iT4r-h2mmqk:w_CbvoV082o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=iT4r-h2mmqk:w_CbvoV082o:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=iT4r-h2mmqk:w_CbvoV082o:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=iT4r-h2mmqk:w_CbvoV082o:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=iT4r-h2mmqk:w_CbvoV082o:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/iT4r-h2mmqk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/8/10/what-s-new-in-edge-rails-default-restful-rendering</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-08-06:9069</id>
    <published>2009-08-06T01:52:00Z</published>
    <updated>2009-08-10T04:15:35Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/5jNi5oU91Jk/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Cleaner RESTful Controllers w/ respond_with</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is schedule for: Rails v3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; is a first-class citizen in the Rails world, though most of the hard work is done at the routing level.  The controller stack has some niceties revolving around mime type handling with the &lt;code&gt;respond_to&lt;/code&gt; facility but, to date, there’s not been a lot built into actionpack to handle the serving of resources.  The &lt;a href="http://github.com/rails/rails/commit/09de34ca56598ae5d0302a14715b2a11b6cc9845"&gt;addition of &lt;code&gt;respond_with&lt;/code&gt;&lt;/a&gt; (and &lt;a href="http://github.com/rails/rails/commit/aed135d3e261cbee153a35fcfbeb47e2e02b12e4"&gt;this follow-up&lt;/a&gt;) takes one step towards more robust RESTful support with an easy way to specify how resources are delivered.  Here’s how it works:&lt;/p&gt;


	&lt;h1&gt;Basic Usage&lt;/h1&gt;


	&lt;p&gt;In your controller you can specify what resource formats are supported with the class method &lt;code&gt;respond_*to*&lt;/code&gt;.  Then, within your individual actions, you tell the controller the resource or resources to be delivered using &lt;code&gt;respond_*with*&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.create(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;, &lt;span class="sy"&gt;:location&lt;/span&gt; =&amp;gt; users_url)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This will match each supported format with an appropriate response.  For instance, if the request is for &lt;code&gt;/users.xml&lt;/code&gt; then the controller will look for a &lt;code&gt;/users/index.xml.erb&lt;/code&gt; view template to render.  If such a view template doesn’t exist then it tries to directly render the resource in the &lt;code&gt;:xml&lt;/code&gt; format by invoking &lt;code&gt;to_xml&lt;/code&gt; (if it exists).  Lastly, if &lt;code&gt;respond_with&lt;/code&gt; was invoked with a &lt;code&gt;:location&lt;/code&gt; option the request will be redirected to that location (as in the case of the &lt;code&gt;create&lt;/code&gt; action in the above example).&lt;/p&gt;


	&lt;p&gt;So here’s the equivalent implementation without the use of &lt;code&gt;respond_with&lt;/code&gt; (assuming no index view templates):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html&lt;tt&gt;
&lt;/tt&gt;      format.xml { render &lt;span class="sy"&gt;:xml&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.json { render &lt;span class="sy"&gt;:json&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.create(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to users_url }&lt;tt&gt;
&lt;/tt&gt;      format.xml { render &lt;span class="sy"&gt;:xml&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;      format.json { render &lt;span class="sy"&gt;:json&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@user&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You can see how much boilerplate response handling is now handled for you especially if it’s multiplied over the other default actions.  You can pass in &lt;code&gt;:status&lt;/code&gt; and &lt;code&gt;:head&lt;/code&gt; options to &lt;code&gt;respond_with&lt;/code&gt; as well if you need to send these headers back on resources rendered directly (i.e. via &lt;code&gt;to_xml&lt;/code&gt;):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all, &lt;span class="sy"&gt;:status&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:ok&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h1&gt;Per-Action Overriding&lt;/h1&gt;


	&lt;p&gt;It’s also possible to override standard resource handling by passing in a block to &lt;code&gt;respond_with&lt;/code&gt; specifying which formats to override for that action:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# Override html format since we want to redirect to a different page,&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# not just serve back the new resource&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.create(params[&lt;span class="sy"&gt;:user&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    respond_with(&lt;span class="iv"&gt;@user&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html { redirect_to users_path }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h1&gt;:except And :only Options&lt;/h1&gt;


	&lt;p&gt;You can also pass in &lt;code&gt;:except&lt;/code&gt; and &lt;code&gt;:only&lt;/code&gt; options to only support formats for specific actions (as you do with &lt;code&gt;before_filter&lt;/code&gt;):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:html&lt;/span&gt;, &lt;span class="sy"&gt;:only&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  respond_to &lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;, &lt;span class="sy"&gt;:except&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:show&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  ...&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h1&gt;The :any Format&lt;/h1&gt;


	&lt;p&gt;If you’re still want to use &lt;code&gt;respond_to&lt;/code&gt; within your individual actions this update has also bundled the &lt;code&gt;:any&lt;/code&gt; resource format that can be used as a wildcard match against any unspecified formats:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;UsersController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@users&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.all&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    respond_to &lt;span class="r"&gt;do&lt;/span&gt; |format|&lt;tt&gt;
&lt;/tt&gt;      format.html&lt;tt&gt;
&lt;/tt&gt;      format.any(&lt;span class="sy"&gt;:xml&lt;/span&gt;, &lt;span class="sy"&gt;:json&lt;/span&gt;) { render request.format.to_sym =&amp;gt; &lt;span class="iv"&gt;@users&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So all in all this is a small, but meaningful, step towards robust controller-level &lt;span class="caps"&gt;REST&lt;/span&gt; support.  I should point out that the contributor of this patch is &lt;a href="http://blog.plataformatec.com.br/"&gt;José Valim&lt;/a&gt; who has authored the very robust &lt;a href="http://github.com/josevalim/inherited_resources/tree/master"&gt;inherited_resources&lt;/a&gt; framework that already has support for &lt;code&gt;respond_with&lt;/code&gt;-like functionality and many more goodies.  If you’re on the search for a solid RESTful controller framework to accompany Rails’ native RESTful routing support I would suggest you take a look at his fine work.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/24JUvuyJLH4MxKxRk0vPsUxWrZU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/24JUvuyJLH4MxKxRk0vPsUxWrZU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/24JUvuyJLH4MxKxRk0vPsUxWrZU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/24JUvuyJLH4MxKxRk0vPsUxWrZU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=5jNi5oU91Jk:7SUQimTq9U8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=5jNi5oU91Jk:7SUQimTq9U8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=5jNi5oU91Jk:7SUQimTq9U8:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=5jNi5oU91Jk:7SUQimTq9U8:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=5jNi5oU91Jk:7SUQimTq9U8:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/5jNi5oU91Jk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-06-02:9007</id>
    <published>2009-06-02T00:24:00Z</published>
    <updated>2009-06-02T00:25:06Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/43EeQAUrHd0/rubyists-learn-some-iphone-skillz" rel="alternate" type="text/html" />
    <title>Rubyists, Learn Some iPhone Skillz</title>
<content type="html">
            &lt;p&gt;If any of you Rubyists are going to be attending the &lt;a href="http://futureruby.com/"&gt;FutureRuby&lt;/a&gt; in Toronto this July and have an interest in learning how to work some magic on the iPhone, I encourage you to check out Mobile Orchard’s Dan Grigsby and his &lt;a href="http://www.mobileorchard.com/futureruby-and-mobile-orchard-workshops-present-beginning-iphone-programming-for-rubyists-toronto-july-9-10/"&gt;Beginning iPhone Programming For Rubyists&lt;/a&gt; course taking place before FutureRuby.  In addition to the iPhone basics, he’ll be covering our &lt;a href="http://iphoneonrails.com"&gt;ObjectiveResource&lt;/a&gt; framework.&lt;/p&gt;


	&lt;p&gt;You can get a discount on the course if you register before June 9th so head on over and give it a peek.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Oup5OLRjjmEE38ropRw28kmFJIA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Oup5OLRjjmEE38ropRw28kmFJIA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Oup5OLRjjmEE38ropRw28kmFJIA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Oup5OLRjjmEE38ropRw28kmFJIA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=43EeQAUrHd0:EoD7lld2-HQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=43EeQAUrHd0:EoD7lld2-HQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=43EeQAUrHd0:EoD7lld2-HQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=43EeQAUrHd0:EoD7lld2-HQ:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=43EeQAUrHd0:EoD7lld2-HQ:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/43EeQAUrHd0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/6/2/rubyists-learn-some-iphone-skillz</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-05-13:8947</id>
    <published>2009-05-13T12:44:00Z</published>
    <updated>2009-05-13T12:45:26Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/92mX4bPlDoM/what-s-new-in-edge-rails-database-seeding" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Database Seeding</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is schedule for: Rails v3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;I’m not sure if this was ever stated explicitly has a preferred practice or not, but for the longest time many of us have recognized that using migrations as a way to populate the database with a base configuration dataset is wrong.  Migrations are for manipulating the structure of your database, not for the data within it and certainly not for simple population tasks.&lt;/p&gt;


	&lt;p&gt;Well, this practice now has a formal support in Rails with the addition of the &lt;a href="http://github.com/rails/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb"&gt;database seeding&lt;/a&gt; feature.  Quite simply this is a rake task that sucks in the data specified in a &lt;code&gt;db/seeds.rb&lt;/code&gt;.  Here are the details:&lt;/p&gt;


	&lt;h3&gt;Specify Seed Data&lt;/h3&gt;


	&lt;p&gt;Add or open the &lt;code&gt;db/seeds.rb&lt;/code&gt; file and put in model creation statements (or any ruby code) for the data you need to be present in order for your application to run.  I.e. configuration and default data (and nothing more):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;[&lt;span class="sy"&gt;:admin&lt;/span&gt;, &lt;span class="sy"&gt;:user&lt;/span&gt;].each { |r| &lt;span class="co"&gt;Role&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; r) }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:login&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:role&lt;/span&gt; =&amp;gt; &lt;span class="co"&gt;Role&lt;/span&gt;.find_by_name(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;))&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h3&gt;Load the Data&lt;/h3&gt;


	&lt;p&gt;Once that is in place you can run one of two rake tasks that will populate the database with this data:
&lt;code&gt;rake db:seed&lt;/code&gt; which will only populate the db with this data and &lt;code&gt;rake db:setup&lt;/code&gt; which will create the db, load the schema and then load the seed data.  This is the task you’ll want to use if you’re starting in a fresh environment.&lt;/p&gt;


	&lt;p&gt;So, quit overloading your migrations with seed data and use this new facility.  But, don’t go overboard and use &lt;code&gt;seeds.rb&lt;/code&gt; for test or staging datasets – it should only be used for the base data that is necessary for your app to run.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Zn-2lXESl1vHEoO12Qkh5V9LyPY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Zn-2lXESl1vHEoO12Qkh5V9LyPY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Zn-2lXESl1vHEoO12Qkh5V9LyPY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Zn-2lXESl1vHEoO12Qkh5V9LyPY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=92mX4bPlDoM:b-YCitb3VsM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=92mX4bPlDoM:b-YCitb3VsM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=92mX4bPlDoM:b-YCitb3VsM:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=92mX4bPlDoM:b-YCitb3VsM:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=92mX4bPlDoM:b-YCitb3VsM:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/92mX4bPlDoM" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/5/13/what-s-new-in-edge-rails-database-seeding</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-04-20:8816</id>
    <published>2009-04-20T11:51:00Z</published>
    <updated>2009-08-10T12:50:34Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/8vzRfWygTY0/what-s-new-in-edge-rails-touching" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Touching</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature was released in Rails v2.3.3&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;There are often times when you want an update made to one object to be reflected up the object graph as an update of an associated parent object.  For instance, if a new comment is created on an article, you may very well want to mark the article as being updated.  With the &lt;a href="http://github.com/rails/rails/commit/abb899c54e8777428b7a607774370ba29a5573bd"&gt;new touch feature&lt;/a&gt; of ActiveRecord, this is a whole lot easier.  Using our previous example, here’s is how it works:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Article&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:comments&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Comment&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# Make create/update/deletes of a comment mark its&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# parent article as updated&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  belongs_to &lt;span class="sy"&gt;:article&lt;/span&gt;, &lt;span class="sy"&gt;:touch&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Adding a new comment marks the article as being updated&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:42:53 -0400 2009&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.comments.create(&lt;span class="sy"&gt;:body&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;New comment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;article.updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:43:27 -0400 2009&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Same for updates/deletes&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.comments.first.destroy&lt;tt&gt;
&lt;/tt&gt;article.updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:45:23 -0400 2009&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is a great way to keep tightly coupled domain models in-sync without resorting to a potential maze of callback logic.&lt;/p&gt;


	&lt;p&gt;Also, if you have a timestamp field named something other than the standard &lt;code&gt;updated_at&lt;/code&gt; or &lt;code&gt;updated_on&lt;/code&gt; you can explicitly specify that field as the value to the &lt;code&gt;:touch&lt;/code&gt; option and it will get marked instead:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Article&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:comments&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_presence_of &lt;span class="sy"&gt;:last_updated_at&lt;/span&gt;  &lt;span class="c"&gt;# non-standard&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Comment&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  belongs_to &lt;span class="sy"&gt;:article&lt;/span&gt;, &lt;span class="sy"&gt;:touch&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:last_updated_at&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Adding a new comment marks the article as being updated&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.last_updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:42:53 -0400 2009&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.comments.create(&lt;span class="sy"&gt;:body&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;New comment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;article.last_updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:43:27 -0400 2009&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Also, somewhat conveniently, you can invoke &lt;code&gt;touch&lt;/code&gt; directly on a model to update its timestamp outside any association callbacks:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;article.updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:42:53 -0400 2009&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article.touch&lt;tt&gt;
&lt;/tt&gt;article.updated_at &lt;span class="c"&gt;#=&amp;gt; &amp;quot;Mon Apr 20 07:43:27 -0400 2009&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So, touch away (in a non-creepy kind of way)!&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8drsSAGHVCQat65XZ9A3qLn6P_s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8drsSAGHVCQat65XZ9A3qLn6P_s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8drsSAGHVCQat65XZ9A3qLn6P_s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8drsSAGHVCQat65XZ9A3qLn6P_s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=8vzRfWygTY0:240spXC_-4g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=8vzRfWygTY0:240spXC_-4g:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=8vzRfWygTY0:240spXC_-4g:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RyansScraps?a=8vzRfWygTY0:240spXC_-4g:I2FUP0JpNAM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RyansScraps?i=8vzRfWygTY0:240spXC_-4g:I2FUP0JpNAM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/8vzRfWygTY0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/4/20/what-s-new-in-edge-rails-touching</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-02-23:8548</id>
    <published>2009-02-23T21:30:00Z</published>
    <updated>2009-06-26T13:05:00Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/_iSUBztPm80/what-s-new-in-edge-rails-batched-find" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Batched Find</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is scheduled for: Rails v2.3&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;ActiveRecord got a little batch-help today with the addition of &lt;a href="http://github.com/rails/rails/commit/d13623ca46c82120c398f4634e206422fc3ad7ea"&gt;ActiveRecord::Base#find_each and ActiveRecord::Base#find_in_batches&lt;/a&gt;.  The former lets you iterate over all the records in cursor-like fashion (only retrieving a set number of records at a time to avoid cramming too much into memory):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.find_each { |a| ... } &lt;span class="c"&gt;# =&amp;gt; iterate over all articles, in chunks of 1000 (the default)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.find_each(&lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:published&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt; }, &lt;span class="sy"&gt;:batch_size&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;100&lt;/span&gt; ) { |a| ... }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# iterate over published articles in chunks of 100&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You’re not exposed to any of the chunking logic – all you need to do is iterate over each record and just trust that they’re only being retrieved in manageable groups.&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;find_in_batches&lt;/code&gt; performs a similar function, except that it hands back each chunk array directly instead of just a stream of individual records:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.find_in_batches { |articles| articles.each { |a| ... } }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# =&amp;gt; articles is array of size 1000&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.find_in_batches(batch_size =&amp;gt; &lt;span class="i"&gt;100&lt;/span&gt; ) { |articles| articles.each { |a| ... } }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# iterate over all articles in chunks of 100&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;code&gt;find_in_batches&lt;/code&gt; is also kind enough to observe good scoping practices:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Article&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  named_scope &lt;span class="sy"&gt;:published&lt;/span&gt;, &lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:published&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.published.find_in_batches(&lt;span class="sy"&gt;:batch_size&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;100&lt;/span&gt; ) { |articles| ... }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# iterate over published articles in chunks of 100&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;One quick caveat exists: you can’t specify &lt;code&gt;:order&lt;/code&gt; or &lt;code&gt;:limit&lt;/code&gt; in the options to &lt;code&gt;find_each&lt;/code&gt; or &lt;code&gt;find_in_batches&lt;/code&gt; as those values are used in the internal looping logic.&lt;/p&gt;


	&lt;p&gt;Batched finds are best used when you have a potentially large dataset and need to iterate through all rows.  If done using a normal find the full result-set will be loaded into memory and could cause problems.  With batched finds you can be sure that only 1000 * (each result-object size) will be loaded into memory.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WpRFCrcmIBcWQW_RiiZ0dPRm8rY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WpRFCrcmIBcWQW_RiiZ0dPRm8rY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WpRFCrcmIBcWQW_RiiZ0dPRm8rY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WpRFCrcmIBcWQW_RiiZ0dPRm8rY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=8zhErFYH"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=VukmmZnV"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=WMpmOQjG"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=Kelyouc1"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=Kelyouc1" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/_iSUBztPm80" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-02-05:8427</id>
    <published>2009-02-05T13:06:00Z</published>
    <updated>2009-02-05T14:03:44Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/YuVwycVs5Uw/get-your-iphone-and-rails-apps-talkin" rel="alternate" type="text/html" />
    <title>Get Your iPhone and Rails Apps Talkin'</title>
<content type="html">
            &lt;p&gt;The iPhone is cool and sexy.  Rails is cool and sexy.  Shouldn’t they be a little more compatible?&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://yfactorial.com"&gt;We&lt;/a&gt; think so and have &lt;a href="http://iphoneonrails.com"&gt;released the first version of ObjectiveResource&lt;/a&gt;, our port of Rails’ ActiveResource to Objective-C for the iPhone.  We’ve used it extensively on some of &lt;a href="http://yfactorial.com/index.php/portfolio/category/iphone_development/"&gt;our iphone projects&lt;/a&gt; and have gotten a good response from others that have stumbled upon it.&lt;/p&gt;


	&lt;p&gt;Basically, it provides an easy way to consume and integrate with Rails’ standard &lt;span class="caps"&gt;XML&lt;/span&gt; and &lt;span class="caps"&gt;JSON&lt;/span&gt; RESTful web-services (just as ActiveResource does for Ruby).&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://iphoneonrails.com"&gt;&lt;img src="http://ryandaigle.com/assets/2009/2/5/iphoneonrails.png"&gt;&lt;/a&gt;  &lt;a href="http://iphoneonrails.com"&gt;iPhoneOnRails.com&lt;/a&gt; is where we’re going to keep the development progress and planning for the framework as well as the various resources we’ve established for those that have questions and concerns.  So have a look, &lt;a href="http://github.com/yfactorial/objectiveresource/tree/master"&gt;play with the source yourself&lt;/a&gt;, join the &lt;a href="http://groups.google.com/group/objectiveresource"&gt;mailing list&lt;/a&gt; and keep track at the &lt;a href="http://iphoneonrails.com/blog"&gt;iPhoneOnRails blog&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;And let us know if you’re using ObjectiveResource and want to be featured on the site, or have a quote about using the framework you want us to put up.&lt;/em&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LLhZ8WG8Glsr2xqZdNxHB4iyl_8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LLhZ8WG8Glsr2xqZdNxHB4iyl_8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LLhZ8WG8Glsr2xqZdNxHB4iyl_8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LLhZ8WG8Glsr2xqZdNxHB4iyl_8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=gKO6yBMO"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=B7zy6ANH"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=Io0WPweG"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=KgkCX8fP"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=KgkCX8fP" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/YuVwycVs5Uw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/2/5/get-your-iphone-and-rails-apps-talkin</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-02-02:8117</id>
    <published>2009-02-02T00:43:00Z</published>
    <updated>2009-03-05T13:02:15Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/09MWz_QHjbs/rails-2-3-released-summary-of-features" rel="alternate" type="text/html" />
    <title>Rails 2.3 Released - Summary of Features</title>
<content type="html">
            &lt;p&gt;Here’s a list of the major new features in Rails v2.3 (most recent first):&lt;/p&gt;


	&lt;h2&gt;Rails 2.3 Features&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="/articles/2009/2/23/what-s-new-in-edge-rails-batched-find"&gt;Batched find&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes"&gt;Nested Model Mass Assignment&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2009/1/30/what-s-new-in-edge-rails-http-digest-authentication"&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Digest Authentication&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/12/29/what-s-new-in-edge-rails-dynamic-scope-methods"&gt;Dynamic Scopes&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/12/11/what-s-new-in-edge-rails-application-generators" title="templates"&gt;Application Generators&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/12/18/what-s-new-in-edge-rails-rails-metal"&gt;Rails Metal&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/11/27/what-s-new-in-edge-rails-no-more-formatted-routes"&gt;No More Formatted Routes&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/11/20/what-s-new-in-edge-rails-object-try"&gt;Object.try&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/11/20/what-s-new-in-edge-rails-render-stops-being-high-maintenance"&gt;Simplified render&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/11/19/what-s-new-in-edge-rails-application-rb-duality-is-no-more"&gt;application.rb Becomes application_controller.rb&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping"&gt;Default Scoping&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The next scheduled release appears to be the 3.0 release, the merger of Rails and Merb.  The core team has alluded to at least a preview release to be ready by &lt;a href="http://en.oreilly.com/rails2009/"&gt;RailsConf 2009&lt;/a&gt;.  Seems a bit aggressive for all the internal tinkering in store, but stay here for for the latest.&lt;/p&gt;


	&lt;p&gt;You should also check out the &lt;a href="http://guides.rubyonrails.org/2_3_release_notes.html"&gt;Rails 2.3 release notes&lt;/a&gt; for the ‘official’ rundown of new features for 2.3.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/b2stAMMTzW8uco9qfzJVu17webo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b2stAMMTzW8uco9qfzJVu17webo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/b2stAMMTzW8uco9qfzJVu17webo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b2stAMMTzW8uco9qfzJVu17webo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=cx4Sw4ct"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=MJ9vID7v"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=jqf4rWuQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=jN9Di2Tl"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=jN9Di2Tl" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/09MWz_QHjbs" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/2/2/rails-2-3-released-summary-of-features</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-02-01:8393</id>
    <published>2009-02-01T14:59:00Z</published>
    <updated>2009-06-26T13:04:55Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/tuzquWKarO0/what-s-new-in-edge-rails-nested-attributes" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Nested Object Forms</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is scheduled for: Rails v2.3&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;We were all teased a few months ago about the possibility of finally &lt;a href="/articles/2008/7/19/what-s-new-in-edge-rails-nested-models"&gt;solving the nested model/complex forms problem in Rails&lt;/a&gt;, but were then cruelly notified that it wasn’t &lt;a href="http://groups.google.com/group/rubyonrails-core/browse_thread/thread/3c61e00916c365e5"&gt;quite ready for prime time&lt;/a&gt;.  But our day has come – the &lt;a href="http://rails.uservoice.com/pages/rails3/suggestions/99641-nested-model-forms"&gt;most requested feature&lt;/a&gt; for Rails 2.3, the &lt;a href="http://github.com/rails/rails/commit/ec8f04584479aff895b0b511a7ba1e9d33f84067"&gt;ability to handle multiple models in a single form&lt;/a&gt;, is here.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;This &lt;a href="http://github.com/rails/rails/commit/5dbc9d40a49f5f0f50c2f3ebe6dda942f0e61562"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; update&lt;/a&gt; was added after the original commit.  I’ve updated the examples here to account for this.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;This feature has &lt;a href="http://weblog.rubyonrails.org/2009/1/26/nested-model-forms"&gt;already been written about on the Rails Blog&lt;/a&gt; quite well by Eloy Duran, the committer of this fine feature, so I’ll try not to replicate what’s already out there.  However, here’s a basic rundown of what you need to do to get your models nested-form capable.&lt;/p&gt;


	&lt;h3&gt;Step 1: Notify Your Model of Nest-able Associations&lt;/h3&gt;


	&lt;p&gt;The first step is to tell your models which of their associations will be able to receive nested attributes.  For all associations you want exposed in nested forms you’ll need to use &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_presence_of &lt;span class="sy"&gt;:name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:children&lt;/span&gt;, &lt;span class="sy"&gt;:class_name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  accepts_nested_attributes_for &lt;span class="sy"&gt;:children&lt;/span&gt;, &lt;span class="sy"&gt;:allow_destroy&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# can also be used on has_one etc.. associations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;With this bit in place, you can now directly create, edit and delete children from a person:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Add a new child to this person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes = [ { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Son&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children &lt;span class="c"&gt;#=&amp;gt; [ &amp;lt;#Person: name: 'Son'&amp;gt; ]&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children.clear&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Add two new children to this person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes =&lt;tt&gt;
&lt;/tt&gt;  [ { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Son&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; }, { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Daughter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children &lt;span class="c"&gt;#=&amp;gt; [ &amp;lt;#Person: name: 'Son'&amp;gt;, &amp;lt;#Person: name: 'Daughter'&amp;gt; ]&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Edit the son (assuming id == 1)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes = [ { &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;, &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Lad&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; the son's name is now 'Lad'&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Edit the daughter (id == 2) and add a new offspring&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes =&lt;tt&gt;
&lt;/tt&gt;  [ { &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;2&lt;/span&gt;, &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Lassie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; }, { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Pat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; the daughter's name is now 'Lassie' and there's a new offspring called 'Pat'&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="c"&gt;# Remove Pat (id = 3), we don't like him/her&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes = [ &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;3&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;_delete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; Pat is now deleted&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


You’ll want to take away a few things from these examples.
	&lt;ul&gt;
	&lt;li&gt;To support both the creation of new objects and the editing of existing ones we have to use an array of hashes for one-to-many associations or a single hash for one-to-one associations.  If no &lt;code&gt;:id&lt;/code&gt; property exists then it is assumed to represent a nested model to create.&lt;/li&gt;
		&lt;li&gt;To delete an existing nested model, use this format: &lt;code&gt;[ :id =&amp;gt; pk, '_delete' =&amp;gt; '1' } ]&lt;/code&gt; where the value of &lt;code&gt;_delete&lt;/code&gt; evaluates to anything &lt;code&gt;true&lt;/code&gt;.  You must also set the &lt;code&gt; accepts_nested_attributes_for&lt;/code&gt; option &lt;code&gt;:allow_destroy&lt;/code&gt; to true as that capability is turned off by default.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;While this may appear a bit hackish when you’re used to dealing with the pleasantries of a rich object model and with ActiveRecord’s associations, this provides the foundation for a seamless transition to the view where you need to create your nested model forms…&lt;/p&gt;


	&lt;h3&gt;Step 2: Create a Nested Model Form&lt;/h3&gt;


	&lt;p&gt;In the view, simply use &lt;a href="http://api.rubyonrails.com/classes/ActionView/Helpers/FormHelper.html#M001386"&gt;fields_for&lt;/a&gt; on these nested models to expose the fields for each such model:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;% form_for @person do |person_form| %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= person_form.label :name %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= person_form.text_field :name %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;% person_form.fields_for :children do |child_form| %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;%= child_form.label :name %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;%= child_form.text_field :name %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;% unless child_form.object.new_record? %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;%= child_form.check_box '_delete' %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;%= child_form.label '_delete', 'Remove' %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;% end %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;% end %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;%= submit_tag %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;% end %&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This will create a form with all the form fields necessary for submitting to a RESTful controller, transparently pushing your &lt;code&gt;children_attributes&lt;/code&gt; onto the person.&lt;/p&gt;


	&lt;p&gt;If there are any validation errors on a child, they will be added to &lt;code&gt;person.errors&lt;/code&gt;, and nothing will save if any of the children fail (i.e. fully transactional).&lt;/p&gt;


A few notes that might be useful to you:
	&lt;ul&gt;
	&lt;li&gt;Using &lt;code&gt;fields_for&lt;/code&gt; on a has_many association automatically executes once for each nested model present, so think of yourself as being inside a loop when building your &lt;code&gt;child_form&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;If you ever need to change behavior based on the nested model currently in scope, it can be accessed via &lt;code&gt;child_form.object&lt;/code&gt;.  In this example we use &lt;code&gt;child_form.object.new_record?&lt;/code&gt; to determine whether or not to display the delete checkbox (as that only makes sense on an existing record).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Step 3: In Your Controllers … Do Nothing&lt;/h3&gt;


	&lt;p&gt;The third step should be the easiest, because we’re all dealing with purely RESTful controllers, right?  The beauty of this solution is that it takes your controllers out of the mix and makes standard for submissions work perfectly with no interference at the controller level.  Just so there’s no confusion, here’s how your create and update actions will look:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;PersonController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.new(params[&lt;span class="sy"&gt;:person&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt;.save ? redirect_to(person_path(&lt;span class="iv"&gt;@person&lt;/span&gt;)) : render(&lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:new&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;update&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.find(params[&lt;span class="sy"&gt;:id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt;.update_attributes(params[&lt;span class="sy"&gt;:person&lt;/span&gt;]) ?&lt;tt&gt;
&lt;/tt&gt;      redirect_to(person_path(&lt;span class="iv"&gt;@person&lt;/span&gt;)) : render(&lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:edit&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Not a peep of those pesky nested models – with the rich support for nested objects at the model layer, it just works!&lt;/p&gt;


	&lt;h3&gt;Extras&lt;/h3&gt;


	&lt;p&gt;As with most powerful features, there are few little tweaks you may find yourself needing.&lt;/p&gt;


	&lt;h4&gt;Default Create Form Fields&lt;/h4&gt;


	&lt;p&gt;Often times you’ll want to have the form displayed with empty fields for easily creating a new nested model.  For example, when a user goes to create a new person I want there to be fields for creating a new child already displayed.&lt;/p&gt;


	&lt;p&gt;Since the &lt;code&gt;person&lt;/code&gt; object is brand new they have an empty &lt;code&gt;children&lt;/code&gt; collection and no &lt;code&gt;child_form&lt;/code&gt; fields will be displayed.  There are two ways to get around this:&lt;/p&gt;


	&lt;p&gt;You can build a new nested object on the controller side (i.e. in the &lt;code&gt;new&lt;/code&gt; action):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt; = &lt;span class="co"&gt;Person&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="iv"&gt;@person&lt;/span&gt;.children.build&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;which will cause there to be empty &lt;code&gt;child_form&lt;/code&gt; fields displayed as desired.  Or you can do it on the view side with a view helper:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;ApplicationHelper&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;setup_person&lt;/span&gt;(person)&lt;tt&gt;
&lt;/tt&gt;    returning(person) &lt;span class="r"&gt;do&lt;/span&gt; |p|&lt;tt&gt;
&lt;/tt&gt;      p.children.build &lt;span class="r"&gt;if&lt;/span&gt; p.children.empty?&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Which can then be used within &lt;code&gt;form_for&lt;/code&gt; to setup the person to the correct form state:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;% form_for setup_person(@person) do |person_form| %&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;!-- ... --&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;% end %&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;I prefer this view-helper approach as it really is a view concern (whether or not to display the form fields to create a new nested object by default).&lt;/p&gt;


	&lt;h4&gt;Specify When Nested Models get Built&lt;/h4&gt;


	&lt;p&gt;If you do have empty nested model form fields displayed by default, you’ll run into the issue where the user submits the form with no values filled in and you have to decide if you want to treat that as somebody trying to create a new nested item with no values, or if that means that no new nested item was submitted.  Quite often you just want to ignore the submissions with no nested field values filled out.&lt;/p&gt;


	&lt;p&gt;Although I would have expected this to be default behavior, you need to manually specify that submissions with empty nested values are ignored using the &lt;code&gt;:reject_if&lt;/code&gt; option of &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt;:&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; You &lt;a href="http://github.com/rails/rails/commit/9010ed27559ed5ab89ea71b4b16f4c8e56d03dbb"&gt;now have the option to use &lt;code&gt;:all_blank&lt;/code&gt;&lt;/a&gt; to ignore the item if all properties are blank.  See below for an updated example.&lt;/em&gt;&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_presence_of &lt;span class="sy"&gt;:name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:children&lt;/span&gt;, &lt;span class="sy"&gt;:class_name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# This will prevent children_attributes with all empty values to be ignored&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  accepts_nested_attributes_for &lt;span class="sy"&gt;:children&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="sy"&gt;:reject_if&lt;/span&gt; =&amp;gt; proc { |attrs| attrs.all? { |k, v| v.blank? } }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# This does the same thing using :all_blank&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  accepts_nested_attributes_for &lt;span class="sy"&gt;:children&lt;/span&gt;, &lt;span class="sy"&gt;:reject_if&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:all_blank&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes = [ { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children.count &lt;span class="c"&gt;#=&amp;gt; 0&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is also useful if you have boolean values in your nested model fields (since, as a checkbox, ‘0’ will be submitted if there’s no value):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_presence_of &lt;span class="sy"&gt;:name&lt;/span&gt;, &lt;span class="sy"&gt;:bad&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:children&lt;/span&gt;, &lt;span class="sy"&gt;:class_name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# This will prevent empty checkboxes submitted for a child to be&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# construed as a submission&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  accepts_nested_attributes_for &lt;span class="sy"&gt;:children&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="sy"&gt;:reject_if&lt;/span&gt; =&amp;gt; proc { |attrs| attrs[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;bad&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;] == &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &amp;amp;&amp;amp; attrs[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;].blank? }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children_attributes = [ { &lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:bad&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; } ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;&lt;span class="iv"&gt;@person&lt;/span&gt;.children.count &lt;span class="c"&gt;#=&amp;gt; 0&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h4&gt;Dynamically Adding Nested Form Fields&lt;/h4&gt;


	&lt;p&gt;If you want to allow the addition of a large number of nested models via your &lt;span class="caps"&gt;HTML&lt;/span&gt; forms, one option is to just have several empty nested forms displayed by default.  This is a little unappealing, however. The far slicker option is to use javascript to dynamically display the new nested form on the user’s request.&lt;/p&gt;


	&lt;p&gt;Eloy has a great &lt;a href="http://github.com/alloy/complex-form-examples/tree/nested_attributes"&gt;example application&lt;/a&gt; setup on GitHub outlining how this works, and I’ll let you take a peek over there to see how to &lt;a href="http://github.com/alloy/complex-form-examples/blob/a234fde4419836f277d7e340657f1d8418911d68/app/views/projects/_form.html.erb#L40"&gt;wire up your dynamic nested form additions&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Eloy’s example app is also a great place to see how the whole thing works, end-to-end.  By far the best resource out there.&lt;/p&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;So there it is, Rails’ most requested new feature in the flesh and blood.  I’m not sure if my experiences are indicative of everybody else’s, but this is a godsend for me.  Many thanks to all the folks involved with this functionality (if you don’t know who they are, check out the next section which links to a bunch of great resources).  A really great effort by the community.&lt;/p&gt;


	&lt;h3&gt;Resources&lt;/h3&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/alloy/complex-form-examples/tree/nested_attributes"&gt;Eloy Duran’s example nested model project&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1202-add-attributes-writer-method-for-an-association"&gt;The Lighthouse ticket for this feature with some good discussions&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://weblog.rubyonrails.org/2009/1/26/nested-model-forms"&gt;The blog post on the official Rails blog&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://groups.google.com/group/rubyonrails-core/browse_thread/thread/3c61e00916c365e5"&gt;The discussion of the various incarnations of this feature on the mailing list&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://railscasts.com/episodes/73"&gt;Ryan Bates’ Railscast on complex forms&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NuBQdAIk_3aREUuB9n0698ttqWY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NuBQdAIk_3aREUuB9n0698ttqWY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NuBQdAIk_3aREUuB9n0698ttqWY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NuBQdAIk_3aREUuB9n0698ttqWY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=ktQjgX0t"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=vMawsjpm"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=iJOlHmVa"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=acLwcXAN"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=acLwcXAN" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/tuzquWKarO0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-01-30:8387</id>
    <published>2009-01-30T02:03:00Z</published>
    <updated>2009-03-18T00:22:37Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/yorFPWcFJ8o/what-s-new-in-edge-rails-http-digest-authentication" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: HTTP Digest Authentication</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is scheduled for: Rails v2.3&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;Long ago, in your mother’s version of rails, we got a &lt;a href="/articles/2006/12/4/whats-new-in-edge-rails-new-http-authentication-plugin-and-a-plea-to-contribute"&gt;http basic authentication&lt;/a&gt; plugin.  That functionality has since been rolled into Rails core, but it was always lacking &lt;span class="caps"&gt;HTTP&lt;/span&gt; digest authentication.  Until &lt;a href="http://github.com/rails/rails/commit/306cc2b920203cfa51cee82d2fc452484efc72f8"&gt;this commit&lt;/a&gt;, that is.&lt;/p&gt;


	&lt;p&gt;For those that may now know the difference, basic authentication only base 64 encodes the authenticating username and password (making it easily decoded) whereas digest authentication sends an &lt;span class="caps"&gt;MD5&lt;/span&gt; hash of your username and password.  To simplify, digest is more secure than basic.&lt;/p&gt;


	&lt;p&gt;To request digest authentication in Rails, &lt;del&gt;you’ll need to be able to retrieve the cleartext password for a given user (so the framework can hash and compare it using the nonce it created specifically for that request)&lt;/del&gt;.  &lt;em&gt;This &lt;a href="http://github.com/rails/rails/commit/be7b64b35aac1c9e9063d1d8317f8b1be2a3411c"&gt;commit&lt;/a&gt; now allows you to also use a specific hashed format of the password.&lt;/em&gt;  Here’s how this works if you have access to a cleartext password:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ArticlesController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  before_filter &lt;span class="sy"&gt;:digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# Given this username, return the cleartext password (or nil if not found)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    authenticate_or_request_with_http_digest(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Articles Administration&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |username|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;User&lt;/span&gt;.find_by_username(username).try(cleartext_password)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Most of us will want to do something with the result of the authentication and can do so with the boolean return value of &lt;code&gt; authenticate_or_request_with_http_digest&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ArticlesController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  before_filter &lt;span class="sy"&gt;:digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    success = authenticate_or_request_with_http_digest(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |username|&lt;tt&gt;
&lt;/tt&gt;      (&lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.find_by_username(username)).try(cleartext_password)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# If authentication succeeds, log the user in.  If not, kick back out a failure&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# message as the response body&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; success&lt;tt&gt;
&lt;/tt&gt;      session[&lt;span class="sy"&gt;:user_id&lt;/span&gt;] = &lt;span class="iv"&gt;@user&lt;/span&gt;.id&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      request_http_digest_authentication(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Authentication failed&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you don’t want to store clear text passwords you can return an &lt;span class="caps"&gt;MD5&lt;/span&gt; hash from the &lt;code&gt;authenticate_or_request_with_http_digest&lt;/code&gt; block as long as it’s in the format &lt;code&gt;username:realm:password&lt;/code&gt;.  You can get a password hash by using &lt;code&gt;Digest::MD5::hexdigest&lt;/code&gt;.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  attr_accessor &lt;span class="sy"&gt;:password&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  validates_presence_of &lt;span class="sy"&gt;:username&lt;/span&gt;, &lt;span class="sy"&gt;:crypted_password&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  before_save &lt;span class="sy"&gt;:hash_password&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  ...&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;hash_password&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; password_changed?&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="pc"&gt;self&lt;/span&gt;.crypted_password =&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="co"&gt;Digest&lt;/span&gt;::&lt;span class="co"&gt;MD5&lt;/span&gt;::hexdigest([username, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;UserRealm&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, password].join(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;))&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;and then in your controller:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ArticlesController&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  before_filter &lt;span class="sy"&gt;:digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;digest_authenticate&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# Just return the crypted (hashed) version of the password if it's in the supported&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# format.  Note that the realm here &amp;quot;UserRealm&amp;quot; should match the middle&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# argument of your password hash&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    success = authenticate_or_request_with_http_digest(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;UserRealm&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |username|&lt;tt&gt;
&lt;/tt&gt;      (&lt;span class="iv"&gt;@user&lt;/span&gt; = &lt;span class="co"&gt;User&lt;/span&gt;.find_by_username(username)).try(crypted_password)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    ...&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So there you have it, digest authentication in edge Rails.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2OlmOxU_zzpUsqTKkd7YERnQ6CA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2OlmOxU_zzpUsqTKkd7YERnQ6CA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2OlmOxU_zzpUsqTKkd7YERnQ6CA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2OlmOxU_zzpUsqTKkd7YERnQ6CA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=TJdTREt2"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=gihCYhZY"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=TrrdJAnl"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=EjafPmGm"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=EjafPmGm" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/yorFPWcFJ8o" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/1/30/what-s-new-in-edge-rails-http-digest-authentication</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2009-01-07:8336</id>
    <published>2009-01-07T16:10:00Z</published>
    <updated>2009-01-08T00:26:10Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/62Lizm-9be0/need-nested-model-support-in-rails-vote-for-it" rel="alternate" type="text/html" />
    <title>Need Nested Model Support in Rails?  Vote for it!</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Nested Model support in Rails is &lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/1202-add-attributes-writer-method-for-an-association"&gt;currently scheduled&lt;/a&gt; for Rails 2.3.  Yay!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;The Rails team has recently organized its community around the &lt;a href="http://rubyonrails.org/activists"&gt;Rails Activists&lt;/a&gt; group and provided several ways for you to speak your mind about the framework – and one of the best ways to impact the maturation of the framework is to &lt;a href="http://rails.uservoice.com/pages/rails3"&gt;vote for features&lt;/a&gt; you’d like to see in upcoming releases.&lt;/p&gt;


	&lt;p&gt;While I don’t usually like to use this site as a bully pulpit, I have to say that the one feature I’d love to see make it’s way into Rails is &lt;a href="http://ryandaigle.com/articles/2008/7/19/what-s-new-in-edge-rails-nested-models"&gt;nested model mass assignment&lt;/a&gt; support.  The team teased us with the foundation of an initial implementation but later yanked it since it didn’t quite cover all the cases.&lt;/p&gt;


	&lt;p&gt;I’ve setup a suggestion on uservoice for exactly this feature.  If you’d like to see this support in Rails &lt;a href="http://rails.uservoice.com/pages/rails3/suggestions/99641-nested-model-forms"&gt;vote for it now!&lt;/a&gt; to be heard.&lt;/p&gt;


	&lt;p&gt;By the way, I totally acknowledge that I am being less than useful here only in complaining and not actually contributing.  Guilty as charged – but to be honest, it’s a hairy problem with a lot of edge cases and sometimes I’m just not that smart.&lt;/p&gt;


	&lt;p&gt;So be heard with your vote (for this feature or any other!)&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CGl4QNsQlu57DHOfN0PnTd2MAHA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CGl4QNsQlu57DHOfN0PnTd2MAHA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CGl4QNsQlu57DHOfN0PnTd2MAHA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CGl4QNsQlu57DHOfN0PnTd2MAHA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=NQe79smf"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=PU4jhGmA"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=QwBqiq7q"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=XNNDxSHZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=XNNDxSHZ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/62Lizm-9be0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2009/1/7/need-nested-model-support-in-rails-vote-for-it</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2008-12-29:8252</id>
    <published>2008-12-29T19:19:00Z</published>
    <updated>2009-03-17T23:56:18Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/1ENPn3rWZvw/contest-free-iphone-oxford-dictionary" rel="alternate" type="text/html" />
    <title>Contest: Free iPhone Oxford Dictionary</title>
<content type="html">
            &lt;p&gt;I’m not big on publicizing commercial works due to the obvious bias involved, but &lt;a href="http://yfactorial.com"&gt;we’ve&lt;/a&gt; recently finished up the &lt;a href="http://yfactorial.com/index.php/portfolio/category/iphone_development#oxford_dictionary"&gt;Oxford American College Dictionary and Thesaurus for the iPhone&lt;/a&gt; and our client was nice enough to give us a few free download codes.  Never one to waste free stuff I thought I’d offer them up to my readers.&lt;/p&gt;


	&lt;p&gt;So here’s the deal – to distribute these free downloads of our Oxford Dictionary for the iPhone (&lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=299247248&amp;mt=8"&gt;appstore&lt;/a&gt;) I’m going to run a little contest: Post your favorite word in the comments along with your preferred usage of the word (like an example sentence).  I’ll pick my favorite five entries after a week or so and will email you your promo codes (so be sure to leave your email address in the comment form).  &lt;em&gt;Note: I am a sucker for humor and wit, so be liberal in your application of them&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Most real iPhone dictionaries (from respected publications) go for upwards of $20 – $30 so this is a pretty decent value.&lt;/p&gt;


	&lt;p&gt;Now wow me with your vocabulary.&lt;/p&gt;


&lt;hr /&gt;
The winning words are: &lt;a href="#comment-8269"&gt;sesquipedalian&lt;/a&gt;, &lt;a href="#comment-8280"&gt;recidivist&lt;/a&gt;, &lt;a href="#comment-8286"&gt;floccinaucinihilipilification&lt;/a&gt;, &lt;a href="#comment-8307"&gt;obsequious&lt;/a&gt; (indirectly) and &lt;a href="#comment-8308"&gt;esquivalience&lt;/a&gt;
&lt;p /&gt;
You guys should be getting your promo codes in a few minutes.  Thanks for the submissions everybody!  (and, yes, all these words are in the dictionary app)
&lt;hr /&gt;

	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/iPhone"&gt;iPhone&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/dictionary"&gt;dictionary&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZAEcVLtFd7lJa6lgrL3yLZGXpHU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZAEcVLtFd7lJa6lgrL3yLZGXpHU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZAEcVLtFd7lJa6lgrL3yLZGXpHU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZAEcVLtFd7lJa6lgrL3yLZGXpHU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=CO7GSh4e"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=WvCedv5e"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=RodS5w42"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=owMrj1yC"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=owMrj1yC" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/1ENPn3rWZvw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2008/12/29/contest-free-iphone-oxford-dictionary</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2008-12-29:8247</id>
    <published>2008-12-29T14:24:00Z</published>
    <updated>2009-03-17T23:56:20Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/SXV0DRNVocw/what-s-new-in-edge-rails-dynamic-scope-methods" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Dynamic Scope Methods</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is scheduled for: Rails v2.3/3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;For quite some time now you’ve been able to perform simple queries using dynamic &lt;code&gt;find_all_by_xx_and_yy&lt;/code&gt; methods:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.find_by_published_and_user_id(&lt;span class="pc"&gt;true&lt;/span&gt;, &lt;span class="i"&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; &amp;quot;SELECT * FROM articles WHERE published = 1 AND user_id = 1&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;These dynamic finders provide an easy way to quickly encapsulate non-reused query conditions (for commonly used query logic you should consider using &lt;a href="/articles/2008/3/24/what-s-new-in-edge-rails-has-finder-functionality"&gt;named scopes&lt;/a&gt;).  The downside, however, is that you can’t chain query conditions when using these dynamic finders.&lt;/p&gt;


	&lt;p&gt;With the recent addition of &lt;a href="http://github.com/rails/rails/commit/66ee5890c5f21995b7fe0c486547f1287afe2b55"&gt;dynamic scopes&lt;/a&gt;, however, you now have a way to both quickly specify query logic and chain further conditions.  The naming works in the same manner as dynamic finders and the chaining works in the same fashion as conventional named scopes:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.scoped_by_published_and_user_id(&lt;span class="pc"&gt;true&lt;/span&gt;, &lt;span class="i"&gt;1&lt;/span&gt;).find(&lt;span class="sy"&gt;:all&lt;/span&gt;, &lt;span class="sy"&gt;:limit&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;5&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; &amp;quot;SELECT * FROM articles WHERE published = 1 AND user_id = 1 LIMIT 5&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Note how you can hang further chainable query methods off the dynamic scope here?  You could also have preceded the dynamic scope with another scope, or even another dynamic scope:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Article&lt;/span&gt;.scoped_by_published(&lt;span class="pc"&gt;true&lt;/span&gt;).scoped_by_user_id(&lt;span class="i"&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;#=&amp;gt; &amp;quot;SELECT * FROM articles WHERE published = 1 AND user_id = 1&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is really just another tool to put in your toolbox based on the powerful named_scope functionality of ActiveRecord.&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QjH7M-23C0-UXTM4Cgn2qsCrIFI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QjH7M-23C0-UXTM4Cgn2qsCrIFI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QjH7M-23C0-UXTM4Cgn2qsCrIFI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QjH7M-23C0-UXTM4Cgn2qsCrIFI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=GZp70DcS"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=zoWQfU44"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=vTvie8jq"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=CXVJkDHe"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=CXVJkDHe" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/SXV0DRNVocw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2008/12/29/what-s-new-in-edge-rails-dynamic-scope-methods</feedburner:origLink></entry>
  <entry xml:base="http://ryandaigle.com/">
    <author>
      <name>ryan</name>
    </author>
    <id>tag:ryandaigle.com,2008-12-23:8218</id>
    <published>2008-12-23T20:16:00Z</published>
    <updated>2008-12-23T20:24:16Z</updated>
    <link href="http://feedproxy.google.com/~r/RyansScraps/~3/3Kd9-J7VPdE/what-s-new-in-edge-rails-merb" rel="alternate" type="text/html" />
    <title>What's New in Edge Rails: Merb!</title>
<content type="html">
            &lt;hr /&gt;
&lt;em&gt;This feature is scheduled for: Rails v3.0&lt;/em&gt;
&lt;hr /&gt;

	&lt;p&gt;Wow, from the bombshell department comes the news that &lt;a href="http://rubyonrails.org/merb"&gt;Rails and Merb will be merging&lt;/a&gt; to form Rails 3.  It seems the Rails and Merb teams have acknowledged that there is good in both frameworks and that they can be combined into a singular web framework.&lt;/p&gt;


	&lt;p&gt;To be honest I don’t love the idea of having less choice in Ruby web-framework world.  However, I do think this bodes well for Rails.  We can only hope innovation stays alive within the combined team (and that their perspectives only enhance each other and don’t outright conflict).&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Read what &lt;a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/"&gt;Yehuda&lt;/a&gt;, now a Rails core team member, &lt;a href="http://brainspl.at/articles/2008/12/23/merb-is-rails"&gt;Ezra&lt;/a&gt;, &lt;a href="http://splendificent.com/2008/12/the-merb-rails-merger-announcement-an-inside-opinion/"&gt;Carl&lt;/a&gt; and &lt;a href="http://merbist.com/2008/12/23/rails-and-merb-merge/"&gt;Matt&lt;/a&gt; have to say as well.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Little ‘ole Rails is definitely growing up – lots of big stuff coming in Rails 3…&lt;/p&gt;


	&lt;p&gt;tags: &lt;a href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;,
&lt;a href="http://technorati.com/tag/rubyonrails"&gt;rubyonrails&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/KtiYC0osN6m71IYa_-tv-JtUwBg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KtiYC0osN6m71IYa_-tv-JtUwBg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/KtiYC0osN6m71IYa_-tv-JtUwBg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KtiYC0osN6m71IYa_-tv-JtUwBg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=67lb5KLI"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=c258y8r7"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=9B55xDOr"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/RyansScraps?a=F2IcbDhz"&gt;&lt;img src="http://feeds.feedburner.com/~f/RyansScraps?i=F2IcbDhz" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RyansScraps/~4/3Kd9-J7VPdE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ryandaigle.com/articles/2008/12/23/what-s-new-in-edge-rails-merb</feedburner:origLink></entry>
</feed>
