<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>scottraymondnet 2006 - Home</title>
  <id>tag:scottraymond.net,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://scottraymond.net/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://scottraymond.net/" rel="alternate" type="text/html"/>
  <updated>2007-03-07T20:30:53Z</updated>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2007-03-07:659</id>
    <published>2007-03-07T20:16:00Z</published>
    <updated>2007-03-07T20:30:53Z</updated>
    <link href="http://scottraymond.net/2007/3/7/sxsw-bound" rel="alternate" type="text/html"/>
    <title>SXSW bound</title>
<content type="html">
            &lt;p&gt;I'm headed to Austin this week for SXSW Interactive&amp;mdash;if you're there, please introduce yourself!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2007-01-24:657</id>
    <published>2007-01-24T19:46:00Z</published>
    <updated>2007-02-08T00:11:59Z</updated>
    <link href="http://scottraymond.net/2007/1/24/what-s-new-in-prototype-1-5" rel="alternate" type="text/html"/>
    <title>What's New in Prototype 1.5</title>
<content type="html">
            &lt;p&gt;XML.com just published an article I wrote on &lt;a href=&quot;http://www.xml.com/pub/a/2007/01/24/whats-new-in-prototype-15.html&quot;&gt;What&amp;rsquo;s New In Prototype 1.5&lt;/a&gt;. It outlines the major themes of the new release: drastically improved test coverage, a completely revamped &lt;a href=&quot;http://prototypejs.org/&quot;&gt;website&lt;/a&gt; (now with &lt;a href=&quot;http://prototypejs.org/api&quot;&gt;API docs&lt;/a&gt;!), and oodles of fixes. But the bulk of the article is reference-style, with descriptions and examples for all of the new methods, classes, and features added since 1.4. By and large, that content was extracted from &lt;a href=&quot;http://www.oreilly.com/catalog/prototypeqr/&quot;&gt;Prototype Quick Reference&lt;/a&gt;, which itself was extracted from &lt;a href=&quot;http://www.oreilly.com/catalog/9780596527440/&quot;&gt;Ajax on Rails&lt;/a&gt;. I&amp;rsquo;m grateful to O&amp;rsquo;Reilly for letting me share that content with the community.&lt;/p&gt;


&lt;p&gt;One thing I didn&amp;rsquo;t mention in the article was the impressive degree of community involvement in this release. Prototype has been criticized in the past for having a &amp;ldquo;black box&amp;rdquo; style of development, but I think this release signals a renewed openness in the process. There is now a group of incredibly talented folks helping to shepherd the project, and I&amp;rsquo;m pretty confident that it will keep going strong. I&amp;rsquo;d like to publicly thank everybody who chipped in to this release, so I compiled a list of the top contributors (those with more than one credit in the changelog):&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;49: Sam Stephenson&lt;/li&gt;
 &lt;li&gt;27: Thomas Fuchs&lt;/li&gt;
 &lt;li&gt;10: Tobie Langel&lt;/li&gt;
  &lt;li&gt;9: Mislav Marohnić&lt;/li&gt;
  &lt;li&gt;7: Christophe Porteneuve&lt;/li&gt;
  &lt;li&gt;5: Andrew Dupont&lt;/li&gt;
  &lt;li&gt;4: DHH&lt;/li&gt;
  &lt;li&gt;3: Brandon Aaron and Todd Ross&lt;/li&gt;
  &lt;li&gt;2: Martin Bialasinski, adsmart, and hawk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time time you see one of these guys, you owe them a pint!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2006-12-22:655</id>
    <published>2006-12-22T22:29:00Z</published>
    <updated>2006-12-22T22:33:05Z</updated>
    <link href="http://scottraymond.net/2006/12/22/ajax-on-rails-is-here" rel="alternate" type="text/html"/>
    <title>Ajax on Rails is here</title>
<content type="html">
            &lt;p&gt;Christmas came a few days early for me, as the FedEx man just dropped off &lt;a href=&quot;http://flickr.com/photos/sco/330363964/&quot;&gt;my author's copy&lt;/a&gt; of &lt;em&gt;Ajax on Rails.&lt;/em&gt; It has taken a tremendous amount of work over the last year, so I'm extremely gratified to finally see it in print.&lt;/p&gt;

&lt;p&gt;If you're interested in Rails, Ajax, or you just like books, you can buy mine. It's available from &lt;a href=&quot;http://www.amazon.com/Ajax-Rails-Scott-Raymond/dp/0596527446/&quot;&gt;Amazon&lt;/a&gt;, or from &lt;a href=&quot;http://www.oreilly.com/catalog/9780596527440/&quot;&gt;O'Reilly&lt;/a&gt;, or from any fine bookseller, once they get their shipments. Just ask for the Monkey Book.*&lt;/p&gt;

&lt;p&gt;If you like the &lt;em&gt;idea&lt;/em&gt; of books but not the physical reality of them, you're not out of luck. O'Reilly decided that Chapter 10, a reference to the Prototype JavaScript library, was useful enough to be packaged as a standalone PDF. So even if you're not a Rails user, you might be interested in the &lt;a href=&quot;http://www.oreilly.com/catalog/prototypeqr/&quot;&gt;Prototype Quick Reference&lt;/a&gt;. When Prototype 1.5 is released (soon), we'll release a new edition covering any last-minute changes; but if you buy it now, you'll get the upgrade for free. Chapter 11 (aka Script.aculo.us Quick Reference) will be released in a similar manner soon.&lt;/p&gt;

&lt;p&gt;I owe a huge thanks to everyone who helped make this book&amp;mdash;all of the gifted folks at O'Reilly, my peerless peer reviewers, everyone who has worked on Rails, Prototype, and Scriptaculous, and my friends, parents, and my wife. I'm a lucky guy to be surrounded by such inspiring people, and I'm quite sure I would have given up on this project without your encouragement.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;*Actually, don't do that; they won't know what you mean at all.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/sco/330363964/&quot;&gt;&lt;img src=&quot;http://scottraymond.net/2006/smallaor.jpg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2006-10-03:648</id>
    <published>2006-10-03T02:08:00Z</published>
    <updated>2006-10-03T02:15:13Z</updated>
    <link href="http://scottraymond.net/2006/10/3/jacobs-well" rel="alternate" type="text/html"/>
    <title>A visit to Jacob's Well</title>
<content type="html">
            &lt;p&gt;Just a quick note to point out this article in the current issue of The Christian Century magazine: &lt;a href=&quot;http://www.christiancentury.org/article.lasso?id=2363&quot;&gt;A visit to Jacob's Well&lt;/a&gt;. The author does a good job of portraying what Jacob's Well is about&amp;mdash;and it reminded me of how grateful I am to be part of this community.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2006-10-02:647</id>
    <published>2006-10-02T22:00:00Z</published>
    <updated>2006-10-02T22:06:58Z</updated>
    <link href="http://scottraymond.net/2006/10/2/blinksale-api" rel="alternate" type="text/html"/>
    <title>Introducing the Blinksale API</title>
<content type="html">
            &lt;p&gt;I'm happy to announce that Firewheel just released the &lt;a href=&quot;http://www.blinksale.com/api&quot;&gt;Blinksale API&lt;/a&gt;. This is a project I've been working on for quite a while, and it feels great to release it to the world. I'm excited to see what's done with it. At some point I plan to write up what we learned building this sucker, but for now I just want to get the word out.&lt;/p&gt;

&lt;p&gt;So if you're into this sort of thing, check it out and let me know if there are any questions, problems, or suggestions!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-07-31:646</id>
    <published>2006-07-31T16:45:00Z</published>
    <updated>2006-08-15T18:34:38Z</updated>
    <link href="http://scottraymond.net/2006/7/31/seeking-reviewers-for-ajax-on-rails" rel="alternate" type="text/html"/>
    <title>Seeking Reviewers for Ajax on Rails</title>
<content type="html">
            &lt;p&gt;Progress on my upcoming O&#8217;Reilly book, &lt;a href=&quot;http://www.amazon.com/gp/product/0596527446/&quot;&gt;&lt;em&gt;Ajax on Rails&lt;/em&gt;&lt;/a&gt;, is moving fast. That means it&#8217;s time to bring a few more people into the project, as Tech Reviewers. The idea of a tech review isn&#8217;t to worry about typos or grammar, but to make sure I&#8217;ve covered all of the relevant topics thoroughly and accurately.&lt;/p&gt;

&lt;p&gt;You don&#8217;t need to be an expert on Ajax, Rails, or writing&amp;mdash;just interested in the subject and willing to give constructive criticism. The schedule is getting crunched, so we need feedback within a week or two.&lt;/p&gt;

&lt;p&gt;&amp;lt;strike&gt;Interested? Email me at &lt;a href=&quot;mailto:sco@scottraymond.net&quot;&gt;sco@scottraymond.net&lt;/a&gt;.&amp;lt;/strike&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We&amp;rsquo;ve got our reviewers. Thanks to all those who replied.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-07-20:597</id>
    <published>2006-07-20T19:11:00Z</published>
    <updated>2006-08-15T18:34:34Z</updated>
    <link href="http://scottraymond.net/2006/7/20/refactoring-to-rest" rel="alternate" type="text/html"/>
    <title>Refactoring to REST</title>
<content type="html">
            &lt;p&gt;Inspired largely by &lt;a href=&quot;http://blog.scribestudio.com/articles/2006/07/09/david-heinemeier-hansson-railsconf-2006-keynote-address&quot;&gt;&lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt;&amp;rsquo;s RailsConf keynote&lt;/a&gt;, I recently set about refactoring &lt;a href=&quot;http://www.iconbuffet.com/&quot;&gt;IconBuffet.com&lt;/a&gt;. Specifically, I wanted to embrace the &lt;a href=&quot;http://dev.rubyonrails.org/svn/rails/plugins/simply_restful/&quot;&gt;SimplyRestful&lt;/a&gt; plugin and see how much of the application could be re-cast in terms of &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_State_Transfer#Resources&quot;&gt;resources&lt;/a&gt;, as opposed to &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_State_Transfer#REST_versus_RPC&quot;&gt;&lt;span class=&quot;caps&quot;&gt;RPC&lt;/span&gt;&lt;/a&gt;&amp;mdash;without changing any functionality.&lt;/p&gt;

&lt;p&gt;The process was gradual, but as of today it&amp;rsquo;s basically done, so I thought I&amp;rsquo;d summarize the results. Before refactoring, IconBuffet had ten controllers and seventy-six actions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;about:&lt;/strong&gt; home, index, license, privacy, tos, feed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;account:&lt;/strong&gt; signup, login, authenticate, set_subscription, retrieve_password, index, logout, update, cart, checkout, update_states&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;delivery:&lt;/strong&gt; index, signup, deliver, download, receive&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;products:&lt;/strong&gt; category, product, add_to_cart, remove_from_cart, download
  &lt;li&gt;&lt;strong&gt;admin/categories:&lt;/strong&gt; index, create, update, delete&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;admin/deliveries:&lt;/strong&gt; index, new, create, edit, update, update_sidebar, push, download_file, delete_file, delete_small_preview, delete_large_preview, delete&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;admin/people:&lt;/strong&gt; index, search, set_administrator, new, create, edit, update, delete, push, gift, ungift&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;admin/products:&lt;/strong&gt; dashboard, index, new, create, edit, update, update_sidebar, download_file, delete_file, delete_sample, delete_small_preview, delete_large_preview, delete&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;admin/site:&lt;/strong&gt; index, update, update_sidebar, delete_feature&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;admin/specifications:&lt;/strong&gt; new, create, edit, update, delete&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, without adding or removing any features, IconBuffet has thirteen controllers and fifty-eight actions:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;about:&lt;/strong&gt; home, index, license, privacy, tos&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;cart_items:&lt;/strong&gt; index, create, destroy&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;categories:&lt;/strong&gt; index, create, show, update, destroy&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;deliverables:&lt;/strong&gt; index, new, create, show, edit, update, destroy&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;deliveries:&lt;/strong&gt; index, new, create, show, update&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;orders:&lt;/strong&gt; index, create&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;people:&lt;/strong&gt; index, new, create, show, edit, update, destroy, retrieve_password&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;products:&lt;/strong&gt; index, new, create, show, edit, update, destroy&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;purchases:&lt;/strong&gt; update&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;pushes:&lt;/strong&gt; index, create, show&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;sessions:&lt;/strong&gt; new, create, destroy&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;settings:&lt;/strong&gt; index, update&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;specifications:&lt;/strong&gt; index, new, create, show, edit, update, destroy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, by adding a few controllers, I cut the total number of actions by almost twenty. That&amp;rsquo;s a pretty big deal, because actions are like moving parts in a machine&amp;mdash;the more there are, the more can go wrong. The fact that I could cut almost twenty actions indicates that there was a lot of redundancy hiding beneath the surface. A big part of that redundancy was in having an Admin module, which quickly proved unnecessary. Instead, I just use &lt;code&gt;before_filter&lt;/code&gt;s to protect certain actions.&lt;/p&gt;

&lt;p&gt;Cutting actions is great, but even more significant is that the remaining ones are almost completely uniform. There are seven standard Rails actions: &lt;em&gt;index&lt;/em&gt;, &lt;em&gt;new&lt;/em&gt;, &lt;em&gt;create&lt;/em&gt;, &lt;em&gt;show&lt;/em&gt;, &lt;em&gt;edit&lt;/em&gt;, &lt;em&gt;update&lt;/em&gt;, and &lt;em&gt;destroy&lt;/em&gt;. Everything else&amp;mdash;oddball actions&amp;mdash;are usually a clue that you&amp;rsquo;re doing &lt;span class=&quot;caps&quot;&gt;RPC&lt;/span&gt;. In the old version, there were forty oddball actions; now there are only five (and four of those are essentially static pages in the about controller.) The upshot is that the controllers are very uniform, which makes the entire application conceptually simpler, and thus easier to maintain, test, and extend.&lt;/p&gt;

&lt;p&gt;Perhaps the most dramatic example of that simplification is in the Routes configuration. Take a look at the before and after:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;strong&amp;gt;# Old: 16 lines, giving 8 named routes&amp;lt;/strong&amp;gt;
ActionController::Routing::Routes.draw do |map|

  map.with_options :controller =&amp;gt; 'products' do |m|
    m.product     'products/:slug',          :action =&amp;gt; 'product'
    m.category    'categories/:slug',        :action =&amp;gt; 'category'
    m.download    'products/:slug/download', :action =&amp;gt; 'download'
    m.add         'add/:id',                 :action =&amp;gt; 'add_to_cart'
    m.remove_cart 'remove/:id',              :action =&amp;gt; 'remove_from_cart'
  end

  map.with_options :controller =&amp;gt; 'delivery' do |p|
    m.connect     'delivery',                :action =&amp;gt; 'index'
    m.receive     'delivery/receive/:token', :action =&amp;gt; 'receive'
    m.connect     'delivery/:action',        
    m.delivery    'delivery/:slug/:action',  :action =&amp;gt; 'product'
  end

  map.connect     'admin', :controller =&amp;gt; &quot;admin/products&quot;, :action =&amp;gt; &quot;dashboard&quot; 
  map.home        '', :controller =&amp;gt; &quot;about&quot;, :action =&amp;gt; &quot;home&quot; 
  map.connect     ':controller/:action/:id'

end

&amp;lt;strong&amp;gt;# New: 3 lines, giving 89 named routes&amp;lt;/strong&amp;gt;
ActionController::Routing::Routes.draw do |map|

  map.resources *%w( product category person cart_item
                     order deliverable delivery push 
                     specification session setting )

  map.home '', :controller =&amp;gt; &quot;about&quot;, :action =&amp;gt; &quot;home&quot; 
  map.connect ':controller/:action/:id'

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now &lt;em&gt;that&amp;rsquo;s&lt;/em&gt; the beauty of convention over configuration. Because the actions are uniform, the routes get far more bang for the buck. Count &amp;rsquo;em: &lt;em&gt;eighty-nine&lt;/em&gt; named routes from just three lines of configuration.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco</name>
    </author>
    <id>tag:scottraymond.net,2006-06-23:592</id>
    <published>2006-06-23T14:22:06Z</published>
    <updated>2006-08-15T18:34:33Z</updated>
    <link href="http://scottraymond.net/2006/6/23/minimal-rails" rel="alternate" type="text/html"/>
    <title>Minimal Rails</title>
<content type="html">
            &lt;p&gt;It&amp;rsquo;s been observed that the success of &lt;a href=&quot;http://rubyonrails.com/&quot;&gt;Ruby on Rails&lt;/a&gt; isn&amp;rsquo;t due to any particular technical breakthrough or insight. The framework is basically just a collection of good ideas culled from elsewhere, packaged nicely and explained well, with a heapin&amp;rsquo; helping of hype. One of those good ideas is &lt;a href=&quot;http://c2.com/cgi/wiki?PassiveCodeGeneration&quot;&gt;passive code generators&lt;/a&gt;: tools that spit out application boilerplate for the developer to modify as needed. On the surface, code generators are simply about cutting keystrokes. But there are subtler implications as well: they lower the barrier to entry for new developers, they encourage consistency (both intra- and inter-project), and they create invitations to best practices, like unit testing.&lt;/p&gt;

&lt;p&gt;After installation, code generation is the first thing a new Rails developer experiences: &lt;code&gt;rails myapp&lt;/code&gt;. (Unfortunately, the next step for newcomers is usually &lt;code&gt;script/generate scaffold&lt;/code&gt;, but that&amp;rsquo;s another story.) The generators are a large part of what makes Rails welcoming to first-timers, and pleasant for full-timers. And they cement community conventions, which is a huge benefit&amp;mdash;every Rails app looks the same in terms of directory structure, file names, and configuration format. Learn how one Rails app is organized, and you&amp;rsquo;ve learned how they&amp;rsquo;re all organized.&lt;/p&gt;

&lt;h3&gt;The Downside of Code Generation&lt;/h3&gt;
&lt;p&gt;Bells ring; singers sing; &lt;a href=&quot;http://www.joelonsoftware.com/articles/LeakyAbstractions.html&quot;&gt;abstractions leak&lt;/a&gt;. For many Railsers&amp;mdash;even experienced ones&amp;mdash;generators involve some degree of voodoo. They make it easy to &lt;em&gt;not&lt;/em&gt; understand how everything works. &lt;em&gt;What are all those files? What&amp;rsquo;s actually required, and what&amp;rsquo;s just convention?&lt;/em&gt; The significance isn&amp;rsquo;t just academic. Someday, you&amp;rsquo;ll face a bug that requires understanding the generated code.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s void the warranty, crack the case, shun the scripts, and build a Rails app from scratch. You&amp;rsquo;ll find it&amp;rsquo;s not hard. A minimal working Rails application needs only six directories, five files, and 19 lines of code&amp;mdash;including configuration. Here&amp;rsquo;s how to do it.&lt;/p&gt;

&lt;h3&gt;But First&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ll assume that you&amp;rsquo;ve got Rails installed and working already (if not, see &lt;a href=&quot;http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html&quot;&gt;Curt&amp;rsquo;s introduction&lt;/a&gt;.) I&amp;rsquo;ll also assume MySQL is installed and accessible with the default permissions (username &lt;code&gt;root&lt;/code&gt;; blank password). And we&amp;rsquo;ll use the excellent &lt;a href=&quot;http://mongrel.rubyforge.org/&quot;&gt;Mongrel&lt;/a&gt; web server (&lt;code&gt;gem install mongrel&lt;/code&gt;) to serve the app. The command line examples are for a Unix-like OS, but the ideas transfer directly to Windows. This example will expect a database named &lt;code&gt;myapp&lt;/code&gt;, with one table named &lt;code&gt;people&lt;/code&gt;, with one column named &lt;code&gt;name&lt;/code&gt;. Go ahead and create a row in the table, with your name in it. Ready? Set?&lt;/p&gt;

&lt;h3&gt;Go&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a directory&lt;/strong&gt; for your application: &lt;code&gt;mkdir myapp; cd myapp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create six subdirectories&lt;/strong&gt;: &lt;code&gt;mkdir log public app config app/controllers config/environments&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create the development environment,&lt;/strong&gt; and leave it blank: &lt;code&gt;touch config/environments/development.rb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create your environment&lt;/strong&gt; file, &lt;em&gt;config/environment.rb&lt;/em&gt;, and enter this:

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;require 'rubygems'
require_gem 'rails'
require 'initializer'
RAILS_ROOT = File.join File.dirname(__FILE__), '..'
Rails::Initializer.run&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;These lines pull in the framework (through the RubyGems package manager) and wind everything up. A stock &lt;em&gt;environment.rb&lt;/em&gt; includes much more, providing configuration hooks and code to handle edge cases.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Configure your database&lt;/strong&gt; by creating &lt;em&gt;config/database.yml&lt;/em&gt;:

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;development:
  adapter: mysql
  database: myapp&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Rails will assume reasonable defaults: &lt;code&gt;root&lt;/code&gt; for the username, a blank password, and &lt;code&gt;localhost&lt;/code&gt; for the host.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Set up your routes&lt;/strong&gt; by creating &lt;em&gt;config/routes.rb&lt;/em&gt;:

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;ActionController::Routing::Routes.draw do |map|
  map.connect '', :controller =&amp;gt; 'people'
end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Write your application&lt;/strong&gt; in &lt;em&gt;app/controllers/application.rb&lt;/em&gt;:

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;class Person &amp;lt; ActiveRecord::Base; end

class PeopleController &amp;lt; ActionController::Base
  def index
    @person = Person.find :first
    render :inline =&amp;gt; &quot;Hello, &amp;lt;%= @person.name %&amp;gt;&quot; 
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Notice we don&amp;rsquo;t have an ApplicationController&amp;mdash;it&amp;rsquo;s optional; your controllers can inherit directly from ActionController::Base. And we don&amp;rsquo;t have the models, helpers, or views directories. They aren&amp;rsquo;t needed; models can be defined anywhere, including &lt;em&gt;application.rb&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That&amp;rsquo;s it&amp;mdash;the minimal application, stripped it down to the rails. Moment of truth time: start it up by running &lt;code&gt;mongrel_rails start&lt;/code&gt;, and then point your browser to &lt;em&gt;http://localhost:3000/&lt;/em&gt;. If all is well, you&amp;rsquo;ll see a hyper-minimal Rails app that exercises the whole stack, M, V, and C. Now stop to consider what&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; there: helpers, views, and model files, a bunch of directories (&lt;em&gt;components&lt;/em&gt;, &lt;em&gt;db&lt;/em&gt;, &lt;em&gt;doc&lt;/em&gt;, &lt;em&gt;lib&lt;/em&gt;, &lt;em&gt;script&lt;/em&gt;, and &lt;em&gt;vendor&lt;/em&gt;), dispatchers, Rake tasks, and tests. All of those things are technically optional. They&amp;rsquo;re conventional, convenient, and recommended&amp;mdash;but not essential.&lt;/p&gt;

&lt;h3&gt;Now Forget Everything I Just Told You&lt;/h3&gt;
&lt;p&gt;So is this the real man&amp;rsquo;s way to write Rails? Hell no. Rails&amp;rsquo; generators are there for a reason, and there&amp;rsquo;s no reason to forgo them in your real work. But it&amp;rsquo;s a worthwhile exercise to go without them, at least once. Not only will you appreciate the shortcuts more, but your understanding of the framework will be stronger.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have I overlooked anything else that can be cut? Left out something essential? Let me know!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;P.S. Attending RailsConf this weekend in Chicago? I&amp;rsquo;d love to meet. I&amp;rsquo;ll be speaking at 10am Saturday morning&amp;mdash;please stop by and introduce yourself!&lt;/p&gt;

	&lt;p&gt;&lt;br /&gt;
&lt;p&gt;&lt;img src=&quot;http://scottraymond.net/2006/minimal-rails.jpg&quot; /&gt;&lt;/p&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-06-01:585</id>
    <published>2006-06-01T15:21:00Z</published>
    <updated>2006-08-15T18:34:32Z</updated>
    <link href="http://scottraymond.net/2006/6/1/rails-writ-large" rel="alternate" type="text/html"/>
    <title>Rails Writ Large</title>
<content type="html">
            &lt;p&gt;I&amp;rsquo;m proud to have an article published in the July issue of &lt;a href=&quot;http://www.linuxjournal.com/issue/147&quot;&gt;Linux Journal&lt;/a&gt;, entitled &amp;ldquo;Rails Writ Large&amp;rdquo;. The editors at LJ asked me to summarize the new additions to Rails in 1.1. Of course, there was so &lt;i&gt;much&lt;/i&gt; new that I couldn&amp;rsquo;t possibly mention everything in the space available, but I hit the highlights. I was also able to include a quick overview of Rails for newcomers&amp;mdash;and hopefully just enough sample code to entice them to dig deeper.&lt;/p&gt;

&lt;p&gt;And speaking of digging deeper, the mini-bio at the end of the article reveals something I&amp;rsquo;ve been keeping quiet: I am writing a book for &lt;a href=&quot;http://www.oreilly.com/&quot;&gt;O&amp;rsquo;Reilly&lt;/a&gt; on creating Ajax-powered applications with Rails, to be available later this year. If you have started using Rails or are considering it for Ajax development, this book will have you covered from every angle&amp;mdash;from the nuts and bolts of XMLHttpRequest, through Prototype, Scriptaculous, and &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt;, and up to the higher-level issues of testing, design, and usability. It&amp;rsquo;s been a challenging and rewarding project so far, and I&amp;rsquo;m really looking forward to sharing the result with the world.&lt;/p&gt;

&lt;p&gt;But more on that in the future. For now, if you want to start your collection of the complete works of Scott Raymond, head to your local purveyor of fine magazines and look for &lt;a href=&quot;http://redhanded.hobix.com/images/dhh-jams.jpg&quot; title=&quot;(According to my wife, his &amp;amp;quot;hot, sexy&amp;amp;quot; mug. Maybe this picture will change her mind?)&quot;&gt;&lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt;&amp;rsquo;s mug&lt;/a&gt;.&lt;/p&gt;

	&lt;p&gt;&lt;br /&gt;
&lt;p&gt;&lt;img src=&quot;/2006/linuxjournal.jpg&quot; /&gt;&lt;/p&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-03-28:582</id>
    <published>2006-03-28T05:23:00Z</published>
    <updated>2006-08-15T18:34:32Z</updated>
    <link href="http://scottraymond.net/2006/3/28/rails-1-1-is-here" rel="alternate" type="text/html"/>
    <title>Rails 1.1 is here</title>
<content type="html">
            &lt;p&gt;Just a quick note to mention that Rails 1.1 &lt;a href=&quot;http://dev.rubyonrails.org/changeset/4089&quot;&gt;is real now&lt;/a&gt;, so I&#8217;ve once again updated &lt;a href=&quot;http://scottraymond.net/articles/2006/02/28/rails-1.1&quot;&gt;my article summarizing the changelogs&lt;/a&gt;, and I&#8217;ve added sections for Prototype and Scriptaculous as well.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-03-18:579</id>
    <published>2006-03-18T06:00:00Z</published>
    <updated>2006-08-15T18:34:31Z</updated>
    <link href="http://scottraymond.net/2006/3/18/rails-1-1-update" rel="alternate" type="text/html"/>
    <title>Rails 1.1 update</title>
<content type="html">
            &lt;p&gt;I have updated my last post on the &lt;a href=&quot;http://scottraymond.net/articles/2006/02/28/rails-1.1&quot;&gt;upcoming changes in Rails 1.1&lt;/a&gt; to reflect the last couple weeks of development. The most notable changes center around support for interesting &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; capabilities&#8212;it seems that David has gotten some &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt; religion, which I&#8217;m pleased to see. Several of these new features have already made it into the development branch of &lt;a href=&quot;http://www.firewheeldesign.com/sparkplug/2006/February/blinksale_20.php&quot;&gt;Blinksale 2.0&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The updates to the article are scattered throughout, so if you just want the highlights, here are the keywords to look for:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;pluggable parameter parsers&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;render(:xml =&amp;gt; ...)&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;respond_to&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;render :content_type =&amp;gt; ...&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;to_xml&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;scaffold verification&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;reload!&lt;/code&gt; and &lt;code&gt;app&lt;/code&gt; in the console&lt;/li&gt;
		&lt;li&gt;Rake namespaces&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;test:uncommitted&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;group_by&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;in groups of&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;cascading eager loading&lt;/li&gt;
		&lt;li&gt;&lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; exception notification&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-02-28:479</id>
    <published>2006-02-28T02:50:00Z</published>
    <updated>2006-08-15T18:34:28Z</updated>
    <link href="http://scottraymond.net/2006/2/28/what-s-new-in-rails-1-1" rel="alternate" type="text/html"/>
    <title>What's new in Rails 1.1</title>
<content type="html">
            &lt;p&gt;It&#8217;s been just over two months since the &lt;a href=&quot;http://scottraymond.net/articles/2005/12/13/whatev&quot;&gt;Rails 1.0 milestone&lt;/a&gt;, and the long push of testing and refining that lead up to it. Surely, the contributors have been taking a much-deserved rest in the time since then. &lt;em&gt;Surely?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;In fact, the core team (and over 120 other contributors) haven&#8217;t slowed down one bit, and the next major release of Rails is here. If you&#8217;re running Edge Rails, you already have access to all the latest features, but perhaps a few have missed your radar. So I&#8217;d like to round-up what&#8217;s new since 1.0 (or at least, everything that&#8217;s interesting to me&#8212;I&#8217;ve skipped a ton of bug fixes, performance improvements, environment-specific enhancements, and smaller changes.) Let&#8217;s start with the easier parts.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Railties&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;The &lt;b&gt;new default schema format&lt;/b&gt; is &lt;code&gt;:ruby&lt;/code&gt; instead of &lt;code&gt;:sql&lt;/code&gt;. This wins the award for best changelog comment in 1.1:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;This means that we&#8217;ll assume you want to live in the world of db/schema.rb where the grass is green and the girls are pretty&#8230; Brought to you by the federation of opinionated framework builders!&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;script/process/spinner&lt;/em&gt; is gone. Instead, use the &lt;b&gt;new &lt;code&gt;-r/--repeat&lt;/code&gt; option&lt;/b&gt; to &lt;em&gt;script/process/spawner.&lt;/em&gt;&lt;/li&gt;
		&lt;li&gt;The &lt;b&gt;new &lt;code&gt;-c/--config&lt;/code&gt; option&lt;/b&gt; on &lt;em&gt;script/server&lt;/em&gt; allows you to specify a path to your lighttpd.conf.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Action and fragment caching&lt;/b&gt; is now ready to use out of the box, storing caches in &lt;em&gt;tmp/cache&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;The environment is &lt;b&gt;forced to be &#8220;test&#8221;&lt;/b&gt; when running tests, so that &lt;code&gt;ENV[&quot;RAILS\_ENV&quot;] = &quot;production&quot;&lt;/code&gt; in &lt;em&gt;config/environment.rb&lt;/em&gt; doesn&#8217;t wreak havoc. (I&#8217;ve been bitten by that nasty.)&lt;/li&gt;
		&lt;li&gt;The default &lt;em&gt;index.html&lt;/em&gt; uses Ajax to fetch details about your Rails configuration from a new, omnipresent &lt;b&gt;Rails::InfoController.&lt;/b&gt;&lt;/li&gt;
		&lt;li&gt;A blank &lt;em&gt;public/javascripts/application.js&lt;/em&gt; is now included in newly-generated apps, and it&#8217;s included in &lt;code&gt;javascript\_include\_tag :defaults&lt;/code&gt;. (I&#8217;d love it if the generator also created a blank &lt;em&gt;application.css&lt;/em&gt;, and an &lt;em&gt;app/views/layouts/application.rhtml&lt;/em&gt; with the standard &lt;span class=&quot;caps&quot;&gt;XHTML&lt;/span&gt; boilerplate.)&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;script/console&lt;/em&gt; gets a couple shortcuts: &lt;code&gt;reload!&lt;/code&gt; reloads all models, and &lt;code&gt;app&lt;/code&gt; is an accessor for an instance of Integration::Session. Handy!&lt;/li&gt;
		&lt;li&gt;ActionView helpers are available from the console, which is great for debugging. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;&amp;gt;&amp;gt; puts helper.options_for_select([%w(a 1), %w(b 2), %w(c 3)])
option value=&quot;1&quot;&amp;gt;a&amp;lt;/option&amp;gt;
option value=&quot;2&quot;&amp;gt;b&amp;lt;/option&amp;gt;
option value=&quot;3&quot;&amp;gt;c&amp;lt;/option&amp;gt;
&amp;gt; nil&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Rake tasks now have namespaces, so for example &lt;code&gt;load_fixtures&lt;/code&gt; is now &lt;code&gt;db:fixtures:load&lt;/code&gt; (which you can also use to load a subset of the application&#8217;s fixtures, e.g. &lt;code&gt;rake db:fixtures:load FIXTURES=customers,plans&lt;/code&gt;). All the old task names will still work. Run &lt;code&gt;rake --tasks&lt;/code&gt; to see the new task names.&lt;/li&gt;
		&lt;li&gt;Ruby 1.8.3 is explicitly disallowed, because Rails is incompatible with it. Check your Ruby version before you upgrade!&lt;/li&gt;
		&lt;li&gt;New Rake task &lt;code&gt;test:uncommitted&lt;/code&gt; tests changes since last checkin to Subversion.&lt;/li&gt;
		&lt;li&gt;The dreaded &#8220;white screen of death&#8221; (a blank browser window for certain Rails errors) should now mostly be a thing of the past.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ol&gt;
	&lt;li&gt;ActiveSupport&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;Every object now has a &lt;b&gt;with_options&lt;/b&gt; method, useful for DRYing up multiple calls to methods having shared options. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;ActionController::Routing::Routes.draw do |map|
  # Account routes
  map.with_options(:controller =&amp;gt; 'account') do |account|
    account.home   '',       :action =&amp;gt; 'dashboard'
    account.signup 'signup', :action =&amp;gt; 'new'
    account.logout 'logout', :action =&amp;gt; 'logout'
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Every object now has a a &lt;b&gt;to_json&lt;/b&gt; method, which outputs &lt;a href=&quot;http://www.json.org/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;&lt;/a&gt; strings. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;[1,2,3].to_json =&amp;gt; &quot;[1, 2, 3]&quot; 
&quot;Hello&quot;.to_json =&amp;gt; &quot;\&quot;Hello\&quot;&quot; 
Person.find(:first).to_json =&amp;gt;
   &quot;{\&quot;attributes\&quot;: {\&quot;id\&quot;: \&quot;1\&quot;, \&quot;name\&quot;: \&quot;Scott Raymond\&quot;}}&quot; 
&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;All enumerables get &lt;b&gt;group_by&lt;/b&gt;, to group collections based on the result of some block. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;transcripts.group_by(&#38;:day)&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Arrays now have &lt;b&gt;in&lt;i&gt;_groups&lt;/i&gt;_of&lt;/b&gt; which iterates over an array in groups of a certain size. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;%w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]
[&quot;4&quot;, &quot;5&quot;, &quot;6&quot;]
[&quot;7&quot;, nil, nil]&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Hashes and Arrays now have &lt;b&gt;to_xml&lt;/b&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;New class &lt;b&gt;CachingTools::HashCaching&lt;/b&gt; lets you created nested, autofilling hashes.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Added &lt;b&gt;Fixnum#seconds&lt;/b&gt; for consistency, so you can say &lt;code&gt;5.minutes + 30.seconds&lt;/code&gt; instead of &lt;code&gt;5.minutes + 30&lt;/code&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;New Hash method &lt;b&gt;diff&lt;/b&gt; shows the difference between two hashes.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Logger now has &lt;b&gt;around_&lt;/b&gt;* methods, to make it easy to log before and after messages for a given block. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;logger.around_info(&quot;Start rendering component (#{options.inspect}): &quot;,
  &quot;End of component rendering&quot;) { yield }&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Time has a funny new method, &lt;b&gt;beginning_of_quarter&lt;/b&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;Time.now.beginning_of_quarter =&amp;gt; Sun Jan 01 00:00:00 CST 2006&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;New &lt;b&gt;delegation&lt;/b&gt; support allows multiple delegations at once (unlike &lt;a href=&quot;http://corelib.rubyonrails.org/files/lib/forwardable_rb.html&quot;&gt;Forwardable&lt;/a&gt;). For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Account &amp;lt; ActiveRecord::Base
  has_one :subscription
  delegate :free?, :paying?, :to =&amp;gt; :subscription
  delegate :overdue?, :to =&amp;gt; &quot;subscription.last_payment&quot; 
end
account.free?    # =&amp;gt; account.subscription.free?
account.overdue? # =&amp;gt; account.subscription.last_payment.overdue?&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Proc#bind(object)&lt;/b&gt;: changes a proc or block&#8217;s self by returning a Method bound to the given object. Based on &lt;a href=&quot;http://redhanded.hobix.com/inspect/aBlockCostume.html&quot;&gt;why&#8217;s &#8220;cloaker&#8221; method&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Object#copy&lt;i&gt;_instance&lt;/i&gt;_variables&lt;i&gt;_from(object)&lt;/b&gt;: copies instance variables from one object to another.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Object#extended&lt;/i&gt;_by&lt;/b&gt;: gets an instance&#8217;s included/extended modules.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Object#extend&lt;i&gt;_with&lt;/i&gt;_included&lt;i&gt;_modules&lt;/i&gt;_from(object)&lt;/b&gt;: extends an instance with the modules from another instance.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Now for the fun stuff!&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;ActiveRecord&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;has_many :through&lt;/b&gt;. See &lt;a href=&quot;http://wiki.rubyonrails.com/rails/pages/ThroughAssociations&quot;&gt;this&lt;/a&gt; and &lt;a href=&quot;http://www.matthewman.net/articles/2006/01/06/rails-activerecord-goes-through&quot;&gt;this&lt;/a&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Author &amp;lt; ActiveRecord::Base
  has_many :authorships
  has_many :books, :through =&amp;gt; :authorships
end
class Book &amp;lt; ActiveRecord::Base
  has_many :authorships
  has_many :authors, :through =&amp;gt; :authorships
end
class Authorship &amp;lt; ActiveRecord::Base
  belongs_to :author
  belongs_to :book
end
Author.find(:first).books.find(:all, :include =&amp;gt; :reviews)&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;The :through option can also be used where the intermediate association is a has_many. (This originated in a patch of mine, taken from Blinksale, but it was substantially improved by Rick Olson). For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Firm &amp;lt; ActiveRecord::Base
  has_many :clients
  has_many :invoices, :through =&amp;gt; :clients
end
class Client &amp;lt; ActiveRecord::Base
  belongs_to :firm
  has_many   :invoices
end
class Invoice &amp;lt; ActiveRecord::Base
  belongs_to :client
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Polymorphic Associations&lt;/b&gt;. See &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations&quot;&gt;Understanding Polymorphic Associations&lt;/a&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Address &amp;lt; ActiveRecord::Base
  belongs_to :addressable, :polymorphic =&amp;gt; true
end
class User &amp;lt; ActiveRecord::Base
  has_one :address, :as =&amp;gt; :addressable
end
class Company &amp;lt; ActiveRecord::Base
  has_one :address, :as =&amp;gt; :addressable
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Nested with_scope.&lt;/b&gt; See &lt;a href=&quot;http://habtm.com/articles/2006/02/22/nested-with_scope&quot;&gt;this&lt;/a&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;Developer.with_scope(:find =&amp;gt; { :conditions =&amp;gt; &quot;salary &amp;gt; 10000&quot;, :limit =&amp;gt; 10 }) do
  Developer.find(:all)     # =&amp;gt; SELECT * FROM developers WHERE (salary &amp;gt; 10000) LIMIT 10
  # inner rule is used. (all previous parameters are ignored)
  Developer.with_exclusive_scope(:find =&amp;gt; { :conditions =&amp;gt; &quot;name = 'Jamis'&quot; }) do
    Developer.find(:all)   # =&amp;gt; SELECT * FROM developers WHERE (name = 'Jamis')
  end
  # parameters are merged
  Developer.with_scope(:find =&amp;gt; { :conditions =&amp;gt; &quot;name = 'Jamis'&quot; }) do
    Developer.find(:all)   # =&amp;gt; SELECT * FROM developers WHERE (( salary &amp;gt; 10000 ) AND ( name = 'Jamis' )) LIMIT 10
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Calculations&lt;/b&gt;: calculations and statistics need no longer require custom &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;. See &lt;a href=&quot;http://weblog.techno-weenie.net/2005/10/20/introducing_calculations&quot;&gt;this&lt;/a&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;Person.count
Person.average :age
Person.minimum :age
Person.maximum :age
Person.sum :salary, :group =&amp;gt; :last_name&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Cascading eager loading&lt;/b&gt; allows for queries like &lt;code&gt;Author.find(:all, :include=&amp;gt; { :posts=&amp;gt; :comments })&lt;/code&gt;, which will fetch all authors, their posts, and the comments belonging to those posts in a single query. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;Author.find(:all, :include=&amp;gt;{:posts=&amp;gt;:comments})
Author.find(:all, :include=&amp;gt;[{:posts=&amp;gt;:comments}, :categorizations])
Author.find(:all, :include=&amp;gt;{:posts=&amp;gt;[:comments, :categorizations]})
Company.find(:all, :include=&amp;gt;{:groups=&amp;gt;{:members=&amp;gt;{:favorites}}})&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Option inheritance&lt;/b&gt; for &lt;code&gt;find&lt;/code&gt; calls on &lt;code&gt;has\_and\_belongs\_to\_many&lt;/code&gt; and &lt;code&gt;has\_many&lt;/code&gt; assosociations. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Post
  has_many :recent_comments, :class_name =&amp;gt; &quot;Comment&quot;, :limit =&amp;gt; 10, :include =&amp;gt; :author
end
post.recent_comments.find(:all) # Uses LIMIT 10 and includes authors
post.recent_comments.find(:all, :limit =&amp;gt; nil) # Uses no limit but include authors
post.recent_comments.find(:all, :limit =&amp;gt; nil, :include =&amp;gt; nil) # Uses no limit and doesn't include authors&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;&lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; representations&lt;/b&gt; for records with &lt;b&gt;&lt;code&gt;to_xml&lt;/code&gt;&lt;/b&gt;. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;topic.to_xml
topic.to_xml(:skip_instruct =&amp;gt; true, :skip_attributes =&amp;gt; [ :id, bonus_time, :written_on, replies_count ])
firm.to_xml :include =&amp;gt; [ :account, :clients ]&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Allow &lt;code&gt;validate\_uniqueness\_of&lt;/code&gt; to be &lt;b&gt;scoped by multiple columns.&lt;/b&gt; See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/1559&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;ActiveRecord::Errors now &lt;b&gt;mixes-in Enumerable.&lt;/b&gt;&lt;/li&gt;
		&lt;li&gt;The &lt;code&gt;:exclusively\_dependent&lt;/code&gt; option has been deprecated in favor of &lt;b&gt;&lt;code&gt;:dependent =&amp;gt; :delete_all&lt;/code&gt;.&lt;/b&gt;&lt;/li&gt;
		&lt;li&gt;The &lt;code&gt;.find()&lt;/code&gt; method, and the &lt;code&gt;has\_and\_belongs\_to\_many&lt;/code&gt; and &lt;code&gt;has\_many&lt;/code&gt; associations, now all take &lt;b&gt;&lt;code&gt;:group&lt;/code&gt;, &lt;code&gt;:limit&lt;/code&gt;, &lt;code&gt;:offset&lt;/code&gt;, and &lt;code&gt;:select&lt;/code&gt;&lt;/b&gt; options.&lt;/li&gt;
		&lt;li&gt;Fixtures may be stored in &lt;b&gt;subdirectories of &lt;em&gt;test/fixtures&lt;/em&gt;&lt;/b&gt;&#8212;great for organizing fixtures for &lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Dynamic finders honor &lt;b&gt;additional passed in &lt;code&gt;:conditions&lt;/code&gt;&lt;/b&gt;. See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/3569&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;validates\_length\_of&lt;/code&gt; now &lt;b&gt;works on &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8&lt;/b&gt; strings&#8212;it counts characters instead of bytes.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ol&gt;
	&lt;li&gt;ActionPack&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;&lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; templates&lt;/b&gt;. Big one. For background, see &lt;a href=&quot;http://www.codyfauser.com/articles/2005/11/20/rails-rjs-templates&quot;&gt;Cody&#8217;s explanation&lt;/a&gt; and &lt;a href=&quot;http://scottraymond.net/articles/2005/12/01/real-world-rails-rjs-templates&quot;&gt;my earlier example&lt;/a&gt;. The basic idea: in addition to .rhtml (Ruby &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;) templates, you can create .rjs (Ruby JavaScript) ones. In them, you can write Ruby code that will &lt;em&gt;generate&lt;/em&gt; JavaScript code, which is sent as the result of an Ajax call, and evaluated by the browser. It sounds complicated, but believe me, Ajax development just got a lot easier.

	&lt;p&gt;The &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; templates are passed an &lt;code&gt;page&lt;/code&gt; object that represents the JavaScriptGenerator, which has many tricks up its sleeve:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Pop an &lt;b&gt;alert()&lt;/b&gt; dialog: &lt;code&gt;alert 'Howdy'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Simulate a &lt;b&gt;redirect&lt;/b&gt; with window.location.href: &lt;code&gt;redirect_to&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Calls a &lt;b&gt;JavaScript&lt;/b&gt; function: &lt;code&gt;call&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Assigns&lt;/b&gt; to a JavaScript variable: &lt;code&gt;assign&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Replaces the &lt;b&gt;outerHTML&lt;/b&gt; of an element: &lt;code&gt;replace&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Insert&lt;/b&gt; text: &lt;code&gt;insert\_html :bottom, 'list', '&amp;amp;lt;li&amp;amp;gt;Last item&amp;amp;lt;/li&amp;amp;gt;'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Call an &lt;b&gt;effect&lt;/b&gt;: &lt;code&gt;visual\_effect :highlight, 'list'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Show something&lt;/b&gt;: &lt;code&gt;show 'status-indicator'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Hide stuff&lt;/b&gt;: &lt;code&gt;hide 'status-indicator', 'cancel-link'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Refer&lt;/b&gt; to an element by id: &lt;code&gt;['blank\_slate']&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;['blank\_slate'].show # =&amp;gt; $('blank_slate').show();&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Get elements with &lt;b&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selectors&lt;/b&gt;: &lt;code&gt;select('p')&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;select('p.welcome b').first # =&amp;gt; $$('p.welcome b').first();&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;select('p.welcome b').first.hide # =&amp;gt; $$('p.welcome b').first().hide();&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Insert&lt;/b&gt; some JavaScript: &lt;code&gt;&amp;amp;lt;&amp;amp;lt;&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Make a &lt;b&gt;draggable&lt;/b&gt;: &lt;code&gt;draggable 'product-1'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;drop_receiving 'wastebasket', :url =&amp;gt; { :action =&amp;gt; 'delete' }&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;sortable 'todolist', :url =&amp;gt; { action =&amp;gt; 'change_order' }&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Delay execution&lt;/b&gt;: &lt;code&gt;delay(20) { page.visual_effect :fade, 'notice' }&lt;/code&gt;
  * &lt;b&gt;&lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; exception notification&lt;/b&gt; via &lt;code&gt;alert()&lt;/code&gt; (set &lt;code&gt;config.action_view.debug_rjs = true&lt;/code&gt;)&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Enumerable methods&lt;/b&gt; can be used, and they&#8217;ll generate the equivalent JavaScript code: &lt;code&gt;page.select('#items li').collect('items'){ |element| element.hide }&lt;/code&gt; generates &lt;code&gt;var items = $$('#items li').collect(function(value, index) { return value.hide(); });&lt;/code&gt;&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;In addition to having .rjs files in your views directory, you can also write &lt;b&gt;Inline &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt;.&lt;/b&gt; For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class UserController &amp;lt; ApplicationController
  def refresh
    render :update do |page|
      page.replace_html  'user_list', :partial =&amp;gt; 'user', :collection =&amp;gt; @users
      page.visual_effect :highlight, 'user_list'
    end
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;You can also write &lt;b&gt;&lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; Helpers&lt;/b&gt; that can be called from update blocks. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;module ApplicationHelper
  def update_time
    page.replace_html 'time', Time.now.to_s(:db)
    page.visual_effect :highlight, 'time'
  end
end
class UserController &amp;lt; ApplicationController
  def poll
    render :update { |page| page.update_time }
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;respond_to&lt;/code&gt; lets an action output different formats according to the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; Accept header. In other words, you&#8217;ve got &lt;b&gt;instance &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt; web services.&lt;/b&gt; Blinksale 2.0 already uses this. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class WeblogController &amp;lt; ActionController::Base
  def index
    @posts = Post.find :all
    respond_to do |wants|
      wants.html # using defaults, which will render weblog/index.rhtml
      wants.xml  { render :xml =&amp;gt; @posts.to_xml } # generates XML and sends it with the right MIME type
      wants.js   # renders index.rjs
    end
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Pluggable parameter parsers&lt;/b&gt; make writable &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt; web services a cinch. By default, posts submitted with the application/xml content type is handled by creating a XmlSimple hash with the same name as the root element of the submitted &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;. More handlers can easily be registered like this:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;# Assign a new param parser to a new content type
ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data| 
  node = REXML::Document.new(post) 
 { node.root.name =&amp;gt; node.root }
end
# Assign the default XmlSimple to a new content type
ActionController::Base.param_parsers['application/backpack+xml'] = :xml_simple&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;New form helpers &lt;b&gt;form\_for&lt;/b&gt;, &lt;b&gt;form\_remote\_for&lt;/b&gt;, and &lt;b&gt;fields\_for&lt;/b&gt; make it easier to work with forms for single objects, even if they don&#8217;t reside in instance variables. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;&amp;amp;lt;% form_for :person =&amp;gt; @person, :url =&amp;gt; { :action =&amp;gt; &quot;update&quot; } do |f| %&amp;amp;gt;
  First name: &amp;amp;lt;%= f.text_field :first_name %&amp;amp;gt;
  Last name : &amp;amp;lt;%= f.text_field :last_name %&amp;amp;gt;
  Biography : &amp;amp;lt;%= f.text_area :biography %&amp;amp;gt;
  Admin?    : &amp;amp;lt;%= f.check_box :admin %&amp;amp;gt;
&amp;amp;lt;% end %&amp;amp;gt;
&amp;amp;lt;% form_for :person =&amp;gt; person, :url =&amp;gt; { :action =&amp;gt; &quot;update&quot; } do |person_form| %&amp;amp;gt;
  First name: &amp;amp;lt;%= person_form.text_field :first_name %&amp;amp;gt;
  Last name : &amp;amp;lt;%= person_form.text_field :last_name %&amp;amp;gt;
  &amp;amp;lt;% fields_for :permission =&amp;gt; person.permission do |permission_fields| %&amp;gt;
    Admin?  : &amp;amp;lt;%= permission_fields.check_box :admin %&amp;amp;gt;
  &amp;amp;lt;% end %&amp;amp;gt;
&amp;amp;lt;% end %&amp;amp;gt;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;form_for&lt;/code&gt; and friends can take a &lt;b cite=&quot;builder*&quot;&gt;* option, where you can pass a custom subclass of FormBuilder. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;&amp;amp;lt;% form_for :person, @person, :url =&amp;gt; { :action =&amp;gt; &quot;update&quot; }, :builder =&amp;gt; LabellingFormBuilder do |f| %&amp;amp;gt;
  &amp;amp;lt;%= f.text_field :first_name %&amp;amp;gt;
  &amp;amp;lt;%= f.text_field :last_name %&amp;amp;gt;
&amp;amp;lt;% end %&amp;amp;gt;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;/b&gt;Integration Testing&lt;b&gt;, a new type of test, spans multiple controllers and actions, tying them all together to ensure they work together as expected. It tests more completely than either unit or functional tests do, exercising the entire stack, from the dispatcher to the database. At its simplest, you simply extend IntegrationTest and write your tests using the get/post methods. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;require &quot;#{File.dirname(__FILE__)}/test_helper&quot; 
require &quot;integration_test&quot; 
class ExampleTest &amp;lt; ActionController::IntegrationTest
  fixtures :people
  def test_login
    # get the login page
    get &quot;/login&quot; 
    assert_equal 200, status
    # post the login and follow through to the home page
    post &quot;/login&quot;, :username =&amp;gt; people(:jamis).username,
      :password =&amp;gt; people(:jamis).password
    follow_redirect!
    assert_equal 200, status
    assert_equal &quot;/home&quot;, path
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;p&gt;Integration Tests can also have multiple session instances open per test, and even extend those instances with assertions and methods to create a very &lt;strong&gt;*powerful testing &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt;&lt;/b&gt; that is specific for your application. You can even reference any named routes you happen to have defined. For example (think &lt;a href=&quot;http://campfirenow.com/&quot;&gt;Campfire&lt;/a&gt; here):&lt;/p&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;def test_login_and_speak
  jamis, david = login(:jamis), login(:david)
  room = rooms(:office)
  jamis.enter(room)
  jamis.speak(room, &quot;anybody home?&quot;)
  david.enter(room)
  david.speak(room, &quot;hello!&quot;)
end
private
module CustomAssertions
  def enter(room)
    # reference a named route, for maximum internal consistency!
    get(room_url(:id =&amp;gt; room.id))
    assert(...)
    ...
  end
  def speak(room, message)
    xml_http_request &quot;/say/#{room.id}&quot;, :message =&amp;gt; message
    assert(...)
    ...
  end
end
def login(who)
  open_session do |sess|
    sess.extend(CustomAssertions)
    who = people(who)
    sess.post &quot;/login&quot;, :username =&amp;gt; who.username,
      :password =&amp;gt; who.password
    assert(...)
  end
end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;render(:xml =&amp;gt; xml)&lt;/code&gt; works just like &lt;code&gt;render(:text =&amp;gt; text)&lt;/code&gt;, but sets the content-type to application/xml and the charset to &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Added &lt;code&gt;:content_type&lt;/code&gt; option to &lt;code&gt;render&lt;/code&gt;, so you can change the content type on the fly. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;render :action =&amp;gt; &quot;atom.rxml&quot;, :content_type =&amp;gt; &quot;application/atom+xml&quot;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Scaffolds now use verification,&lt;/b&gt; to prevent non-idempotent GETs.&lt;/li&gt;
		&lt;li&gt;Allow auto-discovery of &lt;b&gt;third party template library&lt;/b&gt; layouts.&lt;/li&gt;
		&lt;li&gt;More robust relative &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; root discovery for &lt;b&gt;&lt;span class=&quot;caps&quot;&gt;SCGI&lt;/span&gt; compatibility.&lt;/b&gt;&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Unused helper files&lt;/b&gt; can be deleted without throwing exceptions.&lt;/li&gt;
		&lt;li&gt;JavaScriptHelper has been split into &lt;b&gt;PrototypeHelper and ScriptaculousHelper.&lt;/b&gt;&lt;/li&gt;
		&lt;li&gt;Introduced &lt;b cite=&quot;selecte&quot;&gt;d option&lt;/b&gt; to the select helper. Allows you to specify a selection other than the current value of object.method. See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/2991&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;The auto_link text helper accepts an optional block to &lt;b&gt;format the link text&lt;/b&gt; for each url and email address. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;auto_link(post.body) { |text| truncate(text, 10) }&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;content\_for&lt;/code&gt; and &lt;code&gt;capture&lt;/code&gt; now work in .rxml (and any non-rhtml template). See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/3287&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;visual\_effect&lt;/code&gt; supports &lt;b&gt;scoped queues&lt;/b&gt;. See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/3530&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;observe\_field&lt;/code&gt; now has an &lt;b cite=&quot;o&quot;&gt;n option&lt;/b&gt; to specify a different callback hook to have the observer trigger on.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;button\_to\_function&lt;/b&gt;&#8212;works just like &lt;code&gt;link\_to\_function&lt;/code&gt;, but uses a button instead of a link.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;link\_to\_function&lt;/code&gt; will now &lt;b&gt;honor existing &lt;code&gt;:onclick&lt;/code&gt; definitions&lt;/b&gt; when adding the function call.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;submit\_tag&lt;/code&gt; now has a &lt;b cite=&quot;disable\_wit&quot;&gt;h option&lt;/b&gt; to change the text of disabled submit buttons.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;visual\_effect&lt;/code&gt; can now &lt;b&gt;toggle visual effects.&lt;/b&gt; See &lt;a href=&quot;http://dev.rubyonrails.org/ticket/3323&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;auto\_complete\_field&lt;/code&gt; now has a &lt;b cite=&quot;selec&quot;&gt;t option&lt;/b&gt; for to only use part of the auto-complete suggestion as the value for insertion.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ol&gt;
	&lt;li&gt;Prototype&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;New &lt;b&gt;Selector class&lt;/b&gt; (and corresponding &lt;code&gt;$$&lt;/code&gt; function) matches elements by &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selector tokens. For example:&lt;/li&gt;
	&lt;/ul&gt;


&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;// Find all &amp;lt;img&amp;gt; elements inside &amp;lt;p&amp;gt; elements with class 
// &quot;summary&quot;, all inside the &amp;lt;div&amp;gt; with id &quot;page&quot;. Hide 
// each matched &amp;lt;img&amp;gt; tag.
$$('div#page p.summary img').each(Element.hide)

// Attributes can be used in selectors as well:
$$('form#foo input[type=text]').each(function(input) {
  input.setStyle({color: 'red'});
});&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

	&lt;ul&gt;
	&lt;li&gt;Element methods are &lt;b&gt;mixed into &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; elements&lt;/b&gt; referenced by &lt;code&gt;$&lt;/code&gt; and &lt;code&gt;$$&lt;/code&gt;, so you can now write &lt;code&gt;$('foo').show()&lt;/code&gt; instead of &lt;code&gt;Element.show('foo')&lt;/code&gt;.&lt;/li&gt;
		&lt;li&gt;Several new methods added to &lt;b&gt;String&lt;/b&gt;: &lt;code&gt;truncate&lt;/code&gt;, &lt;code&gt;gsub&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;scan&lt;/code&gt;, and &lt;code&gt;strip&lt;/code&gt;.&lt;/li&gt;
		&lt;li&gt;Ajax calls set the &lt;b&gt;&lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; Accept&lt;/b&gt; header to &#8216;text/javascript, text/html, application/xml, text/xml */&lt;/strong&gt;&#8217;&#8217; to inform Rails that it prefers &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt;, but will take anything.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Element.replace&lt;/b&gt; is a cross-browser implementation of the &#8220;outerHTML&#8221; property.&lt;/li&gt;
		&lt;li&gt;A &lt;b&gt;Template class&lt;/b&gt; was added for interpolating named keys from an object in a string.&lt;/li&gt;
		&lt;li&gt;New method &lt;b&gt;&lt;code&gt;Element.childOf(element, ancestor)&lt;/code&gt;&lt;/b&gt; returns true when element is a child of ancestor.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ol&gt;
	&lt;li&gt;Scriptaculous&lt;/li&gt;
	&lt;/ol&gt;


	&lt;ul&gt;
	&lt;li&gt;Local/scoped effect queues. Use &#8220;limit&#8221; option to limit the maximum number of effects in a queue.&lt;/li&gt;
		&lt;li&gt;Added &#8220;visualEffect&#8221; method for the Element Mixin, fixed so you can chain multiple calls.&lt;/li&gt;
		&lt;li&gt;Make it possible to scroll window on dragging.&lt;/li&gt;
		&lt;li&gt;Effect.toggle for slide, blind and appear/fade effects.&lt;/li&gt;
		&lt;li&gt;Sortable.sequence can extract the current sequence of a Sortable as an array, and Sortable.setSequence can programmatically reorder a Sortable.&lt;/li&gt;
		&lt;li&gt;Default effects options are globally modifyable with Effect.DefaultOptions.&lt;/li&gt;
		&lt;li&gt;New core effect Effect.Move can do absolute/relative movement.&lt;/li&gt;
		&lt;li&gt;Scroll options are passed through from Sortable to Draggable.&lt;/li&gt;
		&lt;li&gt;Fix &#8220;only&#8221; option on Sortable.create to accept multiple class names.&lt;/li&gt;
		&lt;li&gt;New Ajax.InPlaceCollectionEditor uses a &lt;span class=&quot;caps&quot;&gt;SELECT&lt;/span&gt; element instead of a text field. See test/functional/ajax_inplacecollectioneditor_test.html for usage.&lt;/li&gt;
		&lt;li&gt;In place editor now uses &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;New &#8220;activate&#8221; method to Autocompleter that allows you to trigger the suggestions through other means than user input.&lt;/li&gt;
		&lt;li&gt;New &#8220;select&#8221; option to Autocompleter to optionally use textnodes from elements with a specific &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; class. See test/functional/ajax_autocompleter_test.html for usage.&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2006-01-11:473</id>
    <published>2006-01-11T21:54:00Z</published>
    <updated>2006-08-15T18:34:28Z</updated>
    <link href="http://scottraymond.net/2006/1/11/yours-truly-on-the-rails-podcast" rel="alternate" type="text/html"/>
    <title>Yours truly on the Rails Podcast</title>
<content type="html">
            &lt;p&gt;Just a quick note to mention that I&#8217;m the guest on the latest &lt;a href=&quot;http://podcast.rubyonrails.com/&quot;&gt;Ruby on Rails Podcast&lt;/a&gt;. Here&#8217;s the &lt;a href=&quot;http://paranode.com/~topfunky/audio/2006/Scott-Raymond.mp3&quot;&gt;direct link to the &lt;span class=&quot;caps&quot;&gt;MP3&lt;/span&gt;&lt;/a&gt; (22mb). Thanks for having me, Geoffrey!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2005-12-13:469</id>
    <published>2005-12-13T23:23:00Z</published>
    <updated>2006-08-15T18:34:28Z</updated>
    <link href="http://scottraymond.net/2005/12/13/rails-1-0-what-a-year" rel="alternate" type="text/html"/>
    <title>Rails 1.0 - What a year</title>
<content type="html">
            &lt;p&gt;Congratulations to the &lt;a href=&quot;http://www.rubyonrails.org/core&quot;&gt;Rails core team&lt;/a&gt; on today&#8217;s long-awaited release of 1.0. The &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;new website&lt;/a&gt; is fittingly spare and elegant.&lt;/p&gt;


	&lt;p&gt;The release almost exactly coincides with my one-year anniversary of using Rails, and it&#8217;s been a good year indeed. It&#8217;s quite a thrill to have not one, but two applications that I developed for Firewheel listed on the &lt;a href=&quot;http://www.rubyonrails.org/applications&quot;&gt;showcase page&lt;/a&gt;. Thanks for that honor, and bravo, gents.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://scottraymond.net/">
    <author>
      <name>sco-crap</name>
    </author>
    <id>tag:scottraymond.net,2005-12-01:457</id>
    <published>2005-12-01T00:46:00Z</published>
    <updated>2006-08-15T18:34:28Z</updated>
    <link href="http://scottraymond.net/2005/12/1/real-world-rails-rjs-templates" rel="alternate" type="text/html"/>
    <title>Real-world Rails RJS templates</title>
<content type="html">
            &lt;p&gt;Today Firewheel Design launched the second site that I helped them develop. The first was &lt;a href=&quot;http://blinksale.com/&quot;&gt;Blinksale&lt;/a&gt; (the un-QuickBooks; an invoicing tool I can&#8217;t imagine doing business without). The latest is an overhaul of &lt;a href=&quot;http://iconbuffet.com/&quot;&gt;IconBuffet&lt;/a&gt;, home of their venerable stock icon collections.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.iconbuffet.com/categories/icons&quot;&gt;&lt;img src=&quot;/2005/rjs.gif&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://firewheeldesign.com/&quot;&gt;Firewheel&lt;/a&gt; is what you&#8217;d call a &#8220;dream client.&#8221; They thoroughly &lt;em&gt;get&lt;/em&gt; the web: they care about standards and providing real value to users. They&#8217;re massively talented designers, both in the &#8220;make it pretty&#8221; sense and the more elusive &#8220;make is usable&#8221; sense. And they provide me, as the developer, with everything I need to make a kick-ass web application.&lt;/p&gt;


	&lt;p&gt;In the case of IconBuffet, the designers at Firewheel wanted the shopping cart to be as simple as humanly possible, with instant feedback when an item is added to the cart. Ajax made perfect sense, and Rails makes that a snap. The only catch was that I needed to update three separate elements on the page any time a product was added or removed from the cart. My first solution was to write some Javascript to handle each action. My code looked like this:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;  var Cart = {
    add: function(product_id) {
      Element.addClassName('product_' + product_id, 'incart')
      new Ajax.Request('/account/add_to_cart/' + product_id,
         { method: 'post', onComplete: Cart.refresh })
    },
    remove: function(product_id) {
      Element.removeClassName('product_' + product_id, 'incart')
      new Ajax.Request('/account/remove_from_cart/' + product_id,
         { method: 'post', onComplete: Cart.refresh })
    },
    refresh: function() {
      new Ajax.Updater('cartbox', '/products/cartbox')
      new Ajax.Updater('num_items', '/products/num_items')
    }
  }&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;Calling &lt;code&gt;Cart.add(1)&lt;/code&gt; would add a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; class to a &lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; element, and then send an Ajax request to the controller to add the item to the cart. That request has an onComplete callback to &lt;code&gt;Cart.refresh&lt;/code&gt;, which made two more Ajax calls, to update the status in the sidebar and the header. It worked, but it wasn&#8217;t great: there was a noticable delay between the three changes on screen, which made the whole thing feel very sluggish. Plus, it created a slight &#8220;code smell&#8221; to have the page&#8217;s logic spread out through so many layers.&lt;/p&gt;


	&lt;p&gt;Just then, the Rails developers (notably &lt;a href=&quot;http://vernix.org/marcel/&quot;&gt;Marcel&lt;/a&gt;) dropped a little goodie in my lap: &lt;a href=&quot;http://dev.rubyonrails.org/changeset/3078&quot;&gt;&lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; Templates&lt;/a&gt;. This addition allows you to generate Javascript from Ruby, which can be returned by Ajax calls and evaluated in the page&#8212;making problems like mine a piece of cake.  Since &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; is just a couple weeks old, I suspect that IconBuffet is one of the first public apps in production to use the technique. Here&#8217;s how my code looks now:&lt;/p&gt;


	&lt;p&gt;As usual, I use &lt;code&gt;link_to_remote&lt;/code&gt;, Rails&#8217; standard way to create an Ajaxified link:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;   link_to_remote &quot;Add to Cart&quot;, :url =&amp;gt; { :action =&amp;gt; 'add_to_cart', :id =&amp;gt; product }&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;The controller saves the product id and renders the &lt;code&gt;add_to_cart&lt;/code&gt; view&#8212;but instead of the usual .rhtml or .rxml template, it&#8217;s an .rjs template:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;   page.replace_html 'cartbox', :partial =&amp;gt; 'cart'
   page.replace_html 'num_items', :partial =&amp;gt; 'num_items'
   page.send :record, &quot;Element.addClassName('product_#{@params[:id]}', 'incart')&quot;&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;These three lines accomplish the same thing as the fourteen lines of Javascript above. The first line renders the &#8216;cart&#8217; partial into the &lt;span class=&quot;caps&quot;&gt;DOM&lt;/span&gt; element #cartbox. The second line does the same thing, but for the header. The third line just creates a line of Javascript to add a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; class to an element. The results of the two techniques is the same, but the effect is far nicer now&#8212;the code is more succinct and centralized, and the user experience is significantly smoother.&lt;/p&gt;


	&lt;p&gt;There&#8217;s a whole lot more that&#8217;s possible, but this should whet your appetite. &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; isn&#8217;t yet available in any released version of Rails, so you&#8217;ve got to checkout the trunk from the repository. It&#8217;s quite a testament to the Rails core team that the bleeding-edge trunk is stable enough to build a production application on&#8230; &lt;em&gt;thanks guys!&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
</feed>
