<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/views/feeds/_feed.html.erb</filename>
    </added>
    <added>
      <filename>app/views/feeds/show.html.erb</filename>
    </added>
    <added>
      <filename>public/images/spinner.gif</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -5,17 +5,29 @@ class FeedsController &lt; ActionController::Base
     @feeds = Feed.find(:all, :include =&gt; :posts)
   end
 
+  def show
+    @feed = Feed.find(params[:id])
+    if since = request.headers['If-Modified-Since']
+      if @feed.updated_at &gt; Time.parse(since)
+        render :partial =&gt; 'feed', :locals =&gt; { :feed =&gt; @feed }
+      else
+        head 204, 'Cache-Control' =&gt; 'max-age=1'
+      end
+    end
+  end
+
   def create
     feed = Feed.create! :url =&gt; params[:url]
     redirect_to :action =&gt; :index
   end
 
   def refresh
-    if params[:id]
-      Feed.find(params[:id]).fetch
-    else
-      Feed.fetch_all
-    end
-    redirect_to :action =&gt; :index
+    Feed.find(params[:id]).fetch
+    head :ok
+  end
+
+  def refresh_all
+    Feed.fetch_all
+    head :ok
   end
 end</diff>
      <filename>app/controllers/feeds_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ class Feed &lt; ActiveRecord::Base
       self.updated_at = Time.now
       save!
 
-      feed.items.each do |item|
+      feed.items.slice(0, 3).each do |item|
         unless posts.find_by_url(item.link)
           posts.create! :title =&gt; item.title, :url =&gt; item.link
         end</diff>
      <filename>app/models/feed.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,21 +9,9 @@
 &lt;/form&gt;
 
 &lt;% unless @feeds.empty? %&gt;
-  &lt;div class=&quot;refresh_all&quot;&gt;&lt;%= link_to &quot;refresh all&quot;, :action =&gt; 'refresh' %&gt;&lt;/div&gt;
+  &lt;div class=&quot;refresh_all&quot;&gt;&lt;%= link_to_function &quot;refresh all&quot;, 'refresh_all()' %&gt;&lt;/div&gt;
 &lt;% end %&gt;
 
 &lt;% @feeds.each do |feed| %&gt;
-  &lt;div class=&quot;feed&quot;&gt;
-    &lt;div class=&quot;header&quot;&gt;
-      &lt;div class=&quot;title&quot;&gt;&lt;%= feed.title %&gt;&lt;/div&gt;
-      &lt;span class=&quot;last_updated&quot;&gt;&lt;%= time_ago_in_words(feed.updated_at) %&gt; ago&lt;/span&gt;
-      &lt;span class=&quot;refresh&quot;&gt;| &lt;%= link_to &quot;refresh&quot;, :action =&gt; 'refresh', :id =&gt; feed.id %&gt;&lt;/span&gt;
-    &lt;/div&gt;
-
-    &lt;div class=&quot;posts&quot;&gt;
-      &lt;% feed.posts.each do |post| %&gt;
-        &lt;div&gt;&lt;%= link_to post.title, post.url %&gt;&lt;/div&gt;
-      &lt;% end %&gt;
-    &lt;/div&gt;
-  &lt;/div&gt;
+  &lt;%= render :partial =&gt; 'feed', :locals =&gt; { :feed =&gt; feed } %&gt;
 &lt;% end %&gt;</diff>
      <filename>app/views/feeds/index.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,8 @@
   &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
   &lt;title&gt;Queueing Feed Reader&lt;/title&gt;
   &lt;%= stylesheet_link_tag 'main' %&gt;
+  &lt;%= javascript_include_tag 'prototype' %&gt;
+  &lt;%= javascript_include_tag 'application' %&gt;
 &lt;/head&gt;
 &lt;body&gt;
   &lt;%= yield %&gt;</diff>
      <filename>app/views/layouts/application.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 ActionController::Routing::Routes.draw do |map|
-  map.resource :feeds
+  map.connect '/feeds/refresh_all', :controller =&gt; 'feeds', :action =&gt; 'refresh_all'
+  map.resources :feeds
 
   map.root :controller =&gt; 'feeds'
 </diff>
      <filename>config/routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,2 +1,35 @@
-// Place your application-specific JavaScript functions and classes here
-// This file is automatically included by javascript_include_tag :defaults
+function refresh_feed(link) {
+  new Ajax.Request('/feeds/refresh/' + link.getAttribute('feed_id'), { method: 'get' })
+  spin_and_wait(link)
+}
+
+function refresh_all() {
+  new Ajax.Request('/feeds/refresh_all', { method: 'get' })
+  $$('.feed .refresh a').each(function(link) {
+    spin_and_wait(link)
+  })
+}
+
+function spin_and_wait(link) {
+  link.addClassName('refreshing')
+  poll_for_update(link.getAttribute('feed_id'), link.getAttribute('last_modified'), link)
+}
+
+function poll_for_update(feed_id, last_modified, link) {
+  setTimeout(function() {
+    new Ajax.Request('/feeds/' + feed_id, {
+      method: 'get',
+      requestHeaders: { 'If-Modified-Since': last_modified },
+      onComplete: function(transport) {
+        if (transport.status == 204) {
+          poll_for_update(feed_id, last_modified, link)
+        } else if (transport.status == 200) {
+          $('feed_' + feed_id).innerHTML = transport.responseText
+        } else {
+          link.innerHTML = 'error'
+        }
+      }
+    }) },
+    1000
+  )
+}</diff>
      <filename>public/javascripts/application.js</filename>
    </modified>
    <modified>
      <diff>@@ -7,8 +7,19 @@
   font-weight: bold;
   padding-right: 2em;
 }
-.feed .header .last_updated,
-.feed .header .refresh {
+.feed .header .subtitle {
   font-size: 90%;
   color: #555;
 }
+
+.refreshing {
+  color: transparent;
+  background: url(/images/spinner.gif) no-repeat;
+}
+.refreshing a {
+  color: transparent;
+  border: 0;
+}
+.refreshing img {
+  outline: none;  /* disable mozilla's dotted box around link */
+}</diff>
      <filename>public/stylesheets/main.css</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 module Delayed
   class Worker
-    SLEEP = 5
+    SLEEP = 1
 
     cattr_accessor :logger
     self.logger = if defined?(Merb::Logger)</diff>
      <filename>vendor/plugins/delayed_job/lib/delayed/worker.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e7db3f437994d7ba68ae7170be4e15a1dc9ddff7</id>
    </parent>
  </parents>
  <author>
    <name>Adam Wiggins</name>
    <email>adam@heroku.com</email>
  </author>
  <url>http://github.com/adamwiggins/qfeedreader/commit/60f2c12fea0786553c43868ebd966ae73e4e2837</url>
  <id>60f2c12fea0786553c43868ebd966ae73e4e2837</id>
  <committed-date>2009-04-14T12:46:54-07:00</committed-date>
  <authored-date>2009-04-12T14:31:49-07:00</authored-date>
  <message>refresh shows a spinner and uses ajax poll with If-Modified-Since</message>
  <tree>675422d82e0b6bac7c7d6fb60d240bfc63f2e3b7</tree>
  <committer>
    <name>Adam Wiggins</name>
    <email>adam@heroku.com</email>
  </committer>
</commit>
