<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns="http://purl.org/rss/1.0/">

<channel rdf:about="http://www.stephensykes.com/blog.html">
    <title>Ruby, Rails and Tech</title>
<link>http://www.stephensykes.com/blog.html</link>
    <description>Stephen muses about any tech that takes his fancy relying on his home-brew blogging software to do the right thing</description>
    <dc:language>en</dc:language>
    <dc:creator>Stephen Sykes</dc:creator>
    <dc:date>2003-12-22T05:16:01+00:00</dc:date>
    <admin:errorReportsTo rdf:resource="mailto:blog.9.sts@xoxy.net"/>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>
    <items>
    <rdf:Seq>
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?158" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?157" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?156" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?155" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?154" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?153" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?152" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?151" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?150" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?149" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?148" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?147" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?146" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?145" />
<rdf:li rdf:resource="http://www.stephensykes.com/blog_perm.html?144" />
    </rdf:Seq>
    </items>
  </channel>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?158" >
<title>This blog has moved</title>
<description>&lt;a href=&quot;http://pennysmalls.com&quot;&gt;My all new blog&lt;/a&gt;: New blog software from &lt;a href=&quot;http://wordpress.org/&quot;&gt;Wordpress&lt;/a&gt;, and a new domain name &lt;a href=&quot;http://pennysmalls.com&quot;&gt;pennysmalls.com&lt;/a&gt;....</description>
<content:encoded><![CDATA[<p><a href="http://pennysmalls.com">My all new blog</a>: New blog software from <a href="http://wordpress.org/">Wordpress</a>, and a new domain name <a href="http://pennysmalls.com">pennysmalls.com</a>.
<p>I gave the blog a new domain all of its own as it's focus is mostly rails and associated tech, and not much to do with my family and personal stuff.
<p>The RSS feed is <a href="http://pennysmalls.com/feed/">here</a>.
<p>Yes, the layout is dull, I'll get to it.
<p>Most of the recent posts are already there, I'll keep this blog around as an archive of the older stuff.
</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?158</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-20T19:55:09+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?157" >
<title>Adding an Expires header with apache for Rails</title>
<description>We have a problem - we really do.  Each time a user requests a page they have to make 50 http requests just to get back a &quot;Not modified&quot; message from the web server.  Their browser is asking about eve...</description>
<content:encoded><![CDATA[<p>We have a problem - we really do.  Each time a user requests a page they have to make 50 http requests just to get back a "Not modified" message from the web server.  Their browser is asking about every little image and css file and so on.  Every one on the page.  Those messages are small, but they add up.  And as we know, "make fewer HTTP requests" is <a href="http://www.oreillynet.com/fyi/blog/2007/09/steve_souders_high_performance.html">Steve Souder's</a> number one rule for speeding up your website.
<p>
What we need to do is to add an <i>Expires</i> header to our static content - one that gives a time a long way in the future so that the browser knows that the content should stays in  the cache -and not be fetched again, or even checked (if it has been updated) from the server.  But what if we want to change a css file or a js file?  The user will get the old one from their own cache.  No good.
<p>
Well Rails has a mechanism to prevent this - it adds a 10 digit number on the end of each url (as generated by image_tag, stylesheet_link_tag, or javascript_include_tag for instance) in the query string.  That number is based on the file modification time - so when the file is updated then the URL will change.  It's like having a remote way to expire the item in the browser's cache.
<p>
So it's simple right? Just turn on mod_expires in Apache?  Not so fast.  What about those images and items that do not have the query string?  We don't want to send an expires header for those.  Definitely not.  (And you will likely have some - for instance images that are referenced from your css files.)  If you do, the user is stuck with their cached version even if you change the file on the server.
<p>
So we need some way of selectively turning on the expires header in apache.
<p>
<a href="http://blog.dannyburkes.com/2006/11/2/versioned-urls-for-rails/">One way [Danny Burkes]</a> (look at the update at the bottom) is to segregate by directory what you want to expire and what not.  But this seems a bit clumsy to manage.  (Also, side issue, I am not totally convinced that the munging of the urls provided by the plugin is needed - at least <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9">section 13.9</a> of the HTTP 1.1 spec seems to suggest that content with query strings will be cached fine if an explicit expires header is given.)
<p>
Actually you can do what you need with one symbolic link and some apache magic.  The obvious magic won't work - you can't detect what's in a query string using a LocationMatch or FilesMatch container.  But we can get around this with a rewrite rule, and a directory container.
This is from my apache httpd.conf file:
<pre>
  # add something we can do a directory match on
  RewriteCond %{QUERY_STRING} ^[0-9]{10}$
  RewriteRule ^(.*)$ /add_expires_header%{REQUEST_URI} [QSA]

  # the add_expires_header directory is just a symlink to public
  &lt;Directory "/path/to/rails_app/public/add_expires_header"&gt;
    ExpiresActive On
    ExpiresDefault "access plus 10 years"
  &lt;/Directory&gt;
</pre>
This detects those query strings (we assume you don't use 10 digit query strings for anything else), and adds a directory on the front of the path.
<p>
We use this as something we can detect in a Directory container.  And in there we turn on the expires header.
<p>We need one more thing:
<pre>
cd /path/to/rails_app/public
ln -s . add_expires_header
</pre>
The symbolic link doesn't go anywhere, and that's just what we want.  All the images and css files and whatnot will be found in their usual places.  It's pretty unobtrusive -you don't need to change anything in your app to start to benefit from the expires header.
<p>It's a big benefit - we have literally gone from 50 HTTP requests per page to about 16.  And with some tweaking we'll get it down more - some of those are from references to images in css, but a few are due to us not using urls generated by rails for static content.  And we can fix those.

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?157</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-17T20:01:21+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?156" >
<title>Benchmarking at the method level in rails controllers</title>
<description>We have a reasonably complicated set of logic inside our controllers that is able to take an incoming url and serve the right content depending on 3 different parts of the url in various combinations ...</description>
<content:encoded><![CDATA[<p>We have a reasonably complicated set of logic inside our controllers that is able to take an incoming url and serve the right content depending on 3 different parts of the url in various combinations and permutations.  There are quite many DB queries required, and sometimes it goes slow.
<p>I wanted to find where the system was spending its time, and the DB query logging provided by ActiveRecord was not enough to show me where the performance needed tuning.
<p>The rails <code>benchmark</code> method to the rescue.  And a little meta-programming.  I added this to application.rb:
<pre>
  if ENV['EXTRA_BENCHMARKING']
    @@added_methods = []
    def self.method_added(id)  # wrap a benchmark around all controller method calls
      name = id.id2name
      if name =~ /^old_(.*)$/
        return if @@added_methods.include?($1)
      else
        return if @@added_methods.include?(name)
      end
      @@added_methods &lt;&lt; name
      alias_method "old_#{name}".intern, name.intern
      eval %{
        def #{name}(*args, &block) 
          logger.info("*=*=*=*=*=*=*=*=* #{name} START")
          self.class.benchmark("*=*=*=*=*=*=*=*=* #{name}", Logger::DEBUG, false) do
            send("old_#{name}", *args, &block)
          end
        end
      }
    end
  end
</pre>
<p>It's important to add this pretty much at the top of application.rb, or at least before all the methods you want to time.
<p>Method_added gets called every time a method is added to the class.   As each method is added we make a note of it in our array @@added_methods, and then alias it with the prefix "old_".  Then we define a new method adding the logger calls and the benchmark call.
<p>The output looks like this:
<pre>
...
*=*=*=*=*=*=*=*=* save_url_history START
*=*=*=*=*=*=*=*=* save_url_history (0.00004)
*=*=*=*=*=*=*=*=* missing_page_catcher START
*=*=*=*=*=*=*=*=* get_categories START
*=*=*=*=*=*=*=*=* get_categories (0.00028)
*=*=*=*=*=*=*=*=* get_continents START
*=*=*=*=*=*=*=*=* get_continents (0.00004)
...
</pre>
<p>Also you will get all your regular debug level logging in between these new lines in your log.
<p>Note that the @@added_methods array is important because both alias_method and the eval'd def result in a call to method_added - so we use the array to prevent infinite recursion.
<p>Just run rails up with the EXTRA_BENCHMARKING environment variable set, and you are away:
<pre>
EXTRA_BENCHMARKING=1 script/server -e production
</pre>
I like to use production mode so I can see the effect of the fragment caching.  But you'll get valid results in development mode too.
</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?156</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-13T10:03:20+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?155" >
<title>Rails logging - config.log_level has no effect</title>
<description>Curiously adding config.log_level = :debug to environment.rb appears to have no effect on the logging performed by ActiveRecord.  To get to see the detailed logging and benchmarking of your database q...</description>
<content:encoded><![CDATA[<p>Curiously adding config.log_level = :debug to environment.rb appears to have no effect on the logging performed by ActiveRecord.  To get to see the detailed logging and benchmarking of your database queries in production mode you need to place this <i>after</i> the Rails::Initializer.run block in environment.rb:

<pre>
ActiveRecord::Base.logger.level = Logger::DEBUG
</pre>
</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?155</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-13T09:41:05+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?154" >
<title>Rails testing - two gotchas</title>
<description>&lt;b&gt;Gotcha 1&lt;/b&gt;
&lt;p&gt;Failing tests.  We'd like them to pass of course.  But there is something strange going on - the error is not a test error, it seems to come from rails itself:
&lt;pre&gt;
  1) Error:...</description>
<content:encoded><![CDATA[<p><b>Gotcha 1</b>
<p>Failing tests.  We'd like them to pass of course.  But there is something strange going on - the error is not a test error, it seems to come from rails itself:
<pre>
  1) Error:
test_searcher_email(OrderMailerTest):
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb:498:in `orders'
    ./test/unit/order_mailer_test.rb:22:in `test_searcher_email'

1 tests, 0 assertions, 0 failures, 1 errors
</pre>
<p>What does it mean?  The clue here is that the error comes from fixtures.rb.  The other thing to note is that I have a setup in my test:
<pre>
  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
   ...
  end
</pre>
Which should be fine, but there is this nasty error.  Let's try something in the setup method - we'll add a call to super there:
<pre>
  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
    ...
    super
  end
</pre>
And the result:
<pre>
Started
.
Finished in 0.160284 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
</pre>
Great, that's fixed it.  But why?  Well it took me a while to find it.  Have a look in /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb - there is your culprit at line 554:
<pre>
     alias_method :setup, :setup_with_fixtures
</pre>
So the rule is, if you override setup you need to call super otherwise you don't get your fixtures set up properly.
<p><b>Gotcha 2</b>
<p>Ever tried to test your routes?  You should.  But if you have routes that depend on what's in your database you've got a problem.  Why?  Because the routing is initialised before any fixtures are loaded.  In fact none of the test related code is loaded at that point.  So your tests just won't work.
<p>I don't know a good way to fix this.  In the end I opted for a fudge at the beginning of routes.rb:
<pre>
  if ENV['RAILS_ENV'] == "test" && Category.count == 0
    Category.create!(:name=>"Families and Friends", :alternative_name=>"Family")
  end
</pre>
And I have a fixture that contains the same information.  This isn't really DRY, but I don't really see a good way to do this.  Maybe we could read the fixtures file ourselves and get the data from there.
<p>But at least the tests run ok now.

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?154</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-09T09:37:30+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?153" >
<title>debug1: Remote: No xauth program; cannot forward with spoofing</title>
<description>I needed to install X on a remote fedora machine, and then use my local machine as the X server over ssh.  Compiling &amp; installing X went smoothly, but I got the following error when running ssh -X (wi...</description>
<content:encoded><![CDATA[<p>I needed to install X on a remote fedora machine, and then use my local machine as the X server over ssh.  Compiling & installing X went smoothly, but I got the following error when running ssh -X (with -v for debug output) to the remote machine:
<pre>
debug1: Remote: No xauth program; cannot forward with spoofing
</pre>
I figured /usr/X11R6/bin needed to be in the path, but modding the path in .bash_profile, /etc/ssh/sshrc, or similar places had no effect.
<p>It turns out that sshd has a hard wired idea of where xauth is supposed to be:
<pre>
$ strings /usr/sbin/sshd|grep xauth
/usr/bin/xauth
xauthlocation
maxauthtries
No xauth program; cannot forward with spoofing.
</pre>
So there you are - the solution is simple:
<pre>
# ln -s /usr/X11R6/bin/xauth /usr/bin/xauth
</pre>

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?153</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-03T10:35:41+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?152" >
<title>Why Ruby is not my favourite programming language</title>
<description>Actually it &lt;i&gt;is&lt;/i&gt; my favourite.  But the title comes from &lt;a href=&quot;http://www.miketaylor.org.uk/tech/wxinmfpl/ruby.html&quot;&gt;this article&lt;/a&gt; (which itself was inspired and copied from the &lt;a href=&quot;ht...</description>
<content:encoded><![CDATA[<p>Actually it <i>is</i> my favourite.  But the title comes from <a href="http://www.miketaylor.org.uk/tech/wxinmfpl/ruby.html">this article</a> (which itself was inspired and copied from the <a href="http://www.lysator.liu.se/c/bwk-on-pascal.html">famous paper</a> about pascal by Brian Kernighan).

<p>On with business though - Ruby has some serious wrinkles that produce counter-intuative and plain strange behaviour.  One might say that they violate the <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/52463">Principle of Least Surprise</a>.  But POLS is somewhat personal - surprising to whom? (just me maybe!)

<p>Surprising result #1
<pre>
b=1
=&gt; 1
a if a=b
NameError: undefined local variable or method `a' for main:Object
        from (irb):2
</pre>
<p>
This is odd indeed.  It seems that the Ruby parser thinks that a is a method at the beginning of the line.  But when it parses a=b it will know (and remember) that it is a variable.  However, when the condition passes and it comes to execute 'a', it does not apply its new found knowledge about the nature of a - it still goes for the method.  And hence the error.
<p>Surprising result #2
<pre>
c=1 unless defined? c
=&gt; nil
c
=&gt; nil
</pre>
<p>This is a bit easier to explain.  Once the parser has seen c=1 it enters c in the symbol table, it knows that c exists as a variable.  Hence it is defined (as nil).  So c=1 is never executed.
<p>Surprising result #3
<pre>
class A
  attr_accessor :a
  def b
    @a=0
    x=a
    a=x+1
    puts("a is #{a}")
    puts("@a is #{@a}")
  end
end
=&gt nil
c = A.new
=&gt; #&lt;A:0x32fb7c&gt;
c.b
a is 1
@a is 0
</pre>
<p>No mystery here really - it's a nice gotcha though - a= does not call self.a=, it just assigns a local variable.  It is just a little confusing unless you think carefully.
<p>Surprising result #4
<pre>
[0.0, 1/0.0].sort
=&gt; [0.0, Infinity]
[0.0, 0/0.0].sort
ArgumentError: comparison of Float with Float failed
</pre>
<p>Thanks to Evan Weaver for pointing this out to me.  This is due to 0/0.0 returning the value NaN (as opposed to 1/0.0 which returns Infinity).  And the comparison with NaN by sort gives the strange error message.
<p>Let me know if you spot any more oddities.</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?152</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-10-01T12:02:14+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?151" >
<title>Could not find rails (&gt; 0) in any repository</title>
<description>This is with a brand new installation of ruby (./configure, make, make install) and of rubygems (ruby setup.rb).  Odd error message to get really, rails is certainly there .
&lt;p&gt;&lt;a href=&quot;http://armyof...</description>
<content:encoded><![CDATA[<p>This is with a brand new installation of ruby (./configure, make, make install) and of rubygems (ruby setup.rb).  Odd error message to get really, rails is certainly there .
<p><a href="http://armyofevilrobots.com/node/418">This</a> helps, but actually all I needed to do was to simply say
<pre>
gem update
</pre>
... and then ...
<pre>
gem install rails --include-dependencies
</pre>
...works as it should.

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?151</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-09-28T12:06:31+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?150" >
<title>Full text search systems</title>
<description>A quick survey of the available open source systems for text search
&lt;ul&gt;
&lt;li&gt;Mysql full text search
&lt;li&gt;&lt;a href=&quot;http://lucene.apache.org/&quot;&gt;Lucene&lt;/a&gt;
&lt;li&gt;&lt;a href=&quot;http://lucene.apache.org/solr/&quot;&gt;...</description>
<content:encoded><![CDATA[<p>A quick survey of the available open source systems for text search
<ul>
<li>Mysql full text search
<li><a href="http://lucene.apache.org/">Lucene</a>
<li><a href="http://lucene.apache.org/solr/">SOLR</a> (server based on lucene)
<li><a href="http://ferret.davebalmain.com/trac">Ferret</a>
<li><a href="http://www.sphinxsearch.com/">Sphinx</a>
<li><a href="http://www.indexdata.dk/zebra/">Zebra</a> (if you can ever figure out how to use it)
</ul>

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?150</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-09-24T14:45:30+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?149" >
<title>Obfuscated ruby - ETA interpreter updated</title>
<description>Just a quick pointer - I had some correspondence resulting in some updates to my by now ancient &lt;a href=&quot;http://www.stephensykes.com/tinyeta.html&quot;&gt;obfuscated ETA interpreter&lt;/a&gt;.  
&lt;p&gt;The idea is to ...</description>
<content:encoded><![CDATA[<p>Just a quick pointer - I had some correspondence resulting in some updates to my by now ancient <a href="http://www.stephensykes.com/tinyeta.html">obfuscated ETA interpreter</a>.  
<p>The idea is to write the shortest interpreter for <a href="http://www.miketaylor.org.uk/tech/eta/doc/">the ETA programming language</a> possible.  Previously I had got the program down to 227 chars of tight and obfuscated Ruby.
<p>
With these updates, either 4 or 16 chars have been knocked off the old best effort, depending on whether you want warnings or not.  And both the newer versions are compatible with Ruby 1.8.6, which is a good thing seeing as the older versions were failing to run.
<p>Although obfuscated programming is on the whole a fairly useless pastime, one certainly learns all the strange little creepy corners of a language.  And Ruby has a few. (And not just <a href="http://www.miketaylor.org.uk/tech/wxinmfpl/ruby.html">this</a>). I'll explain more in a later post.

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?149</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-09-22T22:58:14+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?148" >
<title>IOCCC 2006 winning entries</title>
<description>I am delighted to say that both my entries for the 19th IOCCC qualified for a prize.
&lt;p&gt;The first was a solver for the Bedlam cube. 
Here are the &lt;a href=&quot;IOCCC/2006/sykes1/remarks&quot;&gt;remarks&lt;/a&gt;, the...</description>
<content:encoded><![CDATA[<p>I am delighted to say that both my entries for the 19th IOCCC qualified for a prize.
<p>The first was a solver for the Bedlam cube. 
Here are the <a href="IOCCC/2006/sykes1/remarks">remarks</a>, the <a href="IOCCC/2006/sykes1/Makefile">makefile</a> and the <a href="IOCCC/2006/sykes1/sykes1.c">program itself</a>.
<p>The second was a one liner digital clock program.
Here are the <a href="IOCCC/2006/sykes2/remarks">remarks</a>, the <a href="IOCCC/2006/sykes2/Makefile">makefile</a>, the <a href="IOCCC/2006/sykes2/sykes2.c">program itself</a>, and finally the <a href="IOCCC/2006/sykes2/runner">script for running it</a>.
<p>You can check out my previous entries <a href="http://www.stephensykes.com/blog_perm.html?74">here (2004)</a> and <a href="http://www.stephensykes.com/blog_perm.html?112">here (2005)</a>.
<p>This year the winners are being presented again at the <a href="http://www.vintage.org/2007/main/">Vintage Computer Festival</a> on the 3rd and 4th November 2007 in Mountain View, California.  It was a great event last year, and I'll go there again if I can this time.  I recommend it if you are nearby.


</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?148</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-09-21T06:14:41+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?147" >
<title>xtorrent 1.1 - released today</title>
<description>Now then, there is this very nice torrent client for the mac called &lt;a href=&quot;http://www.xtorrentp2p.com/&quot;&gt;xtorrent&lt;/a&gt; (well, it's more than &lt;i&gt;just&lt;/i&gt; a client).  And there happens to be a new versi...</description>
<content:encoded><![CDATA[<p>Now then, there is this very nice torrent client for the mac called <a href="http://www.xtorrentp2p.com/">xtorrent</a> (well, it's more than <i>just</i> a client).  And there happens to be a new version of it that you can read all about <a href="http://www.newsfirerss.com/blog/?p=178">over here</a>.

<p>
Go have a look.  And see if you can guess why I wrote about it :)
<p>
Truly, all Dave Watanabe's stuff is good though, & I have been using Newsfire as my main newsreader for a long time.

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?147</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-08-31T15:19:57+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?146" >
<title>Caught at the Storyville</title>
<description>&lt;a href=&quot;http://votak.multiply.com/photos/photo/90/20&quot;&gt;http://votak.multiply.com/photos/photo/90/20&lt;/a&gt;

</description>
<content:encoded><![CDATA[<p><a href="http://votak.multiply.com/photos/photo/90/20">http://votak.multiply.com/photos/photo/90/20</a>

</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?146</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-08-28T12:34:39+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?145" >
<title>Rails: wrapping content from a helper</title>
<description>The form_tag method in ActionView uses a nice trick to wrap a block of content in form tags, and you can wrap content the same way yourself.
&lt;p&gt;You want to write something like:
&lt;pre&gt;
&amp;lt;% yellow_...</description>
<content:encoded><![CDATA[<p>The form_tag method in ActionView uses a nice trick to wrap a block of content in form tags, and you can wrap content the same way yourself.
<p>You want to write something like:
<pre>
&lt;% yellow_boxed do %>
some text and html and stuff
it's probably only worth doing it this way
if this bit is longer than a line or two
&lt;% end %>
</pre>
This reads in a very natural way.  To do this, I have a helper method called yellow_boxed:
<pre>
  def yellow_boxed(&block)
    concat(render(:partial=>"yellow_boxtop"), block.binding)
    content = capture(&block)
    concat(content, block.binding)
    concat(render(:partial=>"yellow_boxbottom"), block.binding)
  end
</pre>
This technique can be used in any situation where it is logical to wrap content.
<p>Note that I render a partial for the top and the bottom of my yellow box.  The partials just contain table, tr and td tags and so on, but I wanted to keep the html strings out of my helper.  But for short lengths of html it's not a problem, you can put text strings there instead of the much more expensive calls to render.</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?145</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-08-09T08:50:40+00:00</dc:date>
</item>
<item rdf:about="http://www.stephensykes.com/blog_perm.html?144" >
<title>Tumblelog</title>
<description>I made a &lt;a href=&quot;http://switchstep.tumblr.com/&quot;&gt;tumblelog at tumblr&lt;/a&gt;.  They have a pretty easy to use interface: maybe I'll use it more than this blog.
</description>
<content:encoded><![CDATA[<p>I made a <a href="http://switchstep.tumblr.com/">tumblelog at tumblr</a>.  They have a pretty easy to use interface: maybe I'll use it more than this blog.
</p>]]></content:encoded>
<link>http://www.stephensykes.com/blog_perm.html?144</link>
<dc:creator>Stephen Sykes</dc:creator>
<dc:date>2007-07-11T12:42:45+00:00</dc:date>
</item>
</rdf:RDF>