<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>RailsSpace</title>
    <link>http://blog.railsspace.com</link>
    <language>en</language>
    <webMaster>admin@railsspace.com (Michael Hartl and Aurelius Prochazka)</webMaster>
    <copyright>Copyright 2007-2008</copyright>
    <ttl>60</ttl>
    <pubDate>Sun, 10 Feb 2008 22:22:00 GMT</pubDate>
    <description>A Ruby on Rails book blog</description>
    <item>
      <title>"Add comment", R2.0 templates, and respond_to</title>
      <link>http://blog.railsspace.com/past/2008/2/9/20080210000050794402/</link>
      <pubDate>Sat, 09 Feb 2008 23:29:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/2/9/20080210000050794402/</guid>
      <author>raulparolari@gmail.com (Raul Parolari)</author>
      <description>&lt;p&gt;&lt;style type="text/css"&gt; 
  .ul { text-decoration: underline }
&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;Since R2.0 was introduced, several emails pointed out that the &amp;#8216;add_comment&amp;#8217; (to a
blog post) link did not work. They were
correct (there was some confusion in the email threads, as most people still continued to use R1.2.3, where the form was working but with minor glitches; so, completely different
problems got mixed up). &lt;/p&gt;

&lt;p&gt;The reason for the failure with R2.0 was the following; let us glance at the code 
in the controller was:&lt;/p&gt;

&lt;div class="path"&gt;comments_controller.rb (listing 11.9)&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;def new
  @comment = Comment.new 
  respond_to do |format|      
    format.html   # new.rhtml
    format.js     # new.rjs (notice this comment!)
  end 
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Respective templates for the two formats were &lt;em&gt;new.rhtml&lt;/em&gt; and 
&lt;em&gt;new.rjs&lt;/em&gt;; but the new.rjs template was never executed, and its output discarded by
the Ajax client. 
After an ordeal of tests and (somehow foolish) studies of how the responds_to 
method works internally in Rails, we
went back to read DHH&amp;#8217;s note for 2.0, and this section finally caught 
our attention: &lt;/p&gt;

&lt;blockquote&gt;
the &lt;em&gt;format&lt;/em&gt; of the templates has been
separated from its &lt;em&gt;rendering engine&lt;/em&gt;. So the new format for templates 
is &lt;b&gt;action.format.renderer&lt;/b&gt; 
&lt;/blockquote&gt;

&lt;p&gt;
Could that be the reason for our misery? and if so, what are
the &amp;#8216;format&amp;#8217; and the &amp;#8216;renderer&amp;#8217; for our Rjs template? a caritative note in a
thread clarified it: it had to be &lt;em&gt;.js.rjs&lt;/em&gt; (in poetry: the Rjs engine
renders JavaScript format..).

&lt;p&gt;
So, our derelict &lt;em&gt;new.rjs&lt;/em&gt; file was to be born again
as &lt;b&gt;new.js.rjs&lt;/b&gt; (and then.. clicking for the N+1 time the &lt;em&gt;Add a comment&lt;/em&gt; link.. the form suddenly appeared in front of our incredulous eyes!). 
&lt;p&gt;

&lt;p&gt;
All right: given the time spent (the value of N was indeed high) on this affair, let&amp;#8217;s at least learn something more.
&lt;br /&gt;
Extending the example given by DHH with the rjs case, we could 
have this correspondence between an &lt;em&gt;edit&lt;/em&gt; action and its templates:
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;def edit
  respond_to do |format|      
    format.html     # --&gt; edit.html.erb 
    format.csv      # --&gt; edit.csv.erb
    format.js       # --&gt; edit.js.rjs
    format.iphone   # --&gt; edit.iphone.haml 
  end 
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And of course the templates can be changed (with another &amp;#8216;renderer&amp;#8217;) with no
impact on controller logic, which shows the beauty of the design. [Note: &lt;em&gt;new.rhtml&lt;/em&gt; still works.. which may be the reason that our brain
unconsciously assumed that new.js would still work too!].&lt;/p&gt;

&lt;p&gt;Now, a comment on the code itself (read the following only if you are interested
in Ruby, beyond Rails). Since I saw a RESTful controller, I have always asked 
myself this: &lt;em&gt;how in the world the respond_to method works?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Look at the code above: those &amp;#8216;format.xyz&amp;#8217; calls are method calls, that are going to 
be executed one after the other (rails magic or not, this is how Ruby works)! 
but on the other hand we know that the result is like they
were in an implicit &lt;em&gt;case&lt;/em&gt; statement! so which is it? (if
you ventured a timid &amp;#8220;perhaps both statements are true?&amp;#8221;, you are ahead!).
&lt;/p&gt;

&lt;p&gt;A detailed explanation of this intriguing mechanism (that we read while trying
to debug the problem) would take a few pages; I describe instead a summary, taking as example our add_comment action. First, two preliminary observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
a Rails request can express in the Url a :format parameter (eg: ../posts/3.xml), or specify in the HTTP_ACCEPT header a particular Mime Type requested. 
&lt;br /&gt;
In our case, the
&amp;#8220;Add comment&amp;#8221; link requests an Url like &amp;#8220;/blogs/2/posts/3/comments/new&amp;#8221; which
does not have a :format extension; however Rails&amp;#8217; friend Prototype inserts (in 
the client) a helpful &amp;#8220;text/javascript&amp;#8221; in the HTTP_ACCEPT header.
&lt;/li&gt;

&lt;li&gt;
inside the Rails code that we will examine, the &amp;#8220;mime type&amp;#8221; is not just a string or
symbol, but the MIME::Type object which
contains all the synonyms (eg, &amp;#8216;application/javascript&amp;#8217;) along with its short string and version. In what follows, I will allude to the &amp;#8216;mime type&amp;#8217;, for simplicity (but
you know what it is).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All right: fortified by the above, let&amp;#8217;s attack
the respond_to method, following our &amp;#8216;/blogs/2/posts/3/comments/new&amp;#8217; action (invoked
via Ajax from the client), whose code we refresh:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;def new
  @comment = Comment.new 
  respond_to do |format|      
    format.html   # -&gt; new.html.erb
    format.js     # -&gt; new.js.rjs
  end 
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The steps are the following:&lt;/p&gt;

&lt;ol&gt;

&lt;li&gt;
The &lt;em&gt;respond_to&lt;/em&gt; method starts by retrieving an Array of the Mime types for the request. The first value will be &amp;#8216;text/javascript&amp;#8217; (from the HTTP_ACCEPT
header), but Rails includes several other choices (at lower priority). &lt;br /&gt;
The method also sets up (indirectly) an (empty) hash of @responses. It also receives the block contained in
the &amp;#8216;new&amp;#8217; action (in Ruby, this trick is done via a &amp; prefix to the last parameter listed, like &amp;block).
&lt;/li&gt;

&lt;li&gt;
Then it starts executing the block: this means that the first &amp;#8216;format&amp;#8217; call in the block, which is format.html, is executed; this proves what we stated before: those format.xxx statements are indeed executed serially! 
&lt;br /&gt;
But.. how can it work if all of them are executed? well, it all depends on what &amp;#8216;execution&amp;#8217; means, as we will see next. 
&lt;/li&gt;

&lt;li&gt;
Actually the method &amp;#8216;format.html&amp;#8217; (or any format.xxx) does not exist; so Ruby invokes the famous &lt;em&gt;method_missing&lt;/em&gt; which retrieves the suffix (:html in this case) and &lt;em&gt;creates &lt;/em&gt; a Proc object for &amp;#8216;render :action =&gt; @controller.action_name&amp;#8217;, ie. &amp;#8216;render new&amp;#8217;. 
&lt;p&gt;
It also sets (inside this object) 2 variables, &amp;#8216;template_format&amp;#8217; and &amp;#8216;content_type&amp;#8217; to &amp;#8216;html&amp;#8217; to render (when called) the particular template required.
&lt;br /&gt;
The Proc object is assigned to the @responses hash for the :html mime type (key to hash).
&lt;/li&gt;

&lt;li&gt;
The same goes for the next call, &amp;#8216;format.js&amp;#8217;; another Proc object is added to the hash @responses for the mime type for &amp;#8216;js&amp;#8217;.
Similarly, it attaches the 2 variables seen above to remember that it needs to render :js.
&lt;br /&gt; 
[Digression: if you wonder how several callable objects can be built with 
variables that have the same name but different values (and coexist retaining those values until later when called!), good for
you; welcome to &lt;em&gt;closures&lt;/em&gt;].
&lt;/li&gt;

&lt;li&gt;
Now that the list of &amp;#8216;format.xxx&amp;#8217; calls has ran (storing those &amp;#8216;render new&amp;#8217; methods in hash @responses) the respond_to method needs to pick one of them; which one will it choose? (dramatic pause..) 
&lt;p&gt;
Do you remember that in step 1 we built the array @mime_type_priority, and that the first entry listed was the mime type for &amp;#8216;text/javascript&amp;#8217;? well, the method scans the array extracting the mime types looking for a match in the @responses hash; in our case, it finds and calls right away the   
template &amp;#8216;new&amp;#8217; for &amp;#8216;js&amp;#8217;, and extract from hash @responses the method with that mime type: that is our &lt;span style="color:blue"&lt;b&gt;new.js.rjs&lt;/b&gt;&lt;/span&gt;!
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Indeed those format.xxx calls listed in the controller action &lt;span class="ul"&gt;were all executed&lt;/span&gt;, serially: but &lt;em&gt;execution&lt;/em&gt; meant creating &lt;em&gt;dynamic callable objects&lt;/em&gt; (each of which calls a specific template), and then picking up one of them according to a priority list! Ah, Ruby!&lt;/p&gt;</description>
    </item>
    <item>
      <title>RailsSpace will_paginate</title>
      <link>http://blog.railsspace.com/past/2008/1/31/railsspace_will_paginate/</link>
      <pubDate>Thu, 31 Jan 2008 17:48:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/31/railsspace_will_paginate/</guid>
      <author>raulparolari@gmail.com (Raul Parolari)</author>
      <description>&lt;script type="text/javascript"&gt;
function lib_open_win(link_el, size) {
  var url = link_el.href;
  var const_props =    "menubar=yes,toolbar=yes,location=yes,resizable=yes," 
                     + "status=yes,scrollbars=yes";

  var sz = {};
  sz.small  = "width=600,height=400";
  sz.medium = "width=750,height=600";
  sz.large  = "width=850,height=650";

  size = size ? size : "medium";      // default 
  if (! sz[size]) { size = "medium" } // fix unknown size to default

  var props = const_props + "," + sz[size];

  // Do not clutter desktop; reuse window for same destination (approx), i.e. url
  // Note: win name can't have special characters; moreover IE accepts only alphanums. So we keep only alphanums.
  var win_name   = url; 
  win_name       = win_name.replace(/[^\d\w]/g, '');
  var win_handle = window.open(url, win_name, props ); 
  win_handle.focus();  // place window on front

  return false;
} // lib_open_win
&lt;/script&gt;

&lt;p&gt;&lt;style type="text/css"&gt;
li { margin-left: -1.4em; margin-top: 0.5em }
.blue { color: blue }
&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;The old pagination used in Rails 1.2.3 has been removed from the code in 2.0, but it is still supported via the plugin classic_pagination. However, there are good reasons to kiss her goodbye:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
first, a practical one: the classic_pagination plugin exists just for temporary compatibility; there is no guarantee that it will be maintained. 
&lt;/li&gt;
&lt;li&gt;
second, the plugin forces the programmer to jump through some hoops: see listing 11.10 (or in the final version the method &amp;#8216;paginate&amp;#8217; in application.rb), which, depending on the argument class, calls the plugin (&amp;#8216;super&amp;#8217;) or does &amp;#8216;manual pagination&amp;#8217;; the writer&amp;#8217;s comment  (which aptly captures the absurdity of the situation) is: &amp;#8220;Paginate by hand&amp;#8221;.
&lt;/li&gt;
&lt;li&gt;
third, it has issues of performances when the number of pages is large.
&lt;/li&gt;
&lt;li&gt;finally, a design opinion: this code is a bit uncharacteristic for Rails; the class chosen for Pagination is the ActionController, but the logic seems instead more related to ActiveRecord and ActionView (as pagination is a &amp;#8216;presentation&amp;#8217; of &amp;#8216;Model&amp;#8217; instances). The only advantage that I see in having this in the Controller is that the params method is available (while in a Model, it is not); so, a parameter such as &amp;#8216;params[:page]&amp;#8217; does not need to be passed (in a scale from 0 to 10, weight=1 !).
&lt;/li&gt;
&lt;/ul&gt; 

&lt;p&gt;There are several plugins that replace pagination; I examine here one of the most praised, will_paginate.&lt;/p&gt;

&lt;p&gt;Let us start from the good news; give a look at the listing we just mentioned, 11.10 (method &amp;#8216;paginate&amp;#8217; in application.rb): well, it just &lt;em&gt;disappears!&lt;/em&gt; there is simply no need for it. It is remarkable that at the introduction of that method (start of chapter 11.1.4), the book comments:&lt;/p&gt;

&lt;div class="path"&gt;community_controller.rb (listing 11.9)&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;# &lt;em&gt;what we would really like to do is this:&lt;/em&gt;
def search
  if params[:q]
    ..
    @pages, @users = paginate(@users)
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, with will_paginate that wish becomes reality! if the collection on which we want to paginate has already been computed, eg in @users, we can just write:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;@users = @users.paginate(:page =&gt; params[:page], :per_page =&gt; 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And to paginate on a model we could write (example):&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;@specs = Spec.paginate(:page =&gt; curr_page, :per_page =&gt; 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But wait a moment: the old pagination returned &lt;b&gt;two&lt;/b&gt; objects (see above, @pages, @users), one to manage the pagination, the other with the results for the current page; now, we have only &lt;b&gt;one&lt;/b&gt; object, &lt;em&gt;@specs&lt;/em&gt; in the example! &lt;/p&gt;

&lt;p&gt;
The answer is: indeed we have just &lt;b&gt;one&lt;/b&gt; object, and it is a bit &lt;b&gt;&lt;span class="blue"&gt;smarter&lt;/span&gt;&lt;/b&gt;; it knows both the result of the search &lt;em&gt;and&lt;/em&gt; the one for the pagination! (removing the confusion around those 2 objects was such a gift!).
&lt;/p&gt;

&lt;p&gt;All right; let us now proceed methodically and show how the code in chapters 10&amp;amp;11 can be changed. First, delete the old plugin and install will_paginate (see &lt;a href="http://rock.errtheblog.com/will_paginate" onclick="return lib_open_win(this, 'medium')"&gt;http://rock.errtheblog.com/will_paginate&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start recoding a few methods; the new code is:&lt;/p&gt;

&lt;div class="path"&gt;controllers/community_controller.rb, method index:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;def index  
  @title = "Community"
  @letters = ("A".."Z").to_a
  if params[:id] 
    @initial  = params[:id] 
    curr_page = params[:page]
    specs  = Spec.search_on_last_name(@initial)
    users  = specs.collect { |spec| spec.user }
    @users = users.paginate(:page =&gt; curr_page, :per_page =&gt; 10)
    end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here the pagination is done in the last step, on users (not any longer on specs). So, the search method invoked is just a model search method:&lt;/p&gt;

&lt;div class="path"&gt;models/spec.rb:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;# search specs based on last_name initial
def self.search_on_last_name(name_initial)
  find(:all, :conditions =&gt; ["last_name like ?", name_initial + '%'], 
             :order =&gt; "last_name, first_name")
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, the partials which present the paginated users: first, the _user_table.rhtml (or _user_table.html.erb if you use the rails 2.0 naming convention; both are supported in 2.0); I show what changes from the old to the new version:&lt;/p&gt;

&lt;div class="path"&gt;views/_user_table.rhtml; &lt;b&gt;old code&lt;/b&gt;:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  &lt;% if paginated? %&gt;
    &amp;lt;tr&amp;gt;
      &amp;lt;td colspan="4" align="right"&gt;
      Pages: &lt;%= pagination_links(@pages, :params =&gt; params) %&gt;
    &amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
  &lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;div class="path"&gt;views/_user_table.rhtml; &lt;b&gt;new code&lt;/b&gt;:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  &amp;lt;tr&amp;gt;
    &amp;lt;td colspan="4" align="right"&gt;
      &lt;%= will_paginate @users %&gt;
    &amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we have to recode the _result_summary.rhtml file, that displays the total number of results and the ones displayed in the page. Here I did not find really friendly methods (I mean methods that avoid the business of &amp;#8216;offset +- 1&amp;#8217;); so we will pretend that the friendly methods exist, and then we will add them to the plugin:&lt;/p&gt;

&lt;div class="path"&gt;views/_result_table.rhtml:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;&lt;% if @users %&gt;
  &amp;lt;p&amp;gt;
  Found &lt;%= pluralize(@users.total_entries, "match") %&gt;.
  &lt;% if @users.paginated? %&gt;
    Displaying users &lt;%= @users.first_item %&gt;&amp;ndash;&lt;%= @users.last_item %&gt;.
  &lt;% end %&gt;
  &amp;lt;/p&amp;gt;
&lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we add to the plugin the new methods added, by reopening.. ehm, which is the will_paginate class? let&amp;#8217;s ask Ruby! bring up the rails console:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;ruby script/console
&gt;&gt; Spec.paginate(:all, :page =&gt; 1).class
&gt;&gt; WillPaginate::Collection&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All right, so we need to reopen the WillPaginate::Collection class; we have learnt how to reopen a class in a recent post (on Session); thus, under the lib directory we write a file (that must be required) that will do:&lt;/p&gt;

&lt;div class="path"&gt;lib/will_paginate_ext.rb:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;class WillPaginate::Collection 

  def first_item; offset + 1; end

  def last_item ; first_item + length - 1; end

  def paginated?; total_entries &gt; size; end 
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;[Note: in case anyone finds similar methods in will_paginate, let me know and I will edit this post. The point here is just to centralize the treacherous +-1 and &gt;,&gt;= operations].&lt;/p&gt;

&lt;p&gt;All this work pays handsomely when we add the &lt;em&gt;search&lt;/em&gt; for users across spec/faq/user (chapter 11). As mentioned at the beginning, the long and twisted method &amp;#8216;paginate&amp;#8217; (listing 11.10) in application.rb &lt;b&gt;disappears&lt;/b&gt;! we just need to change one call from the community controller in the action &amp;#8216;search&amp;#8217;:&lt;/p&gt;

&lt;div class="path"&gt;views/controllers/community_controller.rb; &lt;b&gt;old code&lt;/b&gt;:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  @pages, @users = paginate(@users)&lt;/code&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;div class="path"&gt;controllers/community_controller.rb;  &lt;b&gt;new code&lt;/b&gt;:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  @users = @users.paginate(:page =&gt; params[:page], :per_page =&gt; 10)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This single call builds the paginated @users, that can be fed to the View search.html.erb (which calls the same partials that we have seen above). With one shot (ie, one line), we have solved the problem; nice! &lt;/p&gt;

&lt;p /&gt;

And, to finish chapter 11, we port the pagination for the &lt;em&gt;A/S/L search&lt;/em&gt;: the old code is:
&lt;div class="path"&gt;views/controllers/community_controller.rb  browse method; &lt;b&gt;old code&lt;/b&gt;:&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  specs = Spec.find_by_asl(params)
  @pages, @users = paginate(specs.collect { |spec| spec.user })
&lt;/code&gt;&lt;/pre&gt;


&lt;div class="path"&gt;And the &lt;b&gt;new code&lt;/b&gt; is:
&lt;br /&gt;
views/controllers/community_controller.rb  browse method&lt;/div&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  specs = Spec.find_by_asl(params)
  users  = specs.collect { |spec| spec.user }
  @users = users.paginate(:page =&gt; params[:page], :per_page =&gt; 10)
&lt;/code&gt;&lt;/pre&gt;

Notice that we could concatenate statements, for example:
&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;  specs  = Spec.find_by_asl(params)
  @users = specs.collect { |spec| spec.user }.paginate(:page =&gt; params[:page], :per_page =&gt; 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is very much in vogue in Ruby/Rails as it is a compact notation, which eliminates  intermediate local variables (and if you really want to impress your friends, you can even concatenate the 3 statements!). 
&lt;/p&gt;

&lt;p&gt;&lt;p&gt;
Personally, I still like lines of code of about 80 characters (instead of 100, or 140 with the 3 lines concatenated; which is not unusual in Rails internal code!). In any case, the important is to understand all these types of notations.&lt;/p&gt;

&lt;p&gt;Last observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
All the code presented above was tested ok (using the web browser, and running the test suite).
&lt;/li&gt;
&lt;li&gt;
RailsSpace uses pagination again later, in chapter 15, for posts in blogs; the modification should be easy, if you have read this post (so, we leave it as an exercise to the motivated reader :-).
&lt;/li&gt;
&lt;li&gt;
Finally: for more on will_paginate, see the brilliant screencast from Ryan Bates at &lt;a href="http://media.railscasts.com/videos/051_will_paginate.mov"
 onclick="return lib_open_win(this, 'large')"&gt; http://media.railscasts.com/videos/051_will_paginate.mov&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Overwriting default thumbnails</title>
      <link>http://blog.railsspace.com/past/2008/1/25/overwriting_default_thumbnails/</link>
      <pubDate>Fri, 25 Jan 2008 02:10:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/25/overwriting_default_thumbnails/</guid>
      <author>michael@michaelhartl.com (Michael Hartl)</author>
      <description>&lt;p&gt;Just a quick note: once you get to Chapter 12 on Avatars, you should add the following validation to the User model:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;class User &lt; ActiveRecord::Base
  .
  .
  .

  def validate
    # Protect against overwriting default thumbnail...
    if %w(default_thumbnail default).include?(screen_name)
      errors.add(:screen_name, "cannot be that, nice try though")
    end
  end
  .
  .
  .
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Without this validation, users called &amp;#8216;default&amp;#8217; and &amp;#8216;default_thumbnail&amp;#8217; can both overwrite the default thumbnail in the avatar image directory.  D&amp;#8217;oh!  Thanks to Rohit Koul for pointing it out.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Reopening classes to improve the Session interface</title>
      <link>http://blog.railsspace.com/past/2008/1/24/reopening_classes_to_improve_the/</link>
      <pubDate>Thu, 24 Jan 2008 20:31:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/24/reopening_classes_to_improve_the/</guid>
      <author>raulparolari@gmail.com (Raul Parolari)</author>
      <description>&lt;p&gt;Chapter 7 of RailsSpace refactors the management of the session login-logout feature, presenting 3 methods:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;# Method calls:                    # Object:                 
user.login!(session)               # User instance
User.logout!(session, cookies)     # User class
logged_in?                         # controller
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This significantly improved the initial version which disseminated in the code accesses to the session internal data structures (although there are still direct accesses to read the user_id, that we will tackle later).&lt;/p&gt;

&lt;p&gt;
However, there is something a bit odd: the &lt;em&gt;object&lt;/em&gt; on which the methods act changes each time: it is an User &lt;em&gt;instance&lt;/em&gt; to log in the user, then the User &lt;em&gt;class&lt;/em&gt; to log him out, and finally it is the &lt;em&gt;controller&lt;/em&gt; (&amp;#8216;self&amp;#8217; is the controller) to verify the log in. Could we have an uniform way to invoke those 3 actions?
&lt;/p&gt;

&lt;p&gt;Looking inside those methods, it is inmediate to realize that the real object on which the methods act is not user, but &lt;em&gt;session&lt;/em&gt;, which belongs to the class CGI::Session (in my machine, file /usr&amp;#8230;ruby/1.8/cgi/session.rb). If we only could add methods in there!
&lt;/p&gt;

&lt;p&gt;But wait: this is Ruby; we can always reopen a class and add functionality! very much like the book did when it reopened the class String to add the beautiful method &lt;em&gt;or_else?&lt;/em&gt; (ch 9). Comforted by that thought, we created a file with our session extension in the lib directory (that we will &amp;#8216;require&amp;#8217; at the top of the application.rb file):
&lt;/p&gt;

&lt;div class="path"&gt;file lib/session_ext&lt;/div&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;class CGI::Session

  def login!(user)
    self[:user_id] = user.id
  end

  def logout!
    self[:user_id] = nil
  end

  def logged_in?
    not self[:user_id].nil?
  end

end  # CGI::Session&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The content of the methods is identical as before (aside from a detail in the logout action regarding the deletion of the long term cookie, that we will perform now in the controller), and the calls are now: &lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;# In class User Controller
  # in login and register actions
  session.login!(@user)       # old: @user.login!(session)

  # in logout action 
  session.logout!             # old: User.logout!(session, ..)
  cookies.delete(:authorization_token)

# In class ApplicationController
  unless session.logged_in?   # old: unless logged_in?
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;[A curious detail: observe how the place of the terms session,login,user exactly reverse in the login! call; of course, as the &amp;#8216;actor&amp;#8217; is now the session]. &lt;/p&gt;

&lt;p&gt;The same modifications have to be done in the tests. The only place where I left &amp;#8216;logged_in?&amp;#8217; is in the layout, as it is friendlier in that context (in the application helper, I made that method call session.logged_in?). Finally, I deleted the methods dealing with session from the User model.
&lt;/p&gt;

&lt;p&gt;We can at this point observe that it would be nice to also centralize all those accesses to the session hash (like &amp;#8216;User.find(session[:user_id]&amp;#8217;) to retrieve the user_id without exposing the session hash. We can of course achieve that adding a method &amp;#8216;user_id&amp;#8217; to our Session extension. 
&lt;br /&gt;
But, at this point, observing that the &amp;#8216;login!&amp;#8217; and &amp;#8216;logout!&amp;#8217; methods are nothing else than getters/setters on the session, we become tempted to simplify things even further:
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;class Session_Invalid_UserId &lt; Exception; end

class CGI::Session

 # returns current user id in session
 def user_id
   self[:user_id]
 end

 # sets session to given user (or nil)
 def user_id=(value)
   self[:user_id] = 
     case value
     when Fixnum: value
     when User:   value.id
     when nil:    value  
     else
       raise Session_Invalid_UserId, "invalid user_id #{value}"
     end
 end 

 # returns true if there is a session user 
 def user_id?
   self[:user_id] != nil
 end

end  # CGI::Session
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The 3 invocations (session.user_id, session.user_id = @user, session.user_id?) can replace not only the calls login!, logout!, logged_in? but also the accesses to retrieve the user id. Notice also that by doing this we can now detect an error when setting the user_id to something else than a number, an user instance, or nil (for logout).&lt;/p&gt;

&lt;p&gt;After having replaced all the strings in the app and test files (using global replaces), we reopened our browser and everything worked ok! Alas, the happiness was short-lived, as the attempt to run the test suite failed!
&lt;/p&gt;

&lt;p&gt;
We discovered that the tests do not use the CGI::Session but rather a simulation of it, called ActionController::TestSession, that it is just an access to a hash called &amp;#8216;data&amp;#8217;. We could then repair the problem, by simply adding in our session_ext file an extension to that class:
&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;code class="ruby"&gt;class ActionController::TestSession

 def user_id; data[:user_id]; end
 def user_id=(value); data[:user_id] = value; end
 def user_id?; data[:user_id] != nil; end

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

&lt;p&gt;And the test suite ran.. fine (phew!). &lt;/p&gt;

&lt;p&gt;Perhaps all the above work seems an unnecessary trouble (disclosure: we certainly shared that thought, when the tests failed miserably and we had not idea why!). However, in large projects it is often useful at a certain point to organize all functionalities in the most apt way (as, for some reason, entropy, or what we programmers call &amp;#8216;disorder/noise&amp;#8217;, has a subtle way to take off exponentially in software systems).
&lt;p&gt;
Using Ruby, this means identifying the Classes and Objects around which to coalesce functionalities. 
&lt;br /&gt;
What this exercise tried to demonstrate is that even when those classes are not under our control (like the unfamiliar CGI::Session and the unexpected TestSession), Ruby offers us the possibility to reopen those classes and extend their capabilities in the best way that fits our design.
&lt;/p&gt; </description>
    </item>
    <item>
      <title>Login action: from 2 user structures (@user, user), to one</title>
      <link>http://blog.railsspace.com/past/2008/1/18/login_action_from_2_user/</link>
      <pubDate>Fri, 18 Jan 2008 00:09:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/18/login_action_from_2_user/</guid>
      <author>raulparolari@gmail.com (Raul Parolari)</author>
      <description>&lt;p&gt;Hi, everybody,&lt;/p&gt;

&lt;p&gt;I am a new blogger for RailsSpace. Two words about me; I am Italian (so forgive the occasional slip-up) and US resident (Bay Area). After years of real-time apps (network mgmt, Snmp), I began a sabbatical into scripting languages; after a furious flirt with Perl, I finally met Ruby (and nothing was ever the same again..). Recently, I began to read RailsSpace, and I was granted the chance to comment some aspects of the code. &lt;/p&gt;

&lt;p&gt;I start discussing the Login action, at its inception, in chapter 6:&lt;/p&gt;

&lt;div class="path"&gt;Listing 6.8, user_controller.rb&lt;/div&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;
def login
  if request.post? and params(:user)
    @user = User.new(params[:user])
    user = User.find_by_screen_name_and_password(@user.screen_name,
                                                 @user.password)
    if user
      session[:user_id] = user.id
      # flash and redirect
    else
      @user.password = nil
      # flash
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The weak point is this juggling between the &lt;em&gt;@user&lt;/em&gt; (the user received from the form) and &lt;em&gt;user&lt;/em&gt; (the one from the database) structures at every statement. This usage only intensifies in the next chapters as the method becomes progressively more complex. Could we have only 1 structure? Yes, if we collect the user credentials from params:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;
def login
  if request.post? and params(:user)
    screen_name = params[:user][:screen_name]
    password    = params[:user][:password]
    @user = User.find_by_screen_name_and_password(screen_name, password)
    if @user
      session[:user_id] = @user.id
      # flash and redirect
    else
      # bad credentials: return data rcvd, but wout password
      @user = User.new(params[:user])
      @user.password = nil
      # flash
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that we now need to create the user in the &lt;em&gt;else&lt;/em&gt; branch; but the benefit is that there is only 1 structure across the whole method (which, as said, will become quite complex later). And the method is more efficient, as (in the succesful case) we call only once ActiveRecord to build the user.&lt;/p&gt;

&lt;p&gt;Ah, some may say, we do have only 1 structure, but we now access a &lt;em&gt;nested hash!&lt;/em&gt;: is this what you call &lt;em&gt;simplification?&lt;/em&gt;..&lt;/p&gt;

&lt;p&gt;Answer: we can hide the access to the data in a method; it will be generic for any object and any nr of attributes; so the usage will be:&lt;/p&gt;

&lt;pre  class="code"&gt;&lt;code class="ruby"&gt;name, pwd = params_for(:user, :screen_name, :password)
&lt;/code&gt;&lt;/pre&gt;

&lt;div class="path"&gt;We place the method in application_controller.rb &lt;/div&gt;

&lt;pre  class="code"&gt;&lt;code class="ruby"&gt;
# retrieves named params from object
def params_for(object, *names)
  obj_hash = params[object.to_sym]
  return [ ] unless obj_hash

  names.inject([]) { |arr, name| arr &lt;&lt; obj_hash[name.to_sym] }
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This method iterates across the array of names received, extracting the values from the nested hash, and feeding the result array (&lt;em&gt;inject&lt;/em&gt; is a cute way to iterate accumulating a result, without creating extra local variables; very idiomatic inside Rails code).&lt;/p&gt;

&lt;p&gt;All right; so the login looks like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;
def login
 if request.post? and params(:user)
   name, pwd = params_for(:user, :screen_name, :password)
   @user = User.find_by_screen_name_and_password(name, pwd)
   # all the rest of the logic is as above
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the resulting method uses only 1 user structure, and the extraction of parameters is friendly enough. As the method complexity escalates in following chapters (&amp;#8216;remember_me&amp;#8217;, cookies, etc), the programmer can concentrate on the features (without worrying about which structure to access at each statement).&lt;/p&gt;</description>
    </item>
    <item>
      <title>RailsSpace blog code security flaw</title>
      <link>http://blog.railsspace.com/past/2008/1/16/railsspace_blog_code_security_flaw/</link>
      <pubDate>Wed, 16 Jan 2008 18:42:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/16/railsspace_blog_code_security_flaw/</guid>
      <author>michael@michaelhartl.com (Michael Hartl)</author>
      <description>&lt;p&gt;I&amp;#8217;d like to thank Fulvio Cusumano for pointing out a significant security problem in the RailsSpace blog code.  He writes:&lt;/p&gt;

&lt;blockquote&gt;
I&amp;#8217;ve created an account on http://www.railsspace.com/ and my Username is &amp;#8220;fulvio&amp;#8221;.

I am User ID 589.

The following will not work, because I am not user 2. This is correct functionality because it tells me that it isn&amp;#8217;t my blog.

 http://www.railsspace.com/blogs/2/posts/1;edit

The actual security flaw I&amp;#8217;ve found is that I don&amp;#8217;t have a Post of ID #1 however if I access the following URL I can edit/update that post when I shouldn&amp;#8217;t be able too!

 http://www.railsspace.com/blogs/589/posts/1;edit (589 is obviously me, but I don&amp;#8217;t have a post of 1, however it DOES exist within your railsspace database).
 &lt;/blockquote&gt;

&lt;p&gt;This has now been fixed on the site, and in the RailsSpace zip files.  The errata and code listings have also been updated to reflect the fix.&lt;/p&gt;

&lt;p&gt;Here are the changes to make.  First update the Posts fixture so that &lt;tt&gt;blog_id&lt;/tt&gt; of the second post doesn&amp;#8217;t match the blog of the test user:&lt;/p&gt;

&lt;div class="path"&gt;test/fixtures/posts.yml&lt;/div&gt;

&lt;pre class="code"&gt;one:
  id: 1
  blog_id: 1
  title: MyString
  body: MyText
  created_at: 2007-01-16 15:34:32
  updated_at: 2007-01-16 15:34:32

two:
  id: 2
  blog_id: 2
  title: MyString
  body: MyText
  created_at: 2007-01-16 15:34:32
  updated_at: 2007-01-16 15:34:32&lt;/pre&gt;

&lt;p&gt;Then test the behavior we want:&lt;/p&gt;

&lt;div class="path"&gt;test/functional/posts_controller_test.rb&lt;/div&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;class PostsControllerTest &lt; Test::Unit::TestCase
  fixtures :posts, :blogs, :users
  .
  .
  .
  def test_post_blog_mismatch
    wrong_post = posts(:two)  # Post exists, but belongs to wrong blog.
    get :edit, :id =&gt; wrong_post, :blog_id =&gt; @post.blog
    assert_response :redirect
    assert_redirected_to hub_url
    assert_equal "That isn't your blog post!", flash[:notice]
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, get the test to pass by putting in a new before_filter to make sure that &lt;tt&gt;post.blog&lt;/tt&gt; and &lt;tt&gt;@blog&lt;/tt&gt; agree:&lt;/p&gt;

&lt;div class="path"&gt;app/controllers/posts_controller.rb&lt;/div&gt;

&lt;pre class="code"&gt;&lt;code class="ruby"&gt;class PostsController &lt; ApplicationController
  helper :profile, :avatar
  before_filter :protect, :protect_blog
  before_filter :protect_post, :only =&gt; [:show, :edit, :update, :destroy]
  .
  .
  .
  private

  # Ensure that user is blog owner, and create @blog.
  def protect_blog
    @blog = Blog.find(params[:blog_id])
    user = User.find(session[:user_id])
    unless @blog.user == user
      flash[:notice] = "That isn't your blog!"
      redirect_to hub_url
      return false
    end
  end

  def protect_post
    post = Post.find(params[:id])    
    unless post.blog == @blog
      flash[:notice] = "That isn't your blog post!"
      redirect_to hub_url
      return false
    end
  end
end&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>&lt;em&gt;RailsSpace&lt;/em&gt; author update, and thanks</title>
      <link>http://blog.railsspace.com/past/2008/1/11/railsspace_author_update_and_thanks/</link>
      <pubDate>Fri, 11 Jan 2008 06:57:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2008/1/11/railsspace_author_update_and_thanks/</guid>
      <author>admin@railsspace.com (Michael Hartl &amp; Aurelius Prochazka)</author>
      <description>&lt;p&gt;We wanted to give you all an update on our status.   We are both
currently working full-time on new startups, and due to the many
demands on our time we won&amp;#8217;t generally be available for answering
questions about the book or the site.  We hope you continue to find
the RailsSpace Google group useful, and would like to thank the
readers who continue to contribute.  We also appreciate the readers who have
taken the time to point out (in the comments to the &lt;a href="http://blog.railsspace.com/past/2007/12/13/railsspace_now_rails_20_compatible/"&gt;Rails 2.0
compatibility post&lt;/a&gt;)
some of the subtler changes introduced by Rails 2.0.&lt;/p&gt;

&lt;p&gt;We put in long hours writing this book, and it wasn&amp;#8217;t easy, but we
have been gratified that the response has been so positive.  We&amp;#8217;d like
to thank you all for being part of it.  Good luck, and happy Railsing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>RailsSpace video tutorial</title>
      <link>http://blog.railsspace.com/past/2007/12/18/railsspace_video_tutorial/</link>
      <pubDate>Tue, 18 Dec 2007 20:44:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2007/12/18/railsspace_video_tutorial/</guid>
      <author>michael@michaelhartl.com (Michael Hartl)</author>
      <description>&lt;p&gt;I&amp;#8217;d like to congratulate my coauthor &lt;a href="http://aure.com"&gt;Aurelius Prochazka&lt;/a&gt; for the &lt;a href="http://safari.oreilly.com/9780321533890"&gt;RailsSpace Ruby on Rails Tutorial video&lt;/a&gt;, which has been the #1 seller on &lt;a href="http://safari.oreilly.com/video"&gt;the video section of Safari Books Online&lt;/a&gt; for the past couple weeks.&lt;/p&gt;

&lt;p&gt;By the way, as noted in the &lt;a href="http://blog.railsspace.com/past/2007/12/13/railsspace_now_rails_20_compatible/#c74"&gt;comment to the previous blog post&lt;/a&gt;, the video follows the book closely, so &lt;a href="http://blog.railsspace.com/past/2007/12/13/railsspace_now_rails_20_compatible/"&gt;the same Rails 2.0 notes apply&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also note that the &lt;a href="http://safari.oreilly.com/9780321533890"&gt;videos for Chapters 1, 2, 5, and 6 are all free&lt;/a&gt;, so be sure to check &amp;#8216;em out!&lt;/p&gt;</description>
    </item>
    <item>
      <title>&lt;em&gt;RailsSpace&lt;/em&gt; is now Rails 2.0 compatible!</title>
      <link>http://blog.railsspace.com/past/2007/12/13/railsspace_now_rails_20_compatible/</link>
      <pubDate>Thu, 13 Dec 2007 04:08:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2007/12/13/railsspace_now_rails_20_compatible/</guid>
      <author>michael@michaelhartl.com (Michael Hartl)</author>
      <description>&lt;p&gt;&lt;em&gt;RailsSpace&lt;/em&gt; is now compatible with Rails 2.0, with the following changes:&lt;/p&gt;

&lt;ul&gt;

  &lt;li&gt;In Chapter 2, p. 16, instead of 

&lt;pre class="terminal"&gt;&gt; rails rails_space&lt;/pre&gt;

you should use 

&lt;pre class="terminal"&gt;&gt; rails -d mysql rails_space&lt;/pre&gt;

Another possibility is to edit &lt;tt&gt;config/database.yml&lt;/tt&gt; to make sure all the adapters are &lt;tt&gt;mysql&lt;/tt&gt;.

(This is necessary because Rails 2.0.2 changed the default database from MySQL to SQLite3.)
  &lt;/li&gt;

  &lt;li&gt;
    Rails 2.0 uses new filename extensions, such as .html.erb instead of .rhtml.
  &lt;/li&gt;

  &lt;li&gt;In Chapter 10 (Community), you need to install &amp;#8220;classic pagination&amp;#8221; using 

&lt;pre class="terminal"&gt;
&gt; script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;In Chapter 13 (Email), p. 390, change 
    &lt;pre class="code"&gt;&lt;code class="ruby"&gt;server_settings&lt;/code&gt;&lt;/pre&gt; to &lt;pre class="code"&gt;&lt;code class="ruby"&gt;smtp_settings&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

  &lt;li&gt;In Chapter 15, replace &lt;tt&gt;scaffold_resource&lt;/tt&gt;
with just &lt;tt&gt;scaffold&lt;/tt&gt;&lt;/li&gt;  

  &lt;li&gt;In the RESTful routes of Chapters 15 and 16, instead of things like &lt;pre class="code"&gt;&lt;code class="ruby"&gt;edit_post_path(@blog)&lt;/code&gt;&lt;/pre&gt; and &lt;pre class="code"&gt;&lt;code class="ruby"&gt;comments_path(@blog, @post)&lt;/code&gt;&lt;/pre&gt; you need to write &lt;pre class="code"&gt;&lt;code class="ruby"&gt;edit_blog_post_path(@blog)&lt;/code&gt;&lt;/pre&gt; and &lt;pre class="code"&gt;&lt;code class="ruby"&gt;blog_post_comments_path(@blog, @post)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A zip file of the Rails 2.0 compatible RailsSpace code is available for download from the &lt;a href="http://railsspace.com/book"&gt;&lt;em&gt;RailsSpace&lt;/em&gt; book resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;UPDATE: It&amp;#8217;s also worth noting that the RESTful URLs have changed a bit in Rails 2.0.  In particular, the semicolon notation covered in Section 15.1.3 of &lt;a href="http://railsspace.com/15_restful_blogs/Ch15.pdf"&gt;Chapter 15&lt;/a&gt; has been changed to a regular slash.  The arguments we made there that you need something &lt;em&gt;other&lt;/em&gt; than a slash to avoid ambiguity still hold; the Rails designers evidently decided that eliminating the weirdness of the semicolon was worth introducing a little ambiguity.&lt;/p&gt;

&lt;p&gt;UPDATE 2: There are miscellaneous additional small differences introduced by Rails 2.0, as noted in the comments.  Thanks to those who have taken the time to make note of them&amp;#8212;we appreciate it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Railscasts</title>
      <link>http://blog.railsspace.com/past/2007/11/12/railscasts/</link>
      <pubDate>Mon, 12 Nov 2007 19:07:00 GMT</pubDate>
      <guid>http://blog.railsspace.com/past/2007/11/12/railscasts/</guid>
      <author>michael@michaelhartl.com (Michael Hartl)</author>
      <description>&lt;p&gt;I just wanted to give a hearty recommendation to &lt;a href="http://railscasts.com/"&gt;Railscasts&lt;/a&gt; by Ryan Bates.  They&amp;#8217;re bite-size Rails screencasts, nicely produced and well thought-out.  See especially the &lt;a href="http://railscasts.com/episodes;archive"&gt;Railscasts episode archive&lt;/a&gt;, which lists all the Railscasts in chronological order; they are all worth watching, and even intermediate to advanced Rails programmers will learn something from most episodes.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
