<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Ruby Pond</title>
    <link>http://rubypond.com/rss/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby Pond Ltd. | Ruby on Rails Developers, Online Marketing, Social Networking</description>
    
    
        <item>
          <title>JRuby, and why bouncers are assholes</title>
          <description>&lt;p&gt;I&amp;#8217;m normally not one to use this site as a soap box or an outlet for opinion pieces. But I figured it&amp;#8217;s easier than being continually baited into replying on all the various blogs/forums/groups out there. There&amp;#8217;s a whole heap of talk in the ruby community at the moment on JRuby and it&amp;#8217;s place in the ecosystem. Most of it has been kicked off in response to Charles Nutter&amp;#8217;s post on &lt;a href=&quot;http://blog.headius.com/2009/07/jrubys-importance-to-ruby-and-erubycon.html&quot;&gt;JRuby&amp;#8217;s importance to Ruby&lt;/a&gt;. I was fortunate enough to see Charles&amp;#8217; presentation at Rails Underground last week and have a chat to him, and he had some great insights and examples of why JRuby actually is pretty damn awesome.&lt;/p&gt;

&lt;h2&gt;The sky is falling&lt;/h2&gt;

&lt;p&gt;The only real problem I have with Charles&amp;#8217; post is the inference that all is lost for the Ruby community if we don&amp;#8217;t embrace JRuby quickly. It&amp;#8217;s not, it won&amp;#8217;t suddenly disappear. What we will possibly lose is the migration of great java developers like &lt;a href=&quot;http://twitter.com/jimweirich&quot;&gt;Jim Weirich&lt;/a&gt; and Charles. I&amp;#8217;m willing to excuse a bit of sensationalism in his post though, we&amp;#8217;re effectively talking about his livelihood here. He needs to get people to pay attention, he needs people to use JRuby, he needs more of us to embrace it.&lt;/p&gt;

&lt;p&gt;Whatever his motivations, he&amp;#8217;s right.&lt;/p&gt;

&lt;h2&gt;Java sucks&lt;/h2&gt;

&lt;p&gt;Yes, we know. But you&amp;#8217;ve missed the point. This isn&amp;#8217;t about giving &lt;em&gt;us* java, it&amp;#8217;s about giving *java&lt;/em&gt; ruby. Or better yet, giving ruby the JVM. Just try and think through the argument logically; why on earth would a java developer who is unhappy with java for whatever reason move to a new language, that gave you all the same obstacles? They wouldn&amp;#8217;t (no matter what your opinion of the average java dev is). It&amp;#8217;s about combining the flexibility of ruby with the good bits of java, the bits that are good enough to make people want to stick with java.&lt;/p&gt;

&lt;h2&gt;Java/The JVM is slow&lt;/h2&gt;

&lt;p&gt;&amp;#8220;Good morning Mr. Kettle, I&amp;#8217;m the pot&amp;#8230; and you my friend look black&amp;#8221;. Really? People that are happy enough with the performance of ruby 1.8 are pointing the &amp;#8220;unperformant&amp;#8221; stick at other interpreters? Give me a break. The fact is that the JRuby implementation (in most cases) is as good as 1.8, and in many is as good as 1.9. The fact that such a minor section of the community seems to be aggressively migrating to 1.9 highlights the fact that performance really isn&amp;#8217;t such a high concern for you in real life work, it&amp;#8217;s just a great scape goat for debates. Oh, and worried about that additional few secs startup overhead from starting the JVM for little scripts? Then &lt;a href=&quot;http://blog.headius.com/2009/05/jruby-nailgun-support-in-130.html&quot;&gt;don&amp;#8217;t start it up&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Ruby/rails is a competitive advantage&lt;/h2&gt;

&lt;p&gt;Bull. Shit. Your competitive advantage is your expertise and the ability to meet your client requirements, as efficiently as possible. Period. Ruby and Rails have helped you have an edge for the past few years, but there&amp;#8217;s many alternatives that are closing the gap. Most of my clients don&amp;#8217;t care what technology I use so long as I do the best job for them and make the most efficient use of their money. And why should they care? The few clients I have worked for that would care, would probably still prefer I use java over ruby. &lt;/p&gt;

&lt;h2&gt;The EngineYard deal is acknowledgement from Sun that even they think JRuby is dead&lt;/h2&gt;

&lt;p&gt;Wrong. JRuby is never going to be a core part of Sun&amp;#8217;s business. There are so many people that are happy with the status quo that they will continue coding away in java until such a day it might be declared deceased. Why would they have any desire to invest both time and money to stop such a minor outflow from their business? They wouldn&amp;#8217;t, they&amp;#8217;ve got bigger problems to deal with. On the other hand, EngineYard is all about infrastructure&amp;#8230; and infrastructure for hosting ruby apps specifically. Higher performance ruby implementations means they need to invest less in hardware for the same return. It has a direct and appreciable impact on their bottom line. Sun was a great fit initially to allow the guys access to the java team so we could get the most out of the JVM. EngineYard have more to gain out of a successful JRuby at this point than Sun do, so they&amp;#8217;re a much better fit.&lt;/p&gt;

&lt;h2&gt;We don&amp;#8217;t want more java developers or the java community&lt;/h2&gt;

&lt;p&gt;This is the one that irks me the most. I can only recall two occasions in life where one group of people proclaims they are too cool to associate with another group of people. Bouncers at nightclubs, and &lt;em&gt;&amp;#8220;that&amp;#8221;&lt;/em&gt; group in high school. Bouncers are assholes, and those kids from high school probably grew up to become bouncers. &lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve got a problem with someone else, that&amp;#8217;s your own insecurities and your problem to deal with, don&amp;#8217;t infect the rest of us with it. What&amp;#8217;s the issue here? You don&amp;#8217;t like their code? Then fork it, fix it, or do it yourself and the problem magically goes away. If you don&amp;#8217;t want to do that, then shut your pie hole and pay some respect to those that actually do the work. You don&amp;#8217;t like the competition? Go read a book or five, find some better developers to pair with, stop trying to hide.&lt;/p&gt;

&lt;p&gt;If we&amp;#8217;re using a technology that really is as great as we make out, we should see it as inevitable that the community is going to grow significantly in size at some point. I think Malcolm Gladwell refers to it as the tipping point. The technical ability of the average developer may drop a little. Commercial interests may infest us and move conferences to Vegas. But for every 10 hacks you still end up with a Jim Weirich, Giles Bowkett, David A. Black, etc. And for every large conference you end up with a Rails Underground, Scotland on Rails, or Ruby Hoedown.&lt;/p&gt;

&lt;h2&gt;Looking at the world through ruby tinted glasses&lt;/h2&gt;

&lt;p&gt;The fact is that for a long time the performance of ruby has sucked. We&amp;#8217;ve worked around it and justified it for a long time, and for the vast majority of people it didn&amp;#8217;t suck bad enough to cause problems. Heck, we were all happy using webrick until Zed Shaw came along and showed us a better way. But 3rd party library support has also sucked. Trying to create PDFs was a nightmare for ages. Trying to work with Microsoft document formats still is. I can think of at least 5 occasions where I&amp;#8217;ve solved a simple problem in another language because doing it in ruby would have been far too difficult.&lt;/p&gt;

&lt;p&gt;For all the talent the community has, there are so many areas where good support is still lacking that it&amp;#8217;s unrealistic to think there are enough talented people who care &lt;em&gt;and&lt;/em&gt; have the time to do anything about it. Combine that with the fact java has at least (commercially) a 10 year head start and the gap between the two languages is huge. Java has plenty to offer us.&lt;/p&gt;

&lt;h2&gt;Why can&amp;#8217;t it all just be peace, love, rainbows, and freakin flying ponies?&lt;/h2&gt;

&lt;p&gt;All this arguing seems to do is instill a whole &amp;#8220;us and them&amp;#8221; mentality. There&amp;#8217;s no need for it to be that way. Embrace JRuby, take advantage of the performance of the JVM, get access to a whole swathe of new libraries that go far beyond what your current list of gems currently offers you&amp;#8230; and get to keep using the language you love.&lt;/p&gt;

&lt;p&gt;One of the things I admire most about the ruby community is the ability it has to support innovations and allow the proverbial cream to rise to the top. WebBrick was replaced by Mongrel, then we had Thin, and now we&amp;#8217;ve got Passenger. SOAP became REST. AttachmentFu became Paperclipped, etc. I&amp;#8217;d hate if in this instance it wasn&amp;#8217;t allowed to happen because of a whole heap of misconceptions about what JRuby was and what it had to offer.&lt;/p&gt;

&lt;p&gt;Or maybe we just need to get a &lt;a href=&quot;http://www.mylittledjango.com/&quot;&gt;mascot like Django&lt;/a&gt; and chill the fuck out.&lt;/p&gt;</description>
          <pubDate>Thu, 30 Jul 2009 12:58:30 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/07/30/jruby-and-why-bouncers-are-assholes/</guid>
          <link>http://rubypond.com/articles/2009/07/30/jruby-and-why-bouncers-are-assholes/</link>
        </item>
    
        <item>
          <title>Rails Underground - Day 2</title>
          <description>&lt;p&gt;&lt;strong&gt;update:&lt;/strong&gt; &lt;a href=&quot;http://www.rails-underground.com/09-conference-schedule.html&quot;&gt;videos are now online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was a little late to the kick-off of the keynote on day 2 with Yehuda. For the most part if is another discussion on what&amp;#8217;s happening in Rails 3 so I don&amp;#8217;t think I&amp;#8217;ve missed anything I hadn&amp;#8217;t heard before. He then started to go into more detail on how things have changed than he has previously, probably due to the progress since I last saw him in March&amp;#8230;&lt;/p&gt;

&lt;h2&gt;Yehuda Katz - Keynote&lt;/h2&gt;

&lt;p&gt;Yehuda went through the upcoming changes in approach and philosophy on rails Dev. Having well defined contracts, consistent conventions, and allowing things be be changeable. &lt;/p&gt;

&lt;p&gt;One of the changes of not is splitting off ideas and interfaces into modules which can then be imported into a class at runtime. He used the analogy that your parents didn&amp;#8217;t define everything you could do when you were born, you can learn new things. So to when you define ta class you don&amp;#8217;t have to define the complete interface up front, nor if you want to make changes to you need to re-implement the entire class. Instead you can have sub-sections of interfaces included or changed at runtime where appropriate.&lt;/p&gt;

&lt;p&gt;In Rails 3 this translates into better separation of the components and clearly defined interfaces. No longer are you forced to use ActionView, you just need to use something that is &amp;#8220;ActionView compliant&amp;#8221;. The same goes for ActiveRecord, your models are just &amp;#8220;ActionModel compliant&amp;#8221;.&lt;/p&gt;

&lt;p&gt;An ActionView compliant interface just needs to implement the following 3 methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for_controller(paths, assigns, controller)
render_template(opts)
render_partial(opts)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An ActiveModel compliant interface needs the following 4 methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;new_record?
valid?
errors
model_name&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That last &lt;em&gt;model_name&lt;/em&gt; method needs to return plural, partial name, and a few other things rails expects internally. It&amp;#8217;ll only be 10-20 lines of code to implement manually, or there is a module to include if you just want the default behaviour.&lt;/p&gt;

&lt;p&gt;Next up is a cleaner separation of components, one which we got a demo of was splitting out the ActiveModel::Validations. Now you can create your own ActiveModel compliant persistance/ORM layer, and pull in the existing validations for free regardless of where it&amp;#8217;s stored (YAML, CouchDB, etc.).&lt;/p&gt;

&lt;p&gt;By implementing the above you get a system that fully works with ActionPack, so all the usual form and error helpers will just work.&lt;/p&gt;

&lt;p&gt;The other benefit is that pulling in support for these doesn&amp;#8217;t need you to load the entire Rails stack and rob your machine of RAM, it&amp;#8217;s only a 1.5mb hit.&lt;/p&gt;

&lt;p&gt;Next was the new ActionController::Metal demo. At first I wondered why I&amp;#8217;d bother, it was slightly more vebose than just using Rackable or rolling it manually, and seemed to carry more overhead than Sinatra. But it gives you the ability to opt into additional features easily. If you wall before/after filters you can pull in the callbacks module. If you want better rendering options (various formats, etc) pull in the rendering module, if you want different layouts pull in that module. ActionController::Base is basically just ActionController::Metal with all of the modules pulled in, so you&amp;#8217;ve now got the way to strip back to metal, or anything in between.&lt;/p&gt;

&lt;p&gt;The final piece is ActiveSupport. If for some reason you want to pull in the entire ActiveSupport behemoth you just call:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'active_support/all'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Otherwise you can call in the various newly separated modules, one of note was &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'active_support/ruby/shim'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which backports a bunch of useful ruby1.9 features on datatypes that could be easily implemented in pure ruby. So you can use them now, and when you upgrade to ruby1.9 you get the performance improvement of having them implemented in C.&lt;/p&gt;

&lt;p&gt;The end result is a new level of granularity. Just because you want to use DataMapper doesn&amp;#8217;t mean you have to say goodbye to all of ActiveRecord. So you can opt-out of just the tiny pieces you don&amp;#8217;t want. Conversely, you can start completely bare and opt-in on various features to build your own framework on top of rails. You could now build Sinatra on top of rails, and when the complexity of your app increases you can much more easily pull in the additional features you need. All in all, it sounds really cool. Cool enough that I might even try using it on my next app.&lt;/p&gt;

&lt;h2&gt;Dr. Nic Williams - Dead Simple JavaScript Unit Tests in Rails with Blue Ridge and Screw.Unit&lt;/h2&gt;

&lt;p&gt;Dr. Nic has dropped a very important bombshell right at the start of his talk. The while Australia may indeed be losing the current 5 game series, we are still holders of The Ashes. Now on with the less important aspects of the presentation.&lt;/p&gt;

&lt;p&gt;Nic has a bunch of open source plugins and projects which he could have come and given a presentation on, but he&amp;#8217;s so impressed with BlueRidge that he feels it&amp;#8217;s the most important thing to happen to the Rails ecosystem since Cucumber. At a high level it allows you to do both in browser and headless testing, it fits in with the existing rake tasks, and means that javascript testing should just become part of the usual TDD/BDD development approach and not be an afterthought in Cucumber.&lt;/p&gt;

&lt;p&gt;Generating a javascript test with BlueRidge creates a spec file, and a fixture file which will give you some test HTML. The idea being that most of your javascript ultimately want to modify the DOM, so run the app and copy out the rendered HTML you need to use as your stub.&lt;/p&gt;

&lt;p&gt;An example of a test is as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require(&amp;quot;spec_helper&amp;quot;);
require(&amp;quot;../../public/javascripts/accounts.js&amp;quot;);

Screw.Unit(function() {
  describe('accounts/new initially has fields', function() {
    it(&amp;quot;should have name field&amp;quot;, function() {
      expect($('#account_name').size()).to(equal, 1);
    });
  });

  describe('accounts/new to fail if missing name', function() {
    it(&amp;quot;should have erroneous name field&amp;quot;, function() {
      $('#account_submit').click();
      expect($('div.fieldWithErrors #account_name').size()).to(equal, 1)
    });
  });
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first test will check that an account_name field exists, and in TDD it shouldn&amp;#8217;t. So next you should go insert the HTML you need into your stub HTML file. (&lt;strong&gt;note:&lt;/strong&gt; you&amp;#8217;ll also need to ensure that the form doesn&amp;#8217;t actually submit on the test, so you need to add a function to return false when the button is clicked).&lt;/p&gt;

&lt;p&gt;When you run the tests you should find that you get nicely green/red tests in browser for any passing/failing tests.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require(&amp;quot;spec_helper&amp;quot;);
require(&amp;quot;../../public/javascripts/accounts.js&amp;quot;);

Screw.Unit(function() {  
  describe('accounts/new to fail if missing name', function() {
    it(&amp;quot;should have erroneous name field&amp;quot;, function() {
      $('#account_submit').click();
      expect($('div.fieldWithErrors #account_name').size()).to(equal, 1)
    });
  });
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next it is checking that when you submit the form, it wraps the empty form input with the standard rails error div. Run the test, get a failure. Implement the code and the tests go green. You&amp;#8217;ll probably notice that the test passes but you don&amp;#8217;t get the red box, so you need to include the CSS in the test (just below the require) to actually see what the user would:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;css(&amp;quot;../../public/stylesheets/scaffold.js&amp;quot;);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next Dr. Nic went through a big gotcha, in that that tests don&amp;#8217;t run in transactions. Which means the DOM isn&amp;#8217;t reset back to it&amp;#8217;s an initial state, and he highlighted it by adding an additional test to check that when you input a name that you &lt;em&gt;don&amp;#8217;t&lt;/em&gt; get the error div. Unfortunately the test fails, as the div had been inserted by previous test.&lt;/p&gt;

&lt;p&gt;The way to deal with it was using a before block in your test:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require(&amp;quot;spec_helper&amp;quot;);
require(&amp;quot;../../public/javascripts/accounts.js&amp;quot;);
css(&amp;quot;../../public/stylesheets/scaffold.js&amp;quot;);

Screw.Unit(function() {  
 before(function() {
   $('#account_name').val('');
   $('div.fieldWithErrors').remove();
 });

 describe('accounts/new to fail if missing name', function() {
   it(&amp;quot;should have erroneous name field&amp;quot;, function() {
     $('#account_submit').click();
     expect($('div.fieldWithErrors #account_name').size()).to(equal, 1)
   });
 });
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If someone can come up with an easy way to snapshot the DOM/body.innerHTML and all attached events and substitute it back in after each test that would be awesome.&lt;/p&gt;

&lt;p&gt;Defining your own matches is also pretty simple. You simply add an object with match (to do the comparison) and failure_message to display the feedback and push it onto the matchers hash/dictionary.&lt;/p&gt;

&lt;p&gt;If anybody is wondering if they should test more, you need to watch the last 30secs of the presentation once the videos are available. Great job Nic :)&lt;/p&gt;

&lt;h2&gt;Paolo Negri - Divide and conquer riding rabbits and trading gems&lt;/h2&gt;

&lt;p&gt;Paolo had a problem where he had 1,000,000 search phrases and wanted to compare the results between Google and Bing (warning, don&amp;#8217;t try this at home&amp;#8230; it&amp;#8217;s a breach of the terms of service). Trying to fetch 2m pages is quite a time consuming task, enter a distributed approach.&lt;/p&gt;

&lt;p&gt;How many nodes will you need? How many workers? What mechanism should you use to distribute the work? RabbitMQ is an open source implementation of AMQP, written in Erlang. The fact it&amp;#8217;s written in Erlang is relevant is it inherently supports concurrency, fault tolerance, and distribution of tasks.&lt;/p&gt;

&lt;p&gt;To get started you need to install the rabbitmq package and a gem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install rabbitmq
sudo gem install tmm1-amqp&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&amp;#8217;s a link to the code at the bottom so rather than transcribe it all I&amp;#8217;ll just talk through it. &lt;/p&gt;

&lt;p&gt;First you create a worker which does the setup and then subscribe to the queue. The queue is where RabbitMQ will store all outstanding work, and the workers will request new work whenever they&amp;#8217;re free for more processing. At the other end of the process what happens is that your app pushes a message to an exchange, the exchange pops it on a queue, and then workers come take it off the queue. You can have multiple exchanges, multiple queues, and multiple workers. Queues and messages are resident in RAM, however you can persist them to disk for further fault tolerance (for a performance hit).&lt;/p&gt;

&lt;p&gt;There are problems though, if a worker has a problem you could lose some messages. To get around it you can send an ACK message from the worker to prefetch a message. You then process the message, and acknowledge completion. Dead client connections go unacknowledged and the work is handed off elsewhere.&lt;/p&gt;

&lt;p&gt;Another problem is there is no easy way to control the workers. The solution to this is to great a system queue. You give each worker a unique ID and explicitly define which exchange you want to use, and make it use the system queue. You then subscribe the worker to that queue. If you want to do something to the worker you simply post the appropriate command onto the system queue, and the worker will then pick up that command as soon as it can. You can also multicast messages to affect all workers.&lt;/p&gt;

&lt;p&gt;Next up was drilling into some of the detail of fetching the pages Google/Bing. For anyone who&amp;#8217;s not done something like this, you really need to use EventMachine and EventMachine::Deferrables. It means you&amp;#8217;re not blocked waiting for socket responses, but can fire callbacks when you get a response back and you can do other tasks (fetch other pages) concurrently in the one process.&lt;/p&gt;

&lt;p&gt;Problem #3 was working out how many workers you had, and keeping track of what they were doing. The solution was somewhat similar to the system approach, setup a heartbeat queue and have the workers post to the queue what they&amp;#8217;re doing. Then create a different worker which subscribes to that queue, takes all the messages off, and posts them somewhere for you to interrogate or view later (like a web page?).&lt;/p&gt;

&lt;p&gt;For doing TDD with RabbitMQ there is &lt;a href=&quot;http://github.com/danielsdeleo/moqueue&quot;&gt;moqueue&lt;/a&gt; which gives you easy testing of workers. There is also a web front-end for monitoring your RabbitMQ clients and make sure the system is alive called &lt;a href=&quot;http://github.com/auser/alice&quot;&gt;alice&lt;/a&gt;. For testing with EventMachine you&amp;#8217;ve got &lt;a href=&quot;http://github.com/tmml/em-spec&quot;&gt;em-spec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Slides are available at &lt;a href=&quot;http://www.slideshare.net/hungryblank/distributed-and-concurrent-programming-with-rabbitmq-and-eventmachine-rails-underground-2009&quot;&gt;SlideShare&lt;/a&gt;.
Code is on &lt;a href=&quot;http://github.com/hungryblank/rabbit_starter/tree/master&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Pat Allan - &amp;#8220;Sphinx - Beyond the basics&amp;#8221;&lt;/h2&gt;

&lt;p&gt;Sphinx is a full-text search engine, and Thinking Sphinx is an ActiveRecord plugin which will use Sphinx. Once you&amp;#8217;ve set it up if you want to search you just do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Article.search &amp;quot;my name&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll also need to use a few rake tasks to create/update the indexes. Now the basics are out of the way.&lt;/p&gt;

&lt;h3&gt;Facets&lt;/h3&gt;

&lt;p&gt;Pat&amp;#8217;s written some ruby code to provide a means of offering facets (search summaries) like other engines like Solr offer. To use you do &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;indexed field, :facet =&amp;gt; true
has_attribute , :fa&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;rebuild your indexes, then you&amp;#8217;re good to search.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@facets = Article.facets 'pancakes'
@facets == { :author =&amp;gt; { &amp;quot;Pat Allan&amp;quot; =&amp;gt; 12,
                         &amp;quot;Glenn Gillen&amp;quot; =&amp;gt; 1}.
            :tags =&amp;gt; { &amp;quot;breakfast&amp;quot; =&amp;gt; 2,
                       &amp;quot;brunch&amp;quot; =&amp;gt; 3}}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can then drill into the results to return just the Articles for a specific author:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@facet.for(:author =&amp;gt; &amp;quot;Pat Allan&amp;quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Excerpts&lt;/h3&gt;

&lt;p&gt;It got a bit of a cheer, apparently some people have been hanging out for them. They&amp;#8217;re basically the bold bits on a Google page of results, where the actual search terms are highlighted within the results. The syntax is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@articles = Article.search 'pancakes'
@article.excerpts.body&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Geo-searching&lt;/h3&gt;

&lt;p&gt;Pat thinks this could be the killer feature. The only gotcha is that the datatypes need to be in radians as floats. To define lats and longs on your models just do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;has latitude
has longitude&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&amp;#8217;ve already got lat and long data as degrees and decimals you can do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;has 'RADIANS(latitude)',
    :as =&amp;gt; :latitude,
    :type =&amp;gt; :float
has 'RADIANS(latitude)',
    :as =&amp;gt; :latitude,
    :type =&amp;gt; :float&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once that&amp;#8217;s done, you can find all pubs that serve pancakes near a given point:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@pubs = Pub.search 'pancakes'
  :geo =&amp;gt; [@lat, @lng],
  :order =&amp;gt; '@geodist ASC'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once you&amp;#8217;ve got your pubs you probably want&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@pubs.each_with_geodist do |pub, distance|
end&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;International Sphinx&lt;/h3&gt;

&lt;p&gt;Using the character set table means you can now handle international characters easier, so an &amp;#8220;e&amp;#8221; with an accent can be treated as a plain old english &amp;#8220;e&amp;#8221;. Same with other similar characters. &lt;/p&gt;

&lt;p&gt;With word stemming you can now define a custom stemmer to help you handle stemming in various languages without too much trouble. &lt;/p&gt;

&lt;h3&gt;Different Delta Approaches&lt;/h3&gt;

&lt;p&gt;In most rails apps you want information to be available as quickly as possible, so when users update a field you don&amp;#8217;t want to have to rebuild the whole index. To get around that you can do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;define_index do
  set_property :delta =&amp;gt; true
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The downside is you end up with a new column on the table, and a little additional HTTP overhead.&lt;/p&gt;

&lt;p&gt;Instead you can skip the extra column and use the updated_at field to manage deltas:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;define_index do
  set_property :delta =&amp;gt; :datetime, :threshold =&amp;gt; 2.hours
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The downside is they&amp;#8217;re not updated immediately, they&amp;#8217;re updated every 2 hours. Another alternative is to use the delayed option which pushes the request out of process using DelayedJob.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;define_index do
  set_property :delta =&amp;gt; :delayed
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Removes indexing from HTTP requests, and the results are available soon(ish). The downside is it needs a constantly running rake task (using delayedjob) and a long queue of updates could take a while to get through.&lt;/p&gt;

&lt;h3&gt;Multi-server deployment&lt;/h3&gt;

&lt;p&gt;Basically, set the remote_spinx value to true, use the DelayedJob approach, and make sure Spinx and the database are on the same server. You&amp;#8217;ll probably want the DelayedJob and ThinkingSphinx on that server too. Pat&amp;#8217;s not actively using multi-server setups so is looking for feedback on this.&lt;/p&gt;

&lt;h3&gt;Sphinx Scopes&lt;/h3&gt;

&lt;p&gt;People have been using named_scopes with Sphinx and it&amp;#8217;s caused some problems because of the difference between SQL and Sphinx. The new sphinx scopes are an implementation that works just like named scopes, except they chain together properly and work with pagination.&lt;/p&gt;

&lt;h2&gt;Brendan Lim - Mobilize Your Rails Application&lt;/h2&gt;

&lt;p&gt;There are an estimated 4 billing mobile users, which means there are more phones than there are personal computers. Approximately half of those users have mobile web access. With that much reach you need to make your apps accessible to as many of these users as possible.&lt;/p&gt;

&lt;p&gt;THe problem with trying to do just one webpage for all devices is problematic because of resolution differences, javascript, flash, bandwidth, etc.&lt;/p&gt;

&lt;p&gt;Enter MobileFu. It&amp;#8217;ll detect if a user is mobile, can add custom styling based on user agent and takes you one step closer to one webpage. You use it like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MyController &amp;lt; ActionController::Base
  has_mobile_fu

  def index
    respond_to do |format
      format.html
      format.mobile
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which will output the page in a mobile friendly format. Some of the magic happens in the stylessheet_include_tag:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;stylessheet_include_tag &amp;quot;foo&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will look for foo_iphone.css, foo_android.css, etc. so you can have custom styles for each device. You&amp;#8217;ve also got various helper methods to take actions within you view:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;is_mobile_device?
is_device?('blackberry')
in_mobile_view?&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rails iUI is a wrapper for the iUI user interface framework. It takes care of detecing rotating an iPhone and various other helpers. To use it you do the following in your controller:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MyController &amp;lt; ActionController::Base
  acts_as_iphone_controller

  def index
    respond_to do |format|
      format.html
      format.iphone
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then within your view:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;%=include_iui_files%&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To display iPhone styled default interface objects you&amp;#8217;ve the following methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;iui_toolbar( initial_caption, search_url)
button_link_to()
iui_list(items, opts)
iui_grouped_list(items, opts, &amp;amp;group_by_block)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again you need add some stuff into your views to make it work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;body &amp;lt;%=register_orientation_change%&amp;gt;&amp;gt;
observe_orientation_change(url_for_options)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you&amp;#8217;ll receive params[:position] in the request to the url you put in observe_orientation_change, 0 is upright. 90 and -90 is the two various landscape modes (depending on rotation).&lt;/p&gt;

&lt;p&gt;Next up is SMS. You can use Clickatell&amp;#8217;s API. Once you connect to the API you just do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;api.send_message(phone_number, message)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Brendan also wrote something called SMSFu. The problems are that you need to know the recipients carrier and it doesn&amp;#8217;t support as many carriers. But because it sends SMS via email it&amp;#8217;s free to send (to supported carriers). To send you just do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;deliver_sms(phone_number, carrier, message)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now how do you receive SMS? Well you can get a shortcode (an inbound SMS number like 80800), but they&amp;#8217;re quite expensive to setup with monthly costs associated. Alternatively there are providers (like TextMarks) where you&amp;#8217;re given a keyword that users need to prepend on the front of their message, and you share a shortcode. TextMarks then send the next set of words (up to 9) as an array to you to do what you want with.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re wanting to receive MMS, then MMS2R is the gem to use. It strips out any carrier advertising and other stuff that may be added to the core attachment that you actually want. You&amp;#8217;ll get access to the message subject, body, and default_media (the attachment).&lt;/p&gt;

&lt;h2&gt;Jim Weirich, DHH, Obie Fernandez, Geoffrey Grosenbach, Jonathan Siegel - Q&amp;amp;A Session&lt;/h2&gt;

&lt;p&gt;Bah, I can&amp;#8217;t keep pace with questions and responses in a fashion that does them justice. Best wait for the videos.&lt;/p&gt;

&lt;h2&gt;Eleanor McHugh - The Ruby Guide to *nix Plumbing&lt;/h2&gt;

&lt;p&gt;Unix isn&amp;#8217;t just a server based operating system, it&amp;#8217;s a philosophy. It consists of a whole heap of little tools that all receive a little piece of input and do just a little piece of work. And they can all work together to achieve much bigger tasks.&lt;/p&gt;

&lt;p&gt;Eleanor went through a bit of an explanation of how she felt the fascination on better threading in ruby is a bit stupid, and that the introduction of the threading approach we have in 1.8 was a backward step from 1.6. Most problems you can get around by forking the process, and threading is very rarely the appropriate solution to the problem.&lt;/p&gt;

&lt;p&gt;The shell system is simply a process which provides you an interactive environment, job/process management, and a scripting language. However, you can get around using the standard shell scripting languages by using the under-documented shell.rb.&lt;/p&gt;

&lt;p&gt;A little known fact is that the IO/File new methods don&amp;#8217;t just accept a string, but will also accept a file descriptor (which is just a number). So if you open 0, 1, or 2 you&amp;#8217;ll end up writing directly to STDIN, STDOUT, and STDERR respectively.&lt;/p&gt;

&lt;p&gt;Taking the approach further means that you can effectively communicate with any process in a similar fashion by sending signals to the appropriate process descriptors.&lt;/p&gt;

&lt;p&gt;When working with sockets in ruby, Eleanor said you should turn off reverse DNS lookups as they will greatly slow down network connection and tie up your processes needlessly.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s also a whole host of examples of using low level system calls and examples in the &lt;a href=&quot;http://slides.games-with-brains.net/&quot;&gt;slides&lt;/a&gt; which I&amp;#8217;ve no chance of transcribing quickly enough with the right context.&lt;/p&gt;

&lt;h2&gt;Lindsay Holmwood - Behaviour driven monitorins with cucumber-nagios&lt;/h2&gt;

&lt;p&gt;Everyone is probably familiar these days with what Cucumber is and the descriptive syntax it gives you for defining tests. You can combine it with webrat and mechanize to give you a way of monitoring external websites. To get started you need to install the gem and setup a new project:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install auxesis-cucumber-nagios
cucumber-nagios-gen project mysites
cd mysites
rake deps&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You then create a new feature, for the sake of example create one to test the navigation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cucumber-nagios-gen feature rails-underground.com navigation&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which will create the file features/rails-underground.com/navigation.feature. From there you can use all the usual cucumber/webrat commands to go to a page, click links, test for the result text. To run the test you:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cucumber-nagios features/rails-underground.com/navigation.feature&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;cucumber-nagios will then take care of taking the cucumber results and outputting them in a nagios plugin format.&lt;/p&gt;

&lt;p&gt;The caveats are that you&amp;#8217;re going to run problems if you site is javascript dependent. But you&amp;#8217;re embracing progressive enhancement and your site works fine without javascript, right? You could also run into some problems if you&amp;#8217;re trying to run multiple scenarios within the same feature file.&lt;/p&gt;

&lt;p&gt;The big benefits of this approach is that you end up making your system monitoring actually test what you care about. Traditionally these tests are just a ping or socket connection. While if you&amp;#8217;ve got a server down your tests will definitely fail, but there is a whole host of other cases where your site might be responsive but not usable by a real person (DB down?). Lindsay argues that this approach is really (and should be) continuous integration for systems monitoring.&lt;/p&gt;

&lt;p&gt;Some cool examples of people extending it include telephony-systems-test which allows you to test an Asterisk/Adhearsion telephony dial plan. cucumber+dash which pull metrics out of the hosted Dash metrics system to alert you of application performance problems.&lt;/p&gt;

&lt;p&gt;Lindsay went through what seemed like an awesome replacement for nagios that he&amp;#8217;s been working on, which is handling upto 6,000 tests per second. It&amp;#8217;s super top secret at the moment and didn&amp;#8217;t want specifics to go outside the room. He&amp;#8217;s auxesis on github, you join the dots.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve also got summaries for &lt;a href=&quot;/articles/2009/07/24/rails-underground---day-1/&quot;&gt;Rails Underground - Day 1&lt;/a&gt;&lt;/p&gt;</description>
          <pubDate>Sat, 25 Jul 2009 08:59:19 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/07/25/rails-underground---day-2/</guid>
          <link>http://rubypond.com/articles/2009/07/25/rails-underground---day-2/</link>
        </item>
    
        <item>
          <title>Rails Underground - Day 1</title>
          <description>&lt;p&gt;&lt;strong&gt;update&lt;/strong&gt; I&amp;#8217;ve also got summaries for &lt;a href=&quot;/articles/2009/07/25/rails-underground---day-2/&quot;&gt;Rails Underground - Day 2&lt;/a&gt;, plus &lt;a href=&quot;http://www.rails-underground.com/09-conference-schedule.html&quot;&gt;videos are now online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today kicks off the first day of talks for Rails Underground in London. Thankfully they&amp;#8217;ve got usable wifi, and two days of what sound like mostly excellent talks. So over the next couple of days I&amp;#8217;ll hopefully be able to post summaries of the various talks I&amp;#8217;m able to squeeze into.&lt;/p&gt;

&lt;p&gt;So first up&amp;#8230; &lt;/p&gt;

&lt;h2&gt;Fred George - Rails is a Hammer (Keynote)&lt;/h2&gt;

&lt;p&gt;Taking a queue from Martin Fowler&amp;#8217;s &amp;#8220;Patterns of Enterprise Application Architectures&amp;#8221; Fred goes in to discuss the various trade offs that happen in different application styles. Essentially, approaches that get you going quickly usually become exponentially more difficult as the complexity of your problem increases. Rails with it&amp;#8217;s &amp;#8220;convention over configuration&amp;#8221; offers a great way to prototype very quickly, but by Fowler&amp;#8217;s assumption this should get slower and slower to extend as your app complexity grows. So Fred decided to start from scratch, take his learnings from smalltalk and see how things would turn out on a new project.&lt;/p&gt;

&lt;p&gt;Models were just pure ruby, storing to a YAML persistance layer. Sinatra took control of the controllers, with HAML/SASS for the view layer. I turns out that with very little code, YAML provided an easy way to persist the objects quickly to disk. Incrementing filenames on each save also meant that object state was versioned, and actions were simple to undo/redo (and note we&amp;#8217;re talking full objects being serialised to disk with fill state, not just instance variables/attributes).&lt;/p&gt;

&lt;p&gt;Then to link the model with the view comes in Sinatra. It&amp;#8217;s so light and easy, does nothing more than it needs to, it&amp;#8217;s essentially just a set of regexps that push a request to the appropriate code. And how much more do you really need to do in most controllers?&lt;/p&gt;

&lt;p&gt;Next was the view, and for anyone using HAML there is nothing groundbreaking to learn here. It&amp;#8217;s awesome, heaps better than the prescribed ERB, and you should be using it (my conclusion on Fred&amp;#8217;s discussion and my own experience, don&amp;#8217;t flame him directly). It&amp;#8217;s not just less typing, the prescriptive structure makes the code more readable and being able to use variables in CSS is incredibly liberating and DRY.&lt;/p&gt;

&lt;p&gt;Some good debate post keynote on whether it was really a comparison of rails vs alternatives, or just a test project using stuff rails already offers you without using rails.&lt;/p&gt;

&lt;h2&gt;Gwyn Morfey - Refactoring with Fire&lt;/h2&gt;

&lt;p&gt;A high paced and amusing presentation about trying to refactor old apps. Why would you need to consider a rewrite? &amp;#8220;Maybe it was PHP on Rails, or some guys first Rails project&amp;#8221;. The options are burn it to the ground and start again, or try and refactor it. The default option should always be to try and refactor. It&amp;#8217;s usually tested, and it works, and if you re-write it you&amp;#8217;re basically shutting down and delivering absolutely nothing for an extended period town. At which point you eventually release, with the same feature set. And even if you&amp;#8217;re re-writing in an agile fashion, your first releases still have only a minor percentage of the features expected by the users and will be considered a fail.&lt;/p&gt;

&lt;p&gt;You refactor unless:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a very, very, very good reason to rewrite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You rewrite if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can drastically cut scope&lt;/li&gt;
&lt;li&gt;You won&amp;#8217;t stall the business&lt;/li&gt;
&lt;li&gt;You have access to the original coder&lt;/li&gt;
&lt;li&gt;The existing business logic is fundamentally wrong (the requirements have changed?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When going through the estimation phase, it&amp;#8217;s often not accurate to just take a cursory glance at the code and see how easy it is to understand. So much can be hidden under the surface that it&amp;#8217;s usually best to try a spike at implementing something new and see how easy it is.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re considering a re-write, you need to approach it as a complete outsider and say &amp;#8220;I know nothing, what does this thing need to do&amp;#8221;. Otherwise you open yourself up to the stealth feature that was hidden deep in the code that you lost in your re-write. Boot it up, use the application&amp;#8230; and watch the client use the application.&lt;/p&gt;

&lt;p&gt;To make it work and keep the client happy, make sure that any re-write is actually adding value to the existing system. Deliver early, deliver often.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s it on re-writing, next is how to make refactoring manageable. &lt;/p&gt;

&lt;p&gt;Gwyn also added in a shameless plug for his &amp;#8220;noisy partials&amp;#8221; plugin which will insert HTML comments in the rendered views to help you identify where exactly things are being rendered. The &amp;#8220;partial dependencies&amp;#8221; plugin will draw a nice pretty dependency graph showing the links between all the partials in a project.&lt;/p&gt;

&lt;p&gt;Split the long methods into smaller workable and meaningful chunks. You can then work on refactoring these bite sized pieces while you&amp;#8217;re working through the codebase. If there&amp;#8217;s code you don&amp;#8217;t understand, delete it and see what breaks. If nothing breaks, kiss it goodbye&amp;#8230; &amp;#8220;Deleted code is debugged code&amp;#8221;. Make sure that you&amp;#8217;re only working on the small bites, and get it back to a working state before you continue. Otherwise you&amp;#8217;ll forget what it was you were originally working on, and before you know it you&amp;#8217;ll have upgraded your entire rails stack and plugins and nothing works. And don&amp;#8217;t refactor code just because you hate it, much sure you hate it &lt;em&gt;and&lt;/em&gt; it&amp;#8217;s in your way.&lt;/p&gt;

&lt;p&gt;Check out Sequel as the database adapter if you&amp;#8217;re trying to move legacy data between SQL database schemas.&lt;/p&gt;

&lt;h2&gt;Desi McAdam - Working with Legacy Rails Apps - Technical Debt Hell and how to work your way out of it&lt;/h2&gt;

&lt;p&gt;Another talk on dealing with old rails projects and code, am I detecting a general theme here? So what constitutes legacy apps here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Old Rails versions&lt;/li&gt;
&lt;li&gt;No tests&lt;/li&gt;
&lt;li&gt;Complexity in architecture and design&lt;/li&gt;
&lt;li&gt;Violates best practices (fat controllers, poor separation, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essentially, code that is difficult to change. It all boils down to technical debt. &lt;/p&gt;

&lt;p&gt;At Hash Rocket they have rescue missions which they do for clients they inherit with these problems. First off they&amp;#8217;ll spend a couple of days doing a code audit. As Gwyn pointed out though, much of the detail isn&amp;#8217;t uncovered until you try and implement something.&lt;/p&gt;

&lt;p&gt;So what to do and how to make it workable?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pair all the f&lt;em&gt;*&lt;/em&gt;ing time. You need someone to check you and stop you from being sucked in to writing the same style of bad code. If you look at it long enough you&amp;#8217;ll start to find it normal.&lt;/li&gt;
&lt;li&gt;Be fearless. Take the risks and delete the code.&lt;/li&gt;
&lt;li&gt;Write tests. Use cucumber to wrap the main functionality to help give yourself a sense of stability.&lt;/li&gt;
&lt;li&gt;Stay focussed. At the point of change wrap tests around the current functionality, BDD the changes. And don&amp;#8217;t get distracted (at which point it an amp starts squealing in the background and disrupts the talk&amp;#8230; brilliant timing)&lt;/li&gt;
&lt;li&gt;Refactor. Always refactor with tests, and do it as you go. It helps estimate velocity, removes technical debt, and alleviates the broken windows problem.&lt;/li&gt;
&lt;li&gt;Use Git (or anything that lets you branch easily)&lt;/li&gt;
&lt;li&gt;Use your customer. Deliver early and often, and get them to help you test. They&amp;#8217;ve got the best idea of what it&amp;#8217;s meant to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The specific things hash Rocket do in their approach is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update the app to the latest rails version&lt;/li&gt;
&lt;li&gt;Update the plugins and external dependencies (or remove/un-fork where possible). &lt;/li&gt;
&lt;li&gt;Fix the easy stuff. Clean the formatting, remove comment code as you&amp;#8217;re unlikely to get much value from is.&lt;/li&gt;
&lt;li&gt;Use the free stuff. Replace custom code with built-in rails functionality, use new features (like named scopes) to decrease complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Obie Fernandez - Blood, Sweat, and Rails&lt;/h2&gt;

&lt;p&gt;Obie got introduced to ruby via Aslak of Cucumber fame back in 2004, with rails in 2005 for a client in London. &lt;/p&gt;

&lt;h3&gt;Sales &amp;amp; Marketing&lt;/h3&gt;

&lt;p&gt;First piece of advice, controversy can be useful. One of the first things Obie did was writing the top 10 reasons why Java sucks. Just make sure you can take the abuse, especially if you deserve it&amp;#8230; he&amp;#8217;s willing to admit his initial ideas for Rails Maturity Model sucked. Confidence always win. On the flip side of that, don&amp;#8217;t ever seem desperate. The moment you go in and convey, even subconsciously, that you need the work you make the client wonder why you need the work. They&amp;#8217;d much rather work with someone who is in demand. Referrals will be the lifeblood of your business, so go ahead and videotape your clients. Get them used to it, video meetings, testimonials, and help document the project. It&amp;#8217;s a tactical nuclear weapon.&lt;/p&gt;

&lt;p&gt;Make it personal, pick up the phone and call a potential client. It&amp;#8217;s way too easy to just fire off an email or IM.&lt;/p&gt;

&lt;h3&gt;Legal Matters&lt;/h3&gt;

&lt;p&gt;You need to write bulletproof contracts. Keeping them simple is not ideal, too many potential problems. Master services agreements, warranties, digital signing/acceptance, etc. all need to be included. Don&amp;#8217;t negotiate under pressure. You&amp;#8217;ll end up agreeing to things that you shouldn&amp;#8217;t to and it will cost you more in the long run. And when things go wrong, lawyers cost a lot of money.&lt;/p&gt;

&lt;h3&gt;Finances&lt;/h3&gt;

&lt;p&gt;Don&amp;#8217;t undercapitalise. Don&amp;#8217;t do fixed bid contracts. None of Hash Rocket&amp;#8217;s contracts state a deliverable, you&amp;#8217;re buying time and expertise. There is no definition of scope. By documenting scope you&amp;#8217;re breaking the philosophy of agile and you lose the ability to adjust scope. You&amp;#8217;ll probably need to gather some momentum before these are applicable. Make sure you charge what you are worth (a slide showing that Obie billed out at $250/hr, other devs at $190/hr for short term work $150/hr for anything greater than 6 months). Allow some budget for non-paying clients. When you&amp;#8217;re extending credit, some times they&amp;#8217;re just not going to pay (either because they&amp;#8217;re bastards, they ran out of funding, they&amp;#8217;ve drained the kids college fund, etc.). Allow some budget for product development, everyone wants to be 37signals eventually. Don&amp;#8217;t invoice manually, Harvest is a good example of how to handle it easily.&lt;/p&gt;

&lt;h3&gt;Agile Practices&lt;/h3&gt;

&lt;p&gt;You shouldn&amp;#8217;t have to defend agile. Just start from the assumption that &amp;#8220;this is how we work&amp;#8221; and that it&amp;#8217;s that the normal case, then you&amp;#8217;re not having to justify a change in approach. Always do agile by the book first, don&amp;#8217;t try and tweak it and then wonder why it doesn&amp;#8217;t work. Storycard the work, either on index cards or in something like Pivotal Tracker.&lt;/p&gt;

&lt;h3&gt;Client Relationships&lt;/h3&gt;

&lt;p&gt;Execution is absolutely critical. If you&amp;#8217;re not consistently striving for excellence then it&amp;#8217;s all worthless. Going hand-in-hand with that is perception is reality. If you can&amp;#8217;t relay to the client that you&amp;#8217;re doing an excellent job then it&amp;#8217;s worthless also. Bend the rules, the client just wants a result and doesn&amp;#8217;t really care how you go about it. In some cases you should even break the rules. Another simple one is to establish contact, especially with big value contracts, call them every day. Mind their budget, especially if you&amp;#8217;ve made the jump to time based contracts. The responsibility falls back on to you to make sure you&amp;#8217;re not burning through all their cash so have transparency on who&amp;#8217;s working and what the cash burn rate is. Do what you can to win their people over. Fire clients if they deserve to be fired. Hire people on a contract to perm basis &lt;em&gt;(bah! I say they should all be contractors if they&amp;#8217;re any good)&lt;/em&gt;. Keep your employees constantly learning. And make them pair all the time. Empower your employees for change, be open for them to challenge the generally accepted practices (like pairing all the time). You need to actively work to make that possible. Make the work environment appealing and always have fun. Keep everyone in the loop all the time.&lt;/p&gt;

&lt;h2&gt;Charles Nutter - The Present and Future of JRuby (and the Future of Rails as it relates to JRuby)&lt;/h2&gt;

&lt;p&gt;The current version of JRuby is 1.3.1, it&amp;#8217;s ruby 1.8.6 compatible (give or take, it can&amp;#8217;t do continuations and some other things). Has some ruby 1.9 support (somewhere 75%-90% done). &lt;/p&gt;

&lt;p&gt;It&amp;#8217;s roughly equivalent in performance terms to ruby 1.9, with real native threads and runs rails fine. It takes at least 0.5secs to start up, but can take several seconds so it&amp;#8217;s not great. Once up, it should be faster than 1.9 in almost all cases. Most ruby application bottlenecks are in the core classes and not ruby itself (string manipulations, working with hashes, etc.) and the JRuby performance in these classes is mixed which makes providing meaningful benchmarks almost impossible. Some cases are great, others are bad. Also because of the iterative optimisations that the JVM does internally a single run of an application doesn&amp;#8217;t show real world performance. To demonstrate Charles ran a fractal generation program 5 times and you could see how much quicker the latter runs were.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s the only ruby implementation with true native threads. Again another demonstration showing how with JRuby you can effectively max out two cores, yet with regular ruby, even 1.9, you only ever really get the equivalent of 1 core working (spread across the two cores). Next was a really cool demo that I&amp;#8217;ll do no justice here. Basically using FFI to call C functions and have them then execute ruby callbacks.&lt;/p&gt;

&lt;p&gt;Next was a demo of starting an app (Typo) using Glassfish. Just download the gem, go into the app and:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;quot;glassfish -e production&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&amp;#8217;re running threadsafe rails it will start just one instance of the JVM and keep memory usage low. In any event, it takes care of concurrency and all the usual problems for you.&lt;/p&gt;

&lt;h3&gt;Ruby 1.9 support&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s at about maybe 80% of 1.9.1. The 1.9.2 release adds a bunch more, but they&amp;#8217;d like some help (so get in touch if you&amp;#8217;re interested/able). He also gave a cool example of a change to regexps in 1.9 that I&amp;#8217;d not seen. If you want to extract a grouped match from a regexp pattern you&amp;#8217;d normally do something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;str = &amp;quot;Welcome to Rails Underground&amp;quot;
matched = str.match(/Welcome to Rails (.*)/)
matched[1] == &amp;quot;Underground&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem is if you change the regexp to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;matched = str.match(/(Welcome) to Rails (.*)/)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;matched[1] now becomes &amp;#8220;Welcome&amp;#8221; rather than underground, and your code brakes. In ruby 1.9 you can name grouped matches:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;str = &amp;quot;Welcome to Rails Underground&amp;quot;
matched = str.match(/Welcome to Rails (?&amp;lt;conf&amp;gt;.*)/)
matched[:conf] == &amp;quot;Underground&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;What&amp;#8217;s missing?&lt;/h3&gt;

&lt;p&gt;One thing that isn&amp;#8217;t missing is 1.8 compatibility, it&amp;#8217;s a mostly solved problem. There are some edge cases that wont work, but it&amp;#8217;s got the best coverage of all the alternative estimates. On the todo list is better performance, better java integration. To highlight some of the upcoming performance improvements Charles went through the intermediate code the new compiler generates which was quite fascinating to see. Makes me glad I don&amp;#8217;t have to build compilers for a living though. As a result there is also a &amp;#8220;ruby2java&amp;#8221; executable which generates java classes from ruby code now. And to further help with the java and ruby integration there is a &amp;#8220;become_java&amp;#8221; method you can call on a ruby class to turn it into an object that can be used natively within java.&lt;/p&gt;

&lt;p&gt;The other tasks are rubifying the java libraries. Hibernate, Ant, Maven, etc. It&amp;#8217;s basically an attempt to keep all of the rich functionality and performance that java offers, without the inherent java ugliness. The big news is that Hibernate is basically done now and just needs to be wrapped up in a nice ruby DSL. But you can use Hibernate as a persistance layer in JRuby now.&lt;/p&gt;

&lt;h3&gt;How can you help&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use JRuby every chance you get&lt;/li&gt;
&lt;li&gt;Help improve JRuby (especially 1.9)&lt;/li&gt;
&lt;li&gt;Start evangelising ruby at java conferences&lt;/li&gt;
&lt;li&gt;Study Groovy, Scala, Clojure, etc&lt;/li&gt;
&lt;li&gt;Study java libraries and help rubify them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Gwyn Morfey (filling in for Laurie Young) - Agile Deployment with Ruby&lt;/h2&gt;

&lt;p&gt;You&amp;#8217;re going to need a lot of servers, so you may as well make the job as easy as possible. You&amp;#8217;ve got lost of serving options, you should be using passenger though. There&amp;#8217;s now Ruby Intelligent Packaging called RIP which is great and you should use it, except it doesn&amp;#8217;t work&amp;#8230; so just keep an eye on it. You also need to have continuous integration setup and working. CruiseControl.rb isn&amp;#8217;t great but it works. &lt;/p&gt;

&lt;p&gt;As far as actually deploying, capistrano is there. But use webistrano, it&amp;#8217;s a thin layer over capistrano. The main benefit is you get an audit history so you can see who deployed what, where, and when. Next is puppet to manage your server config. It&amp;#8217;s not as quick is making disk images, but it&amp;#8217;s more flexible and much easier to maintain &lt;em&gt;(Personally, I&amp;#8217;d advocate Chef instead of puppet)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You need multiple servers (either actual dedicated iron for each, or virtualised environments) to deploy to. A test server for external testers and/or clients to run through the completed development prior to a production deployment. A pre-production server that closely mirrors the production server. It&amp;#8217;s there as a final sanity check prior to going live, and there to check there isn&amp;#8217;t some configuration difference on the production box that will trip you up. Make sure you test both the up and down migrations, it should work, but it often doesn&amp;#8217;t. And there is nothing worth than discovering the rollback won&amp;#8217;t work once you get to production.&lt;/p&gt;

&lt;p&gt;On production, make sure you&amp;#8217;ve got notifications setup. &amp;#8220;Exception Notifier&amp;#8221;, &amp;#8220;Get Exceptional&amp;#8221;, &amp;#8220;HopToad&amp;#8221;, &amp;#8220;New Relic&amp;#8221; test them all and make a call, just use one. Service monitoring, make sure things stay up with monit or god. To help with peak loads consider a Content Delivery Network like Limelight Networks.&lt;/p&gt;

&lt;p&gt;You&amp;#8217;ll probably need a debug server. If you push things all the way to production and you get errors, it&amp;#8217;s quite possibly data related. You need to copy the logs, assets, and all other data over to try and work through. In practice, New Bamboo don&amp;#8217;t run a separate debug server but just re-provision pre-production very quickly (it&amp;#8217;s there, it&amp;#8217;s got the production code already, it&amp;#8217;s almost ready to go).&lt;/p&gt;

&lt;h2&gt;Martin Kleppmann - Sales &amp;amp; payments in your app&lt;/h2&gt;

&lt;p&gt;The Ruby Invoicing Framework tries to give a solid foundation where you can build a solid web application. It offers a few classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invoice - you owe us money&lt;/li&gt;
&lt;li&gt;Credit note - oops you billed to much&lt;/li&gt;
&lt;li&gt;Payment -thanks for the cash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They all inherit from LedgerItem which throws is a naming throw back to accounting terms, but it essentially offers you access to discrete billing line items and two companies, one on each side of the transaction. What it gives you for free is an automatically rendered invoice (an actual invoice you can post/email to the client) with all the legally required fields included.&lt;/p&gt;

&lt;p&gt;Accountant need to know the exact dates of transactions, that bank statements reconciling, and VAT/sales or other applicable taxes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;insert various slides about accounting practices and how ledger items are calculated. I&amp;#8217;d expect anybody who runs their own business already knows all this stuff&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve had to roll most of this stuff myself over the past 12-18 months, and for the most part our schemas and approach is almost identical. Just to save myself the maintenance headache, I&amp;#8217;ll probably look at porting over to this invoicing gem. I also need to look at the existing open standards (UBL, XBRL-GL, OAccounts, and OASIS) and see how they fit in.&lt;/p&gt;

&lt;h2&gt;George Palmer - CouchDB and Ruby&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve covered the background on what CouchDB is in previous posts, or it&amp;#8217;s otherwise readily available with a quick search so I&amp;#8217;ll leave you to find the really high level stuff out yourself. Documents are stored as JSON, you get subsets of documents via views. Done.&lt;/p&gt;

&lt;p&gt;Unlike relational databases which you pay a performance hit on indexes when you insert data, CouchDB makes you pay the penalty on the first read of a view. That means if you path insert a bunch of data, the next request to see that information is going to be slow. In a typical read heavy web application, this isn&amp;#8217;t that noticeable. If you&amp;#8217;re inserting data often, then there are ways to mitigate the problem.&lt;/p&gt;

&lt;p&gt;So when should you use CouchDB? If you want a schema-less database. FriendFeed was used as an example, given the amount of data they store adding a new column in MySQL could take several hours. Often it also relates more directly to your real-world models. George went through an example from constructing his &amp;#8220;5ft Shelf&amp;#8221; site and the complexities associated with books (numerous ISBNs, different titles in different countries, difference retail prices in different locales, different editions, etc.) and how difficult it is to map all these permutations in a relational system. The final scenario is when you know you&amp;#8217;re going to need replication or sharding, either for offline capability or scaling.&lt;/p&gt;

&lt;p&gt;You shouldn&amp;#8217;t use it is when your problem domain is very fixed. Finance is a good example, real estate transactions are another.&lt;/p&gt;

&lt;p&gt;Enter George&amp;#8217;s couch_foo plugin which is a way of interfacing with CouchDB in an ActiveRecord fashion. Because everything is ultimately stored as JSON, there&amp;#8217;s no real concept of datatypes. So long as the attributes can be translated to JSON and reconstructed from JSON you&amp;#8217;re good to use any datatype/object you type. But the plugin does natively support validations, associations, callbacks, and pretty much everything you&amp;#8217;d expect from AR. One gotcha is that if you try and order by an attribute that isn&amp;#8217;t exposed by the key, it will return &lt;em&gt;all&lt;/em&gt; the results and then order them in ruby. It&amp;#8217;s a double sting if you then try and limit, as you&amp;#8217;ve pulled back a heap of records you never needed.&lt;/p&gt;

&lt;p&gt;Performance wise, George said there&amp;#8217;s a whole heap of naive benchmarks claiming CouchDB is faster than this or that. It&amp;#8217;s a different approach, some things are going to be quicker, some are going to be slower. The latest CouchDB release (0.9) does offer some speed improvements over previous versions though.&lt;/p&gt;</description>
          <pubDate>Fri, 24 Jul 2009 08:54:50 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/07/24/rails-underground---day-1/</guid>
          <link>http://rubypond.com/articles/2009/07/24/rails-underground---day-1/</link>
        </item>
    
        <item>
          <title>Scotland on Rails 09 - Videos are up</title>
          <description>&lt;p&gt;Not much more to say really, the title sums it up. For those that weren&amp;#8217;t there or those that were that just want a recap go and check out the &lt;a href=&quot;http://www.engineyard.com/blog/community/scotland-on-rails/&quot;&gt;Scotland on rails videos&lt;/a&gt; now.&lt;/p&gt;

&lt;p&gt;And I &lt;em&gt;will&lt;/em&gt; eventually get around to doing that round-up of the post/out-of-conference activities to do should you be looking to attend the conference yourself next year.&lt;/p&gt;</description>
          <pubDate>Thu, 21 May 2009 10:41:37 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/05/21/scotland-on-rails-09---videos-are-up/</guid>
          <link>http://rubypond.com/articles/2009/05/21/scotland-on-rails-09---videos-are-up/</link>
        </item>
    
        <item>
          <title>Belated Scotland on Rails round up</title>
          <description>&lt;p&gt;Okay, so I&amp;#8217;m almost a month and a half late in finishing this. And the content might already seem a little dated given &lt;a href=&quot;http://www.railsconf.com/&quot;&gt;RailsConf&lt;/a&gt; is currently on in Vegas and &lt;a href=&quot;http://euruko2009.org/&quot;&gt;EuRuKo&lt;/a&gt; kicks off this weekend in Barcelona. But better late than never.&lt;/p&gt;

&lt;h2&gt;The Summary&lt;/h2&gt;

&lt;p&gt;So in summary, how was it? Pretty good and great value. It wasn&amp;#8217;t blow my mind amazing, but there was enough good stuff going on to justify the trip. Plus Scotland is a beautiful country, and Edinburgh in-particular a great city, so any means of justifying a business expense to get&amp;nbsp;there&amp;nbsp;is&amp;nbsp;worthwhile&amp;nbsp;;)&lt;/p&gt;

&lt;p&gt;So onto the sessions I saw or chatted in depth to people about.&lt;/p&gt;

&lt;h2&gt;Sessions&lt;/h2&gt;

&lt;h3&gt;Keynote - Marcel Molina Jr&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;d heard of Marcel before, I&amp;#8217;d even seen his name grace the cover of some books I own, but I didn&amp;#8217;t know much about him beyond that. For those like me, he was one of the original core team at 37signals that worked on Rails. And his keynote was quite a personal look at the beginnings of the framework. Digging up old usenet posts from DHH showing how he&amp;#8217;s trying to learn ruby, to slowly building the hype around rails, to a public release. For a presentation that was essentially reading old emails and newsgroup postings I found it thoroughly enjoyable. It was particularly interesting to see just how quickly DHH went from new to ruby to releasing probably one of the most widely used tools written in the language.&lt;/p&gt;

&lt;h3&gt;Implementing Geo-awareness - Jim Remsik&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;d had big hopes for this presentation. I&amp;#8217;ve dabbled with geo-awareness stuff before, heck I&amp;#8217;ve even written my own rails mapping plugin because I thought YM4R and the alternatives weren&amp;#8217;t very ruby (btw. it&amp;#8217;s in use for the &lt;a href=&quot;http://map.ly/&quot;&gt;collaborative mapping/direction&lt;/a&gt; site I quickly rustled up for my girlfriend &lt;a href=&quot;http://map.ly/&quot;&gt;Map.ly&lt;/a&gt;). I was really looking at some idea re how to make an existing site more &amp;#8220;geo aware&amp;#8221;, and this presentation was little more than &amp;#8220;how to put a google map on your site 101&amp;#8221;. For all my complaints about the existing plugins and their approach, they&amp;#8217;re still quite simple to use. With any level of ruby/rails knowledge, this talk could have probably been reduced to 5-10mins.&lt;/p&gt;

&lt;h3&gt;Getting Git: Getting effective project management - Scott Chacon&lt;/h3&gt;

&lt;p&gt;Scott is part of the team at Logical Awesome working on Github. He&amp;#8217;s also done the peepcode on git, and maintains the community book. He really knows his git, and by all accounts I&amp;#8217;m disappointed I missed this one for the geo-awareness session. Thankfully the guys I pair with most days, &lt;a href=&quot;http://www.effectif.com&quot;&gt;Graham Ashton&lt;/a&gt; and Jon Ramsey, went and filled me in somewhat on it. The first half was a bit of an introduction on what it is, why it&amp;#8217;s different, how to use it, etc. that could mostly be ignored if you&amp;#8217;ve used it at any length. Apparently the second half of the talk (which unfortunately he tried to cram into 10mins) was amazing. Showing how to use bisect to identify which commit introduced a bug as one of the highlights. The slides are available at &lt;a href=&quot;http://github.com/schacon/git-presentations/tree/master&quot;&gt;github&lt;/a&gt; and hopefully the videos will be up soon.&lt;/p&gt;

&lt;h3&gt;Ruby on the couch eating potatoes - Alexander Lang&lt;/h3&gt;

&lt;p&gt;A well times presentation for my perspective. I&amp;#8217;ve been looking at a number of relational database alternatives of late for one of my side projects, and &lt;a href=&quot;http://couchdb.apache.org/&quot;&gt;CouchDB&lt;/a&gt; had come up as one of the most likely contenders. So I&amp;#8217;d done a fair degree of research on CouchDB itself, but not much on the most suitable adapter for using it with rails.&lt;/p&gt;

&lt;p&gt;Alex did a good job going through all the various know adapters for talking to CouchDB (including his own, CouchPotato) and pointed out the pros and cons of each. Amazingly for a presentation like this he admitted that you should avoid his. For those interested, the winner was Paul Carey&amp;#8217;s &lt;a href=&quot;http://github.com/paulcarey/relaxdb/tree/master&quot;&gt;RelaxDB&lt;/a&gt;. A point of contention which spilled onto the twittersphere was Alex&amp;#8217;s recommendation to avoid George Palmer&amp;#8217;s &lt;a href=&quot;http://github.com/georgepalmer/couch_foo/tree/master&quot;&gt;CouchFoo&lt;/a&gt; (George was in the audience). The rationale being that CouchFoo, much like CouchPotato, is too &amp;#8220;ActiveRecord&amp;#8221; and that document-based databases are different to relational databases so this means the approach must be inherently wrong.&lt;/p&gt;

&lt;p&gt;Personally I think no, the rationale is wrong. Sure, you don&amp;#8217;t want to treat CouchDB like a relational database because you&amp;#8217;re missing the benefits gained in the document approach and kind of missing the whole point. But that doesn&amp;#8217;t mean ActiveRecord for CouchDB is wrong. ActiveRecord does not &lt;em&gt;have to&lt;/em&gt; mean Object Relational Mapper, it&amp;#8217;s just up until this point it&amp;#8217;s all people have used it for. In fact, there is is nothing in the name ActiveRecord that inherently infers it is only for relational schemas. I think if people had grown up being accustomed to AR being an Object Document Mapper instead of an ORM then this argument would be moot. In rails you interface with an object, the adapter takes care of how to store it be-it in a document store or a relational store. We&amp;#8217;ve got a pretty well documented API for AR, with lots of validation rules and other plugins that are useful. If you then decide to go build a relational schema in your document database that isn&amp;#8217;t the fault of CouchFoo, just like AR can&amp;#8217;t be blamed if you decide to try and keep everything in a single big flat table in MySql. &lt;/p&gt;

&lt;p&gt;My own conclusion after some research was the two best adapters out there were RelaxDB and CouchFoo. RelaxDB seems the best (I&amp;#8217;ll go into details in a future post) but CouchFoo is ideal if you want to transition quickly or need access to some of the AR helpers/mixins. So all in all, a good presentation and made me go back and re-assess my own research on the topic and we ultimately shared the same conclusion albeit with different reasoning.&lt;/p&gt;

&lt;h3&gt;Merb and Rails 3.0 - Yehuda Katz&lt;/h3&gt;

&lt;p&gt;Probably not a lot to go through here which wont be out of date due to RailsConf. An interesting and high-paced presentation from Yehuda on what&amp;#8217;s coming in rails 3.0, some of the design decisions, etc. Probably not a huge amount of new information for anybody that had been using merb or following the public updates.&lt;/p&gt;

&lt;h3&gt;In Praise of non-fixtured data - Kevin Barnes&lt;/h3&gt;

&lt;p&gt;I often wonder how I&amp;#8217;d go on stage in front of a bunch of peers, but I&amp;#8217;m thankful that many of the presenters at these conferences looks as nervous up there as I&amp;#8217;d be. Kevin made me rethink if I should ever bother. A really excellent and clear presenter that was a joy to listen to.&lt;/p&gt;

&lt;p&gt;That being said, I didn&amp;#8217;t take from this as much as I&amp;#8217;d hoped. It&amp;#8217;s my own fault as the talk was exactly what was presented on the label, mostly about why you shouldn&amp;#8217;t use fixtured data and then a look at what the alternatives are. I was looking for a bit more of a detailed comparison of the pros/cons of each of the object factory approaches (much like Alex had done in the CouchDB talk) but it was really just a cursory mention of them all and then a look at how to use the one Kevin had developed, ObjectDaddy.&lt;/p&gt;

&lt;h3&gt;Confessions of a PackRat - Scott Raymond&lt;/h3&gt;

&lt;p&gt;I only caught the tail-end of this talk, but from those I spoke to it was quite insightful. Scott went into detail about how the developed a Facebook app and then needing to scale quickly to deal with the load. Everything from scaling into EC2, switching between technologies, and having to handle people trying to game the system. The 10 mins I saw were thoroughly enjoyable.&lt;/p&gt;

&lt;h3&gt;Advanced Deployment - Johnathon Weiss&lt;/h3&gt;

&lt;p&gt;This is one that I felt wasn&amp;#8217;t at all what was described on the label. I&amp;#8217;d normally consider deployment something more akin to &amp;#8220;getting your stuff onto servers&amp;#8221;. Instead this covered lots of high-level architectural options you have available to you, the alternatives for each, but without any real explanation on why you should choose one over another. An interesting topic, but pitched to the wrong crowd with the wrong name I feel. Much better for manager types with little-to-no hands on rails experience. I think anybody who&amp;#8217;s actually deployed an application would have known the answers to all the theoretical questions raise.&lt;/p&gt;

&lt;h3&gt;The Ruby Object Model - Dave Thomas&lt;/h3&gt;

&lt;p&gt;The guy that brought is the Pragmatic Programmers and a number of ruby books and videos from that stable gave a great presentation on the object model with ruby. The shoeless maestro strutted around the stage and made what could be a very dull and overly technical topic seem approachable and simplistic. When you call a method where does it look to first to run it? Where does it bubble up to? In what order? And how do you access an anonymous method? All this arnd more was answered! Not sure if I picked up anything new, but it was a great cementing of my understanding in a highly graphical fashion. 6 weeks on when I&amp;#8217;m debugging the internals of something I&amp;#8217;m still visualising Dave&amp;#8217;s charts in my head to help me. Much of the content you can go through at leisure and in more detail in the $5 videos from &lt;a href=&quot;http://www.pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming&quot;&gt;pragprog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;R-house - Fernand Galiana&lt;/h3&gt;

&lt;p&gt;Fernand took the noble risk of trying to do a live demonstration of the possibilities of using home automation with ruby. Thankfully for the most part it worked, and when it didn&amp;#8217;t he was entertaining enough to cover it and continue. And I have to appreciate the level of work that has gone into R-house and the libraries it depends on to make this happen, with such a range of different home automation equipment out there and each with there own slight nuances on how to interface it can&amp;#8217;t have been a simple job. A great presentation, not sure how soon I&amp;#8217;ll be able to use any of it though.&lt;/p&gt;

&lt;h3&gt;How to makes a successful Rails app - Steven A Bristol&lt;/h3&gt;

&lt;p&gt;A presentation with no slides?! The horror!! Steven was another excellent presenter, and with a great presentation to boot. He went into what it takes to actually make a successful Rails app (hint: actually releasing it is a big part), and the advice was sound. The other big one which I think many developers ignore, I know I&amp;#8217;ve been guilty of it, is trying to do the design yourself. Pay for a few days of their time and make it look professional. He was awfully opinionated on a number of topics without any real basis. That was fine when I agreed with him, I thought he was full of shit when he didn&amp;#8217;t justify it ;) One point that niggled at me throughout most of the presentation was that the reason I know of Steven and his company was through the the open-source &lt;a href=&quot;http://lovdbyless.com/&quot;&gt;Lovd by Less&lt;/a&gt; social networking framework they&amp;#8217;d built in rails. I&amp;#8217;d needed something like it once upon a time and looked at Lovd, and the code was horrible. So here I was being lectured by someone on how to make a Rails app who&amp;#8217;d produced some of the ugliest code I&amp;#8217;d tried to use. &lt;/p&gt;

&lt;p&gt;Then the bombshell hit (paraphrasing), &amp;#8220;I don&amp;#8217;t care what the code looks like if it works, just get it out the door and see if people like it. Anybody who&amp;#8217;s seen some of our code will know it&amp;#8217;s horrible&amp;#8221;. And he was right, on all counts. But&amp;#8230; I still had hesitations reservations. This was an open source framework, so the consumers in this instance are developers. So for the same reasons that you should get a designer to make your site look good for regular punters, I think you should take the time to make your code elegant and usable for developers. He&amp;#8217;s got a great looking product which does what it needs to, it&amp;#8217;s a shame that it&amp;#8217;s such a pain to use and made me question the validity of what he was saying. To that end, and rather than continuing to pay other developers to extend my own social networking engine I&amp;#8217;ve taken it upon myself to fix everything I think is broken with Lovd. There&amp;#8217;s still a long way to go and I&amp;#8217;ll make a more formal announcement once it&amp;#8217;s nearer completion but it&amp;#8217;s already come a long way IMHO. Get it from &lt;a href=&quot;http://github.com/rubypond/lovd-by-less/tree&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Who needs Photoshop? Image manipulation in Ruby - Cory Forsyth&lt;/h3&gt;

&lt;p&gt;Reading through this initially I thought it was going was a bit of a sensational headline for what was going to be an intermediate level look at rmagick. And given my own experience with rmagick, I couldn&amp;#8217;t possibly stomach the thought of it ever being considered a viable photoshop replacement. I was wrong.&lt;/p&gt;

&lt;p&gt;This was another thoroughly entertaining and informative presentation. Cory went through in detail the logic behind the one feature that has been making me want to upgrade to the latest version of photoshop, &lt;a href=&quot;http://www.youtube.com/watch?v=019mu8FTy6M&quot;&gt;content aware scaling&lt;/a&gt;, complete with code samples. Next up was facial recognition which could be applied to suggest smart cropping, or apparently put party hats on cats. It&amp;#8217;s most likely made my CS4 upgrade redundant, which paid for the trip numerous times over.&lt;/p&gt;

&lt;h3&gt;Edgecase dialog: Ruby code review - Joe O&amp;#8217;Brian and Jim Weirich&lt;/h3&gt;

&lt;p&gt;It sounded like a boring topic, it should have been a boring topic, and a very odd note on which to end a conference. It turns out Joe and Jim are brilliant entertainers taking the audience through a hypothetical role play of a consultant coming in to refactor an existing rails code base. While it&amp;#8217;s unlikely they&amp;#8217;ll be invited back to do their return for the Edinburgh Fringe Festival in August, they thoroughly deserved their rapturous applause at the end. I&amp;#8217;ve not got any notes unfortunately, I&amp;#8217;m not sure if that&amp;#8217;s because I was laughing too hard or most of it was common sense. In any event, it was a great reminder that you should step back and look at you code to make sure you aren&amp;#8217;t trying to be clever for the sake of it. Simple solutions are often the best.&lt;/p&gt;

&lt;h2&gt;Seeya next year&lt;/h2&gt;

&lt;p&gt;It was well worth the trip. The conference was super cheap so it&amp;#8217;s really not hard to justify the expense and Edinburgh is a great place to visit. I&amp;#8217;ve been there as both a tourist and lived there for 12 months, so I&amp;#8217;ll do a subsequent post for those looking to attend next year with my own off-conference highlights.&lt;/p&gt;</description>
          <pubDate>Fri, 08 May 2009 13:15:08 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/05/08/belated-scotland-on-rails-round-up/</guid>
          <link>http://rubypond.com/articles/2009/05/08/belated-scotland-on-rails-round-up/</link>
        </item>
    
        <item>
          <title>Capturing a form cancel</title>
          <description>&lt;p&gt;I&amp;#8217;ve been meaning to write this one up for months now, ever since I originally posted the &lt;a href=&quot;http://rubypond.com/articles/2008/07/16/sexy-forms-in-rails/&quot;&gt;sexy forms in rails&lt;/a&gt;. The form builder I talk about in that post makes it easy to put a submit and cancel button on a the form, and a few people have asked how to handle the cancel action. Some have suggested using javascript to redirect back using an onclick, ick! What happens if the user doesn&amp;#8217;t have javascript support? Sure you might try and justify it by saying, &amp;#8220;Well, how many users don&amp;#8217;t have javascript these days?&amp;#8221; but there is absolutely no reason why this &lt;em&gt;has&lt;/em&gt; to use javascript, so lets make it work for &lt;em&gt;everybody&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s actually much easier than you&amp;#8217;d think, within &lt;em&gt;application.rb&lt;/em&gt; I&amp;#8217;ve got the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ApplicationController &amp;lt; ActionController::Base
  before_filter :catch_cancel, :update =&amp;gt; [:create, :update, :destroy]
  after_filter :set_referrer, :only =&amp;gt; [:index, :show]

  private
    def set_referrer
      session[:referrer] = url_for(params)
    end

    def catch_cancel
      redirect_to session[:referrer] if params[:commit] == &amp;quot;Cancel&amp;quot;
    end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The logic being, that if we&amp;#8217;ve got a fully RESTful architecture the only pages we&amp;#8217;ll ever want to go &amp;#8220;back&amp;#8221; will be the index or show actions on each controller. So we cheekily call url&lt;em&gt;for in an after filter with the current params to get the path of the page we&amp;#8217;ve just display the user, and stash it in the session. Theoretically it may be possible to use ENV[&amp;#8220;HTTP&lt;/em&gt;REFERER&amp;#8221;] instead but it&amp;#8217;s not guaranteed, this approach however ensures we keep track of the page to go back to explicitly ourselves.&lt;/p&gt;

&lt;p&gt;Then, to piece it all together there&amp;#8217;s a before filter checking if the user has clicked the submit button labeled with &amp;#8220;Cancel&amp;#8221;. You&amp;#8217;ll need to change that equality test dependent on what text you put on your button. You may also need to move the before filter into the controllers that require them, depending on the order it needs to run with other filters you have.&lt;/p&gt;

&lt;p&gt;Hope that helps.&lt;/p&gt;</description>
          <pubDate>Fri, 06 Feb 2009 22:40:02 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/02/06/capturing-a-form-cancel/</guid>
          <link>http://rubypond.com/articles/2009/02/06/capturing-a-form-cancel/</link>
        </item>
    
        <item>
          <title>Ruby Manor Videos Available</title>
          <description>&lt;p&gt;For anybody that was unable to attend (like me), or for those that just want a recap then a selection of the &lt;a href=&quot;http://rubymanor.org/videos/&quot;&gt;Ruby Manor videos&lt;/a&gt; are now available for download. Hopefully some more will be posted soon.&lt;/p&gt;

&lt;p&gt;For any of the bits that are missing you can read through Graham&amp;#8217;s review of the various sessions. &lt;a href=&quot;http://effectif.com/2008/11/22/notes-from-the-ruby-manor&quot;&gt;Ruby Manor part 1&lt;/a&gt; and &lt;a href=&quot;http://effectif.com/2008/11/23/notes-from-the-ruby-manor-part-2&quot;&gt;Ruby Manor part 2&lt;/a&gt;&lt;/p&gt;</description>
          <pubDate>Fri, 16 Jan 2009 14:38:44 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/16/ruby-manor-videos-available/</guid>
          <link>http://rubypond.com/articles/2009/01/16/ruby-manor-videos-available/</link>
        </item>
    
        <item>
          <title>scRUBYt! Gets Plugins!</title>
          <description>&lt;p&gt;Yes! You heard right! As you may have gathered, it&amp;#8217;s been a rather frantic month of development for scRUBYt! and currently this is the addition I&amp;#8217;m most proud of. One of the most common requests used to be along the lines of &amp;#8220;when do you plan to support xxx format output?&amp;#8221;. Now, scRUBYt! is oblivious to output formats. That&amp;#8217;s right, it natively supports nothing, nada, zilch. But to make it useful, we&amp;#8217;ve written a Hash output plugin which we&amp;#8217;re shipping it with.&lt;/p&gt;

&lt;h2&gt;How to use a scRUBYt! output plugin&lt;/h2&gt;

&lt;p&gt;Firstly, you need to make sure you have the plugin you require installed. At the time of writing there will only be the two I&amp;#8217;ve written, Hash and XmlFile. Then in your ruby file require the plugin. As the current edge release isn&amp;#8217;t yet packaged as a gem you&amp;#8217;ll need to test this with the github checkout and reference the output plugin explicitly:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;quot;plugins/scrubyt_xml_file_output/scrubyt_xml_file_output&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&amp;#8217;ve been following the tutorials talking about &lt;a href=&quot;http://rubypond.com/articles/2009/01/15/web-scraping---the-amazon-example-finale/&quot;&gt;web scraping&lt;/a&gt; with the new version for the past few weeks you&amp;#8217;ll have seen how to direct output to a plugin. To request Hash output it&amp;#8217;s:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new :output =&amp;gt; :hash do
    fetch &amp;quot;http://www.google.com/search?&amp;amp;q=ruby&amp;quot;
    result &amp;quot;//html/body/div[5]/div/div/h2/a&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and for XmlFile it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@file = File.open(&amp;quot;results.xml&amp;quot;, &amp;quot;w&amp;quot;)
@extractor = Scrubyt::Extractor.new :output =&amp;gt; :xml_file, :file =&amp;gt; @file do
    fetch &amp;quot;http://www.google.com/search?&amp;amp;q=ruby&amp;quot;
    result &amp;quot;//html/body/div[5]/div/div/h2/a&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The XmlFile output takes an additional parameter which is the file to stream the results out to.&lt;/p&gt;

&lt;h2&gt;Creating your own plugin&lt;/h2&gt;

&lt;p&gt;That&amp;#8217;s great for those of you that are happy with XML or Hash output, but what about if you want some other custom format? Well it&amp;#8217;s time to create your own. I&amp;#8217;ll show you the actual code that implements the XmlFile output to show you how simple it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'rexml/document'
require &amp;quot;#{File.dirname(__FILE__)}/inflector&amp;quot;
require &amp;quot;#{File.dirname(__FILE__)}/inflections&amp;quot;

class Scrubyt::Output::XmlFile &amp;lt; Scrubyt::Output::Plugin  
  @subscribers = {}
  on_initialize :setup_file
  before_extractor :open_root_node
  after_extractor :close_root_node
  on_save_result :save_xml


  def setup_file(args = {})
    @file = args[:file]
  end

  def open_root_node(*args)
    @file.write(&amp;quot;&amp;lt;root&amp;gt;&amp;quot;)
  end

  def save_xml(name, results)
    if results.is_a?(::Hash)
      @file.write results.to_xml
    else
      results.each do |result|
        @file.write result.to_xml(name)
      end
    end
  end

  def close_root_node(*args)
    @file.write(&amp;quot;&amp;lt;/root&amp;gt;&amp;quot;)
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The require lines at the top are only needed for this output format. REXML to construct the XML tags for me, and some inflections I&amp;#8217;ve put together to turn the Hash and Array objects into XML. Now into analysing the class proper.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Scrubyt::Output::XmlFile &amp;lt; Scrubyt::Output::Plugin  
  @subscribers = {}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At the moment, you&amp;#8217;ll need to inintialize this instance variable to be an empty Hash for the events to get attached correctly. I&amp;#8217;m looking for a way to remove it, stay tuned. But for now you&amp;#8217;ll need to put it in.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;on_initialize :setup_file
before_extractor :open_root_node
after_extractor :close_root_node
on_save_result :save_xml&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we&amp;#8217;ve got four events to listen for, the concept should be familiar if you&amp;#8217;re coming from Rails. Essentially all we are doing is saying &amp;#8220;When we initialize run the setup&lt;em&gt;file method. Before the extractor actually starts, run the method called open&lt;/em&gt;root&lt;em&gt;node. Whenever we get a result to save, call save&lt;/em&gt;xml. And finally, after the extractor run the method called close&lt;em&gt;root&lt;/em&gt;node.&amp;#8221;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def setup_file(args = {})
  @file = args[:file]
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is fairly straightforward. If you&amp;#8217;ve got any custom logic that needs to happen when the output plugin is initialized you can place it in here. Any parameter that is passed in to Extractor.new() is passed through for you to access here.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def open_root_node(*args)
  @file.write(&amp;quot;&amp;lt;root&amp;gt;&amp;quot;)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now just to open the XML file, and keep it somewhat consistent with the old scRUBYt! XML output we open a &lt;root&gt; node within the file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def save_xml(name, results)
  if results.is_a?(::Hash)
    @file.write results.to_xml
  else
    results.each do |result|
      @file.write result.to_xml(name)
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here is where the majority of the magic happens. The save_xml method will be passed the desired name for the result, and a hash of the results. This is essentially the same format you&amp;#8217;d get if you used the Hash output format, except for each individual detail block rather than then entire extractor.&lt;/p&gt;

&lt;p&gt;The reason for the if/else scenario is for when results are not part of a detail block. If you&amp;#8217;re just returning results straight (like the Google example at the top of this post) then &amp;#8220;results&amp;#8221; in this context will be a list/Array of all the matching results rather than a Hash.&lt;/p&gt;

&lt;h2&gt;Passing results back to the extractor&lt;/h2&gt;

&lt;p&gt;Not everyone is going to want to stream results out to a file though, so to deal with this you can make a results method available on the instance of your plugin. As I said earlier, even Hash operates as a plugin now so we can see an example of how this work in the Hash output plugin:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Scrubyt::Output::Hash &amp;lt; Scrubyt::Output::Plugin
  @subscribers = {}
  on_initialize :setup_results
  on_save_result :store_hash

  def setup_results(args = {})
    @results = []
  end

  def results
    @results
  end

  def store_hash(name, passed_results)
    @results &amp;lt;&amp;lt; passed_results
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we setup a @results instance on&lt;em&gt;initialize, and then on&lt;/em&gt;save&lt;em&gt;results simply pushes the passed&lt;/em&gt;results into @results. Confused yet? Hopefully the code is clear enough to make sense.&lt;/p&gt;

&lt;p&gt;All that happens then is that back in your extractor definition the call to @extractor.results is passed through to the first output plugin it can find.&lt;/p&gt;

&lt;h2&gt;Naming Conventions and Namespacing&lt;/h2&gt;

&lt;p&gt;The only additional requirement for a plugin to work in scRUBYt! is that it is correctly named and namespaced. As you may have noticed the ones I&amp;#8217;ve provided are called Scrubyt::Output::Hash and Scrubyt::Output::XmlFile, that means they can be targeted using :output =&gt; :hash and  :output =&gt; :xml&lt;em&gt;file respectively. If you wanted to call your output GlennsBadExample it would be namespaced as Scrubyt::Output::GlennsBadExample and you&amp;#8217;d then just need to require the appropriate file and use :output =&gt; :glenns&lt;/em&gt;bad_example&lt;/p&gt;

&lt;h2&gt;Oh the possibilities! So what&amp;#8217;s next?&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;re only just starting to see the possibilities that this will offer our extractors. It opens up the possibility of pushing results not only to a different format, but possibly a completely different service. It&amp;#8217;s now trivial to create an output format that streams results directly into backgroundRB, a nanite worker, or a web service for further processing and data warehousing. By the time you read this, you&amp;#8217;ll also be able to pass in an array of outputs like :output =&gt; [:hash, :xml_file] and have both plugins generate the appropriate format(s). For the scraper I&amp;#8217;m currently working on where I have two different companies wanting the same data, this could be just the ticket for interfacing directly to their API as I scrape.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d love to hear what ideas people might have for this, or how you think it could be improved. We&amp;#8217;re really hopeful that this is the kind of thing that makes developing and extending scRUBYt! really easy for those with more complicated needs.&lt;/p&gt;</description>
          <pubDate>Fri, 16 Jan 2009 01:18:45 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/16/scrubyt-gets-plugins/</guid>
          <link>http://rubypond.com/articles/2009/01/16/scrubyt-gets-plugins/</link>
        </item>
    
        <item>
          <title>Web Scraping - The Amazon Example Finale</title>
          <description>&lt;p&gt;So yesterday I showed you a fairly contrived example of &lt;a href=&quot;http://rubypond.com/articles/2009/01/13/more-web-scrapers-with-the-upcoming-scrubyt/&quot;&gt;how to build a web scraper&lt;/a&gt; using scRUBYt! to get data from Amazon (they&amp;#8217;ve got an API that would be much easier and more robust if you need access to this info, but that&amp;#8217;s not the point at the moment). But if you look at the results, they&amp;#8217;re not the greatest. There is too much noise in some fields, and we probably want to share there data with another system so a ruby based Hash object isn&amp;#8217;t going to work.&lt;/p&gt;

&lt;h2&gt;Removing empty results with scRUBYt!&lt;/h2&gt;

&lt;p&gt;For various reasons, sometimes you may not get all the data you want back for every record. It&amp;#8217;s usually related to your result definition being too restrictive, or a change in format on a specific page. Maybe the price information is in a different DIV if it is on sale. In any event, you need to make a decision on what to do. In the new release of scRUBYt! there are three immediate options that come to mind, but we may well build more in if required. First, and what we did yesterday in the example, is to do nothing. You&amp;#8217;ll get the nil/empty result returned back to you to handle as you see fit. Second, you can simply drop any fields that are nil (I&amp;#8217;ve just displayed the first few results):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot; do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;, :remove_blank =&amp;gt; true
    saving &amp;quot;//td[@class='price']&amp;quot;
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;
  end
end
puts @extractor.results.inspect
=&amp;gt; [{:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language [ILLUSTRATED]  (Paperback)&amp;quot;}, 
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;}, 
             {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;}, 
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 0596516177&amp;quot;}]}
    {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language (Paperback)&amp;quot;}, 
             {:saving=&amp;gt;nil}, 
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 020171096X&amp;quot;}]}, 
    {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Beginning Ruby: From Novice to Professional (Beginning from Novice to Professional) (Paperback)&amp;quot;}, 
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;}, 
             {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;}, 
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 1590597664&amp;quot;}]}
    ...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&amp;#8217;ve set :remove_blank to true on the price field, and as a result you&amp;#8217;ll see that the 2nd result contains no price element. Alternatively, you could drop any detail block (in this example, any single book) which is missing the field:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot; do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;, :required =&amp;gt; true
    price &amp;quot;//b[@class='priceLarge']&amp;quot;, :required =&amp;gt; true
    saving &amp;quot;//td[@class='price']&amp;quot;
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;
  end
end
puts @extractor.results.inspect
=&amp;gt; [{:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language [ILLUSTRATED]  (Paperback)&amp;quot;},
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;},
             {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;},
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 0596516177&amp;quot;}]},
    {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Beginning Ruby: From Novice to Professional (Beginning from Novice to Professional) (Paperback)&amp;quot;},
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;},
             {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;},
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 1590597664&amp;quot;}]},
    {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Programming Ruby: The Pragmatic Programmers' Guide, Second Edition [ILLUSTRATED]  (Paperback)&amp;quot;},
             {:price=&amp;gt;&amp;quot;$29.67&amp;quot;},
             {:saving=&amp;gt;&amp;quot;$15.28\n      (34%)\n    &amp;quot;},
             {:isbn=&amp;gt;&amp;quot;ISBN-10: 0974514055&amp;quot;}]},
    ...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This time the &amp;#8220;The Ruby Programming Language (Paperback)&amp;#8221; book isn&amp;#8217;t included in the results at all. For our purposes though, I&amp;#8217;ve decided that I only want to know about books that I have &lt;em&gt;all&lt;/em&gt; the details for. Instead of setting :required on every result, I can specify it on the book_detail definition which will give the same output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot;, :required =&amp;gt; :all do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;
    saving &amp;quot;//td[@class='price']&amp;quot;
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Sanitizing scRUBYt! output&lt;/h2&gt;

&lt;p&gt;The output still isn&amp;#8217;t quite what we want. We&amp;#8217;ve dumped the empty results, but we&amp;#8217;ve still got that ugly &amp;#8220;ISBN-10: &amp;#8221; in front of the ISBN. We could clean it up later, but it&amp;#8217;s creating additional work for ourselves. And if we want this thing to scale (I&amp;#8217;ve got scrapers which scrape thousands of pages off a single site) trying to keep all that data hanging around in memory isn&amp;#8217;t going to work. So let&amp;#8217;s do as much of possible within the scRUBYt! definition as we&amp;#8217;re collecting the data: &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot;, :required =&amp;gt; :all do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;
    saving &amp;quot;//td[@class='price']&amp;quot;
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;, :script =&amp;gt; Proc.new{|isbn| isbn.gsub(&amp;quot;ISBN-10: &amp;quot;, &amp;quot;&amp;quot;)}
  end
end
puts @extractor.results.inspect
=&amp;gt; [{:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language [ILLUSTRATED]  (Paperback)&amp;quot;},
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;},
             {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;},
             {:isbn=&amp;gt;&amp;quot;0596516177&amp;quot;}]},
    ... ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now you&amp;#8217;ll see that we&amp;#8217;re getting a much cleaner ISBN result. Just create a Proc, the result will be passed into in and then do as you see fit. An if statement to check it contains something you expect, a regexp, the possibilities are endless. You can also combine this with the other options like :require and :remove_blank. So let&amp;#8217;s really jazz this thing up. We&amp;#8217;ll clean up the saving, and pull in the description and that&amp;#8217;s all the data we need:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot;, :required =&amp;gt; :all  do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;
    saving &amp;quot;//td[@class='price']&amp;quot;, :script =&amp;gt; Proc.new{|saving| saving.match(/(\$[\d\.]*)/)[1]}
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;, :script =&amp;gt; Proc.new{|isbn| isbn.gsub(&amp;quot;ISBN-10: &amp;quot;,&amp;quot;&amp;quot;)}
    description &amp;quot;//div[@id='productDescription']//div[@class='content']&amp;quot;
  end
end
puts @extractor.results.inspect
=&amp;gt; [{:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Beginning Ruby: From Novice to Professional (Beginning from Novice to Professional) (Paperback)&amp;quot;},
             {:price=&amp;gt;&amp;quot;$26.39&amp;quot;},
             {:saving=&amp;gt;&amp;quot;$13.60&amp;quot;},
             {:isbn=&amp;gt;&amp;quot;1590597664&amp;quot;}, 
             {:description=&amp;gt;&amp;quot;Product Description\n  Ruby is perhaps best known as the engine powering the...&amp;quot;}]}, 
    {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Programming Ruby: The Pragmatic Programmers' Guide, Second Edition [ILLUSTRATED]  (Paperback)&amp;quot;}, 
             {:price=&amp;gt;&amp;quot;$29.67&amp;quot;}, 
             {:saving=&amp;gt;&amp;quot;$15.28&amp;quot;}, 
             {:isbn=&amp;gt;&amp;quot;0974514055&amp;quot;}, 
             {:description=&amp;gt;&amp;quot;Product Description\n  Ruby is an increasingly popular, fully object-oriented dynamic...&amp;quot;}]},
    ...]&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Outputting results to XML&lt;/h2&gt;

&lt;p&gt;Inevitably there comes a time where you want to consume this data in something other than your ruby application. At that point, passing around a Hash is probably not the best idea. Alternatively, you might have a scraper that has to scrape hundreds to thousands of pages. Storing all the results in a Hash as you go will bring your machine to it&amp;#8217;s knees. So here comes one of the largest changes to the way the new release of scRUBYt! works.&lt;/p&gt;

&lt;p&gt;Previously, you always had results returned as a Hash and/or XML depending on your need. Everything was held in memory until you destroyed your extractor. Now, the standard XML option is to stream the results out to a file as they are processed and remove them from memory. There is no way to retrieve the results as XML within your program, they have to be streamed out to a file (and really, why would you want XML within your app when you can have native ruby structures instead?). So to save our scraper above out to an XML file you just pass a new output format and an instance of a File to the extractor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@file = File.new(&amp;quot;amazon_results.xml&amp;quot;, &amp;quot;w&amp;quot;)
@extractor = Scrubyt::Extractor.new :output =&amp;gt; :xml_file, :file =&amp;gt; @file do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot;, :required =&amp;gt; :all  do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;
    saving &amp;quot;//td[@class='price']&amp;quot;, :script =&amp;gt; Proc.new{|saving| saving.match(/(\$[\d\.]*)/)[1]}
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;, :script =&amp;gt; Proc.new{|isbn| isbn.gsub(&amp;quot;ISBN-10: &amp;quot;,&amp;quot;&amp;quot;)}
    description &amp;quot;//div[@id='productDescription']//div[@class='content']&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now a call to @extractor.results at the end of the scrape will return no results. I hope that wasn&amp;#8217;t too much and it&amp;#8217;s given you a good view into how to create your very own web scraper. If you have any questions, head on over to the &lt;a href=&quot;http://www.scrubyt.org/&quot;&gt;scRUBYt! forums&lt;/a&gt; or post them in the comments.&lt;/p&gt;</description>
          <pubDate>Thu, 15 Jan 2009 20:52:12 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/15/web-scraping---the-amazon-example-finale/</guid>
          <link>http://rubypond.com/articles/2009/01/15/web-scraping---the-amazon-example-finale/</link>
        </item>
    
        <item>
          <title>More web scrapers with the upcoming scRUBYt!</title>
          <description>&lt;p&gt;In the previous articles I gave a brief glimpse at the upcoming scRUBYt! release. We learned how to do some basic &lt;a href=&quot;http://rubypond.com/articles/2008/12/09/web-spidering-and-data-extraction-with-scrubyt/&quot;&gt;html scraping&lt;/a&gt;, and then followed it up by &lt;a href=&quot;http://rubypond.com/articles/2008/12/17/web-spider-creation-with-scrubyt---part-ii/&quot;&gt;scraping multiple pages&lt;/a&gt;. As promised, in this installment I&amp;#8217;ll go over how to get more detailed logging output to help you debug your scraper while in development and how to submit and navigate forms.&lt;/p&gt;

&lt;h2&gt;Logging Scraper Output&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s been quite a fundamental change to the way scRUBYt! works internally of late. It doesn&amp;#8217;t manifest itself visually in the way you interface to it, but it does mean logging the output is now much easier and cleaner. Using our most basic example from the first tutorial, you just need to pass the :log_level into the extractor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new(:log_level =&amp;gt; :verbose) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By default, the output is directed to stdout so you&amp;#8217;d see the following on your screen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;start
fetch: http://www.google.com/ncr
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&amp;#8217;re after a more complex example, here is the scraper definition from the second part of the tutorial series and the corresponding log output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new(:log_level =&amp;gt; :verbose) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_detail &amp;quot;//h3[@class='r']/a&amp;quot; do
    title &amp;quot;//title&amp;quot;
    summary &amp;quot;//p&amp;quot;, :script =&amp;gt; Proc.new{|result| result if result.match(%r{(\w+\W+){25}})}
  end
  next_page &amp;quot;//a[text()*='Next']&amp;quot;, :limit =&amp;gt; 2
end&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;start
fetch: http://www.google.com/ncr
textfield: 'q' = 'ruby'
with options ''
submit
next detail: 'page' = 'http://ruby-lang.org/'
with args: ''
next detail: 'page' = 'http://en.wikipedia.org/wiki/Ruby_(programming_language)'
with args: ''

etc...

next page: /search?hl=en&amp;amp;ie=UTF-8&amp;amp;q=ruby&amp;amp;start=10&amp;amp;sa=N
fetch: http://www.google.com/search?hl=en&amp;amp;ie=UTF-8&amp;amp;q=ruby&amp;amp;start=10&amp;amp;sa=N
next detail: 'page' = 'http://www.rubycentral.com/book/'
with args: ''

etc...

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

&lt;p&gt;At present the valid :log_level values are :none, :critical, :error, :warn, :info, :debug, and :verbose (in increasing order of noise). If you want to direct the log output to something other than stdout the only way at the moment is to override the Scrubyt::Logger#log method. I&amp;#8217;m looking at ways to make it easier to substitute in a file based or other logging approach.&lt;/p&gt;

&lt;h2&gt;Making Your Scraper Navigate Forms&lt;/h2&gt;

&lt;p&gt;So now that we know how to log the output, let&amp;#8217;s do something more useful with our scraper. We can&amp;#8217;t really take our Google example from previous posts any further given how simple their interface is, so let us move over to Amazon. Say I wanted to grab a list the books on ruby that are for sale. Sure, I could probably get this information via an Amazon API&amp;#8230; but that&amp;#8217;s not really the point now is it ;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Scrubyt::Extractor.new(:log =&amp;gt; :debug) do
  fetch &amp;quot;http://www.amazon.com/&amp;quot;
  select_option &amp;quot;url&amp;quot;, &amp;quot;Books&amp;quot;
  fill_textfield &amp;quot;field-keywords&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  book_detail &amp;quot;//td[@class='dataColumn']/table/tr/td/a&amp;quot; do
    title &amp;quot;//h1[@class='parseasinTitle']&amp;quot;
    price &amp;quot;//b[@class='priceLarge']&amp;quot;
    saving &amp;quot;//td[@class='price']&amp;quot;
    isbn &amp;quot;//li[text()*='ISBN-10:']&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So let&amp;#8217;s run through what we&amp;#8217;ve got here, hopefully some of it looks familiar from the previous examples we&amp;#8217;ve gone through. First we fetch the page to start with, then in the select field named &amp;#8220;url&amp;#8221; we choose the options that says &amp;#8220;Books&amp;#8221;, and we then submit the form. scRUBYt! will keep track of the last form you input any data to, so if there are multiple forms on the page then you just need to target the appropriate input fields. From there, the submit action will work out what it needs to do.&lt;/p&gt;

&lt;p&gt;Next is to define a detail block, so we point out the XPath to the heading/link for each book on the page and say we want to navigate to that page and extract the title, price, saving, etc. I&amp;#8217;ve been a little cheeky with the isbn definition, saying just find me any LI tag that contains the string &amp;#8220;ISBN-10:&amp;#8221;. If we were to look at the results generated you&amp;#8217;d see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;puts @extractor.results.inspect
[{:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language [ILLUSTRATED]  (Paperback)&amp;quot;}, {:price=&amp;gt;&amp;quot;$26.39&amp;quot;}, 
          {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 0596516177&amp;quot;}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Programming Language (Paperback)&amp;quot;}, 
          {:price=&amp;gt;nil}, 
          {:saving=&amp;gt;nil}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 020171096X&amp;quot;}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Beginning Ruby: From Novice to Professional (Beginning from Novice to Professional) (Paperback)&amp;quot;}, 
          {:price=&amp;gt;&amp;quot;$26.39&amp;quot;}, 
          {:saving=&amp;gt;&amp;quot;$13.60\n      (34%)\n    &amp;quot;}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 1590597664&amp;quot;}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Beginning Ruby: From Novice to Professional (Kindle Edition)&amp;quot;}, 
          {:price=&amp;gt;nil}, 
          {:saving=&amp;gt;nil}, 
          {:isbn=&amp;gt;nil}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Programming Ruby: The Pragmatic Programmers' Guide, Second Edition [ILLUSTRATED]  (Paperback)&amp;quot;}, 
          {:price=&amp;gt;&amp;quot;$29.67&amp;quot;}, 
          {:saving=&amp;gt;&amp;quot;$15.28\n      (34%)\n    &amp;quot;}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 0974514055&amp;quot;}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;The Ruby Way, Second Edition: Solutions and Techniques in Ruby Programming (2nd Edition) (Addison-Wesley Professional Ruby Series) (Paperback)&amp;quot;}, 
          {:price=&amp;gt;&amp;quot;$29.69&amp;quot;}, 
          {:saving=&amp;gt;&amp;quot;$15.30\n      (34%)\n    &amp;quot;}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 0672328844&amp;quot;}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Ruby Way, The: Solutions and Techniques in Ruby Programming (Kindle Edition)&amp;quot;}, 
          {:price=&amp;gt;nil}, 
          {:saving=&amp;gt;nil}, 
          {:isbn=&amp;gt;nil}]}, 
 {:book=&amp;gt;[{:title=&amp;gt;&amp;quot;Learning Ruby [ILLUSTRATED]  (Paperback)&amp;quot;}, 
          {:price=&amp;gt;&amp;quot;$23.09&amp;quot;}, 
          {:saving=&amp;gt;&amp;quot;$11.90\n      (34%)\n    &amp;quot;}, 
          {:isbn=&amp;gt;&amp;quot;ISBN-10: 0596529864&amp;quot;}]}
]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we have a reasonable snapshot of the data. You&amp;#8217;ll see there though, that it&amp;#8217;s not perfect. Firstly, we are missing information for some results. We&amp;#8217;ve got spaces and carriage returns in the saving data, and we probably don&amp;#8217;t need the &amp;#8220;ISBN-10:&amp;#8221; string at the front of the ISBN result. And what if we wanted to link to the actual result so someone could actually buy the book on Amazon? &lt;/p&gt;

&lt;p&gt;All good questions, and all easily solvable. I&amp;#8217;ll follow it up with a post in the next day or so and highlight some of the new ways of specifying constraints on your data in scRUBYt!. And special thanks have to go to Homeflow who have been funding at least a day of time for Peter and I each week lately, hence the increased level of development in scRUBYt!. It&amp;#8217;s nice when you have clients who want to actively give back.&lt;/p&gt;</description>
          <pubDate>Tue, 13 Jan 2009 01:20:13 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/13/more-web-scrapers-with-the-upcoming-scrubyt/</guid>
          <link>http://rubypond.com/articles/2009/01/13/more-web-scrapers-with-the-upcoming-scrubyt/</link>
        </item>
    
        <item>
          <title>Rails Hosting - Updated</title>
          <description>&lt;p&gt;This is just a quick note so that those subscribing to my feed or checking the site for updates are aware. I&amp;#8217;ve made a series of minor changes to the &lt;a href=&quot;http://rubypond.com/articles/2008/12/04/ruby-on-rails-hosting-round-up/&quot;&gt;rails hosting&lt;/a&gt; post from last month based on the feedback provided by you guys. If you&amp;#8217;ve got any additional experiences with different rails hosts that you&amp;#8217;d like to share, then please send them through.&lt;/p&gt;</description>
          <pubDate>Mon, 05 Jan 2009 23:10:53 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/05/rails-hosting---updated/</guid>
          <link>http://rubypond.com/articles/2009/01/05/rails-hosting---updated/</link>
        </item>
    
        <item>
          <title>Ruby on Rails Tutorials</title>
          <description>&lt;p&gt;There has been a few occasions over the previous months when various people I meet have asked me to point them in the right direction to get started with ruby on rails. I remember when I started, it was a pretty easy question to answer&amp;#8230; everyone just got pointed in the general direction of why_&amp;#8217;s poignant guide, the pickaxe book, and agile web development with rails. But things have come a long way since then. There is not only a veritable cornucopia of options now out there, but for somebody who isn&amp;#8217;t already engrossed in the community it&amp;#8217;s almost impossible to tell which ones are still relevant and useful and which ones are so dated that they&amp;#8217;ll make your attempts to learning markedly more difficult.&lt;/p&gt;

&lt;p&gt;So with that in mind, I&amp;#8217;ve attempted to compile a list of resources which are still (at least for the most part) still relevant at the time of posting. Some will have some minor inconsistencies either in implementation or current convention but I&amp;#8217;ve made a genuine effort to review and ensure they are not way out of line. If you find in errors on that front, please let me know in the comments.&lt;/p&gt;

&lt;p&gt;So without any further ado, here are the ruby on rails tutorials I&amp;#8217;ve found broken into various categories (a couple are listed in more than one):&lt;/p&gt;

&lt;h2&gt;Ruby on Rails Tutorials&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#getting-started&quot;&gt;Getting Started and Example Applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#models-migrations&quot;&gt;Models/Migrations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#controllers&quot;&gt;Controllers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#views&quot;&gt;Views&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#routing&quot;&gt;Routing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mail&quot;&gt;Mail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#testing&quot;&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#performance-admin-debug&quot;&gt;Performance, Administration, and Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#misc&quot;&gt;Miscellaneous&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#special-mention&quot;&gt;Extra Special Mention&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a name=&quot;getting-started&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Getting Started and Example Applications&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/getting_started_with_rails.html&quot; rel=&quot;nofollow&quot;&gt;Getting started with Rails&lt;/a&gt;
A great guide on building your first rails app and understanding the framework.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.bitwisemag.com/2/Ruby-On-Rails-Tutorial-The-Basics&quot; rel=&quot;nofollow&quot;&gt;Ruby On Rails Tutorial : The Basics&lt;/a&gt;
A two-part tutorial to getting up and running on rails by Huw Collingbourne.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://ruby.about.com/od/rubyonrails/ss/railsblog1.htm&quot; rel=&quot;nofollow&quot;&gt;Building a blog&lt;/a&gt;
About.com have have this guide for Rails 2.1 which runs you through the classic &amp;#8220;15-minute blog&amp;#8221; project.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://docs.activestate.com/komodo/4.4/tutorial/railstut.html&quot; rel=&quot;nofollow&quot;&gt;Starting a rails project using Komodo&lt;/a&gt;
For those of you using Komodo this is a great guide to show you how to develop within Komodo and run the tests within your IDE.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.webmonkey.com/tutorial/Ruby_on_Rails_for_Beginners&quot; rel=&quot;nofollow&quot;&gt;Building a bookmark manager&lt;/a&gt;
A quick introductory guide to rails and an example app to manage your bookmarks.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://godbit.com/article/beginners-guide-to-rails-part-1&quot; rel=&quot;nofollow&quot;&gt;Building a contact manager&lt;/a&gt;
A ruby on rails tutorial on how to get acquainted with the framework by building a contact list manager.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.oracle.com/technology/pub/articles/haefel-oracle-ruby.html&quot; rel=&quot;nofollow&quot;&gt;A simple product catalog&lt;/a&gt;
A tutorial from Oracle on how to create a comics catalog on top of an Oracle back-end.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://media.rubyonrails.org/video/rails_blog_2.mov&quot; rel=&quot;nofollow&quot;&gt;The official 15-min blog screencast&lt;/a&gt;
A rather high paced run-through of how to get a blog up and running in 15mins.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.sitepoint.com/article/learn-ruby-on-rails/&quot; rel=&quot;nofollow&quot;&gt;The ultimate guide to ruby &amp;amp; rails&lt;/a&gt;
Quite a detailed and useful tutorial from Patrick Lenz which not only goes through rails but is a pretty decent intro to the ruby you should get your head around first too.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/&quot; rel=&quot;nofollow&quot;&gt;What I wish I knew&lt;/a&gt;
A bit of a retrospective from someone after they got their first few rails applications under their belt.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsforum.com/viewtopic.php?id=1033&quot; rel=&quot;nofollow&quot;&gt;Sending Instant Messages in Rails&lt;/a&gt;
How to use XMPP and BackgroundRB to send messages to GMail and other Jabber based clients.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsforum.com/viewtopic.php?id=1041&quot; rel=&quot;nofollow&quot;&gt;Programming Conventions&lt;/a&gt;
A discussion on what exactly DRY means, why you should stick to conventions, and when you should look at optimization.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;models-migrations&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Models/Migrations&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/06/18/bulk-insertion-of-data-with-activerecord/&quot;&gt;Bulk Insert into ActiveRecord with Rails&lt;/a&gt;
How to quickly insert multiple records at once with ActiveRecord.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.oracle.com/technology/pub/articles/haefel-oracle-ruby.html&quot; rel=&quot;nofollow&quot;&gt;Using Oracle&lt;/a&gt;
A tutorial from Oracle on how to create a comics catalog on top of an Oracle back-end.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2007/11/20/reject-junk-email-addresses-with-email-veracity/&quot;&gt;Rails email validation&lt;/a&gt;
Check that a provided email address really is legit, by doing a DNS/MX lookup on the domain.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsforum.com/viewtopic.php?id=1011&quot; rel=&quot;nofollow&quot;&gt;Rail Migrations for beginners&lt;/a&gt;
This tutorial is a little dated, but thankfully the examples all still work in Rails 2.x. What I particularly like, is that they actually cover how to add an index to a column which most don&amp;#8217;t cover and thus many don&amp;#8217;t bother to do.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/migrations.html&quot; rel=&quot;nofollow&quot;&gt;Rails Guide to Migrations&lt;/a&gt;
A very detailed guide on what you can and can&amp;#8217;t do in migrations. Even I learnt a few new tricks from reading through it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/activerecord_validations_callbacks.html&quot; rel=&quot;nofollow&quot;&gt;ActiveRecord Validations and Callbacks&lt;/a&gt;
All the various validation options you have, and what method callbacks you can hook into when modifying an instance of a model.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/association_basics.html&quot; rel=&quot;nofollow&quot;&gt;ActiveRecord Associations&lt;/a&gt;
How to link up the associations between the models in your applications.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/finders.html&quot; rel=&quot;nofollow&quot;&gt;Finding records in your database&lt;/a&gt;
A tutorial on all the various ways you can find either a single record, or a collection of records, using ActiveRecord. The built in finders, and how to pass your own custom conditions in are all handled.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;controllers&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Controllers&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2007/11/27/simplifying-rails-controllers-with-make_resourceful/&quot;&gt;Simplify Ruby on Rails controllers with make_resourceful&lt;/a&gt;
Take advantage of the DRY approach by quickly implementing common controller actions in just a few lines of code.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.devarticles.com/c/a/Ruby-on-Rails/Controlling-Information-Access-with-the-Rails-Action-Controller/&quot; rel=&quot;nofollow&quot;&gt;Controlling Information Access&lt;/a&gt;
A quick explanation of the why/when you should make methods in your controllers private or protected.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/07/11/useful-flash-messages-in-rails/&quot;&gt;Displaying Useful Flash Messages&lt;/a&gt;
How to provide more useful feedback on errors or actions to your users within your application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/07/16/sexy-forms-in-rails/&quot;&gt;Consistent and sexy rails forms&lt;/a&gt;
How to both DRY up your code and ensure your users get a consistent experience by using a Rails Custom Form Builder.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/actioncontroller_basics.html&quot; rel=&quot;nofollow&quot;&gt;ActionController Basics&lt;/a&gt;
How to use filters, disabling the session, cookies, authentication, and protecting against forgery. It&amp;#8217;s called basics, but it covers quite a lot.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2007/12/13/new-error-handling-in-rails-2-0/&quot;&gt;Catching rails error messages&lt;/a&gt;
An easy example of how to use the 2.x approach to catching errors in your rails applications.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;views&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Views&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/form_helpers.html&quot; rel=&quot;nofollow&quot;&gt;Introduction to form helpers&lt;/a&gt;
A quick tutorial on when you should use the object/model based form helpers in rails, and when you should use the standard ones.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/layouts_and_rendering.html&quot; rel=&quot;nofollow&quot;&gt;Rendering layouts and views&lt;/a&gt;
How to render a response to the web browser within your rails app. Also goes into providing only a HEAD response, nesting layouts, using partials, redirects, and using yield.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/01/03/unobtrusive-javascript-with-lowpro/&quot;&gt;Implementing unobtrusive javascript in rails&lt;/a&gt;
How to stop using the built-in javascript helpers and instead use lowpro to keep your views and code clean.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;routing&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Routing&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://adam.blog.heroku.com/past/2007/12/20/nested_resources_in_rails_2/&quot; rel=&quot;nofollow&quot;&gt;Nested Resources in Rails 2.x&lt;/a&gt;
A guide to bring you up to speed on the changes between the way resources work in 1.x and the 2.x releases.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/routing_outside_in.html&quot; rel=&quot;nofollow&quot;&gt;Rails Routing from the Outside-In&lt;/a&gt;
A very comprehensive guide on how to configure and use the routing options in rails.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;mail&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Mail&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2007/11/16/trap-rails-from-sending-mail-via-smtp/&quot;&gt;Stop Rails from sending email&lt;/a&gt;
A useful way to check that mail is getting sent, without actually sending it.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;testing&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2007/12/10/testing-xml-output-in-rspec-and-rails/&quot;&gt;Test Rails XML Output with rspec&lt;/a&gt;
How to easily test XML output using rspec.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/01/07/testing-web-services-with-rspec/&quot;&gt;Testing webservices using rspec&lt;/a&gt;
A guide on testing the old style SOAP/XML webservices with rspec.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/03/31/using-rspec-have_tag/&quot;&gt;Using rspec have_tag&lt;/a&gt;
How to test anything you need to in a view with rspec have_tag&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;performance-admin-debug&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Performance, Administration, and Debugging&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/02/06/improving-rails-app-and-mongrel-performance-with-thin/&quot;&gt;Improve Rails Performance with Thin&lt;/a&gt;
A tutorial on replacing mongrel or webrick with the event driven thin web server.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/04/08/letting-nginx-automatically-detect-new-rails-apps/&quot;&gt;Let nginx automatically become aware of your Rails apps&lt;/a&gt;
How to configure nginx to automatically become aware of any new apps you deploy and start serving them without any additional configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/04/07/rails-god-config/&quot;&gt;Monitoring your Rails app with god&lt;/a&gt;
How to use the god monitoring tool to manage, start, stop, and restart your rails app.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://effectif.com/2008/4/8/monitoring-backgroundrb-with-god&quot;&gt;Monitoring BackgroundRB with god&lt;/a&gt;
Another tutorial on using god, this one for monitoring BackgroundRB.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/06/18/bulk-insertion-of-data-with-activerecord/&quot;&gt;Improving Bulk Data Insertion with ActiveRecord&lt;/a&gt;
Reduce the number of round-trips to the database by batch inserting records into ActiveRecord.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/07/17/the-complete-guide-to-setting-up-starling/&quot;&gt;Background Processing with Starling&lt;/a&gt;
How to off-load long running tasks to a queue so that you don&amp;#8217;t tie up your webserver processes requests needlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsenvy.com/2007/2/28/rails-caching-tutorial&quot; rel=&quot;nofollow&quot;&gt;Ruby on Rails Caching Tutorial&lt;/a&gt;
Another two-part tutorial. This one, by Gregg from RailsEnvy, runs through the various ruby on rails caching options and how to implement them to improve the performance of your site.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial&quot; rel=&quot;nofollow&quot;&gt;Ruby on Rails Rake Tutorial&lt;/a&gt;
Gregg from RailsEnvy again running through how to make the most of rake. If you&amp;#8217;re not already writing your own custom tasks in rake you should definitely take a look because there is probably a handful of things your could (and should) be doing in it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.sitepoint.com/article/debug-rails-app-ruby-debug/&quot; rel=&quot;nofollow&quot;&gt;Debug your app with ruby-debug&lt;/a&gt;
I don&amp;#8217;t know how I ever diagnosed problems in development before I learnt how
to use ruby-debug. If you&amp;#8217;ve got applications even just staring to come together, you really need to get your head around this tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.rubyinside.com/19-rails-tricks-most-rails-coders-dont-know-131.html&quot; rel=&quot;nofollow&quot;&gt;19 Rails Tricks Most Rails Coders Don&amp;#8217;t Know&lt;/a&gt;
Not a tutorial per se, but a good collection of handy tips on how to benchmark performance, test various aspects of your app, improve it&amp;#8217;s performance, and more.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.railsforum.com/viewtopic.php?id=872&quot; rel=&quot;nofollow&quot;&gt;Reading a stack trace&lt;/a&gt;
You&amp;#8217;re inevitably going to see a few when your developing, you better learn how to make sense of them.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/security.html&quot; rel=&quot;nofollow&quot;&gt;Ruby on Rails Security Guide&lt;/a&gt;
Storing and protecting the session, user management, projecting from injection, and more.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/debugging_rails_applications.html&quot; rel=&quot;nofollow&quot;&gt;Debugging Rails Applications&lt;/a&gt;
How to use views to help you debug your app, detecting memory leaks, and using the logger.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/benchmarking_and_profiling.html&quot; rel=&quot;nofollow&quot;&gt;Benchmarking and Profiling Rails&lt;/a&gt;
The why and how of benchmarking and profiling. Still a work in progress.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;misc&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Miscellaneous&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/12/08/custom-starting-templates-for-rails-apps/&quot;&gt;Define your own base rails framework with templates&lt;/a&gt;
Stop manually importing and installing all the same plugins in all of your applications, define a template in just a few lines and let rails know what it should start with.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/06/26/make-your-own-im-bot-in-ruby-and-interface-it-with-your-rails-app/&quot;&gt;Integrate an IM Bot into your Rails App &lt;/a&gt;
How to make an Instant Messaging BOT and use it in your rails application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guides.rails.info/creating_plugins.html&quot; rel=&quot;nofollow&quot;&gt;Creating Plugins&lt;/a&gt;
How to create a plugin for use in your rails app.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubypond.com/articles/2008/02/08/improved-timezones-in-rails-2-1/&quot;&gt;Working with Rails Timezones&lt;/a&gt;
How to use the 2.x enhancements to easily switch between timezones or display dates/times in a users local zone.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;special-mention&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Super extra special mention&lt;/h2&gt;

&lt;p&gt;Ryan Bates is simply tireless in providing useful screencasts showing various bits of functionality and tips within rails. If I was to list each of the ones I thought would be useful here, then the list would probably be 3 times longer than it already is. Instead, make sure you check out &lt;a href=&quot;http://railscasts.com/&quot; rel=&quot;nofollow&quot;&gt;Railscasts&lt;/a&gt; and scan through the archive.&lt;/p&gt;</description>
          <pubDate>Mon, 05 Jan 2009 02:34:09 GMT</pubDate>
          <guid>http://rubypond.com/articles/2009/01/05/ruby-on-rails-tutorials/</guid>
          <link>http://rubypond.com/articles/2009/01/05/ruby-on-rails-tutorials/</link>
        </item>
    
        <item>
          <title>Web Spider Creation with scRUBYt! - Part II </title>
          <description>&lt;p&gt;Continuing on from the previous post, &lt;a href=&quot;/articles/2008/12/09/web-spidering-and-data-extraction-with-scrubyt/&quot;&gt;Web Spidering and Data Extraction with scRUBYt!&lt;/a&gt;, this article will help you delve a little deeper with the &lt;a href=&quot;http://www.scrubyt.org&quot;&gt;scRUBYt! scraping framework&lt;/a&gt; both in terms of your understanding of how to use it&amp;#8230; and actually delving deeper in your crawl to more pages.&lt;/p&gt;

&lt;h2&gt;A quick recap on the last web spider&lt;/h2&gt;

&lt;p&gt;So as far as we got last week was to go off to Google, put in a search for the word &amp;#8220;ruby&amp;#8221;, and then list the link text for each of the results. Here&amp;#8217;s the code we ended up with to get that far:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_title &amp;quot;//h3[@class='r']&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;How to scrape deeper pages&lt;/h2&gt;

&lt;p&gt;But this is a fairly contrived example, and it&amp;#8217;s not exactly going to save you a huge amount of time over a quick manual copy-and-paste job from the results page. But what if you didn&amp;#8217;t want to just have a list of the links, you wanted some kind of summary or additional detail on each of the links? Lets actually go to each website, and see what kind of content they&amp;#8217;ve got and grab something useful from it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_detail &amp;quot;//h3[@class='r']/a&amp;quot; do
    page_body &amp;quot;//body&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you offer up the XPath to a link element with a result name ending in _detail, and then pass in a block, scRUBYt! will follow the link before trying to process the block. That means we can use this technique for following each of the results Google gives us, and at each we return all of the text contain on the page between the &amp;lt;body&amp;gt; tags. &lt;/p&gt;

&lt;p&gt;Now you could take the hash returned, and do some post processing on it to get something meaningful from the text extracted. But for the sake of example, I&amp;#8217;ll make some big assumptions and assume that every page is going to have at least a &amp;lt;title&amp;gt; tag, and a &amp;lt;p&amp;gt; tag with more than just a few words in it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_detail &amp;quot;//h3[@class='r']/a&amp;quot; do
    title &amp;quot;//title&amp;quot;
    summary &amp;quot;//p&amp;quot;, :script =&amp;gt; Proc.new{|result| result if result.match(%r{(\w+\W+){25}})}
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you may have noticed, you can pass a proc in as a parameter to your result definition. The output of the XPath match will be passed in to the proc, and the result ultimately returned as the final result for that definition? Make sense? If not, what I&amp;#8217;ve done above is look for all &amp;lt;p&amp;gt; tags on the page and pass them in to my proc definition. The proc then runs a regexp against it to check that at least 25 words exist within the &amp;lt;p&amp;gt;, if there is then all the &amp;lt;p&amp;gt; content is returned otherwise nil is returned.&lt;/p&gt;

&lt;h2&gt;What if the results are paginated?&lt;/h2&gt;

&lt;p&gt;You could potentially create a highly recursive extractor to handle this, but it&amp;#8217;s such a common case that we&amp;#8217;ve included a method to do it for you:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_detail &amp;quot;//h3[@class='r']/a&amp;quot; do
    title &amp;quot;//title&amp;quot;
    summary &amp;quot;//p&amp;quot;, :script =&amp;gt; Proc.new{|result| result if result.match(%r{(\w+\W+){25}})}
  end
  next_page &amp;quot;//a[text()*='Next']&amp;quot;, :limit =&amp;gt; 2
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;ve used the XPath text() function here to highlight its usefulness. I use it quite a lot as a shortcut to get things working and test, and it&amp;#8217;s been a lifesaver in many scenarios where the markup is inconsistent or you want to keep the scraper definition generic. And thankfully, it works for this scenario. However, be wary of using it as is in production as it may have some unexpected side effects. If one of the results that came back had the word &amp;#8220;Next&amp;#8221; in the title, then scRUBYt! would diligently follow that link and you&amp;#8217;d end up on the wrong page.&lt;/p&gt;

&lt;h2&gt;What&amp;#8217;s next?&lt;/h2&gt;

&lt;p&gt;In the next installment I&amp;#8217;ll briefly cover how to handle logging of the scrape to help you diagnose any problems, and how to handle more complex form completion.&lt;/p&gt;</description>
          <pubDate>Wed, 17 Dec 2008 10:00:35 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/12/17/web-spider-creation-with-scrubyt---part-ii/</guid>
          <link>http://rubypond.com/articles/2008/12/17/web-spider-creation-with-scrubyt---part-ii/</link>
        </item>
    
        <item>
          <title>Web Spidering and Data Extraction with scRUBYt!</title>
          <description>&lt;p&gt;Some of you may be aware that I work on (time permitting) the &lt;a href=&quot;http://www.scrubyt.org&quot; rel=&quot;nofollow&quot;&gt;scRUBYt! project&lt;/a&gt; with &lt;a href=&quot;http://www.rubyrailways.com/&quot; rel=&quot;nofollow&quot;&gt;Peter Szinek&lt;/a&gt;. Hopefully some of you have actually found an excuse to use the tool, I know there are quite a few hundred other satisfied users out there. Well Peter has been furiously working away on polishing up the lastest release, we&amp;#8217;ve also gone back and refactored a lot of the internals and improved the test coverage of library. Given the gnarly levels of recursion in it, at times it was proving difficult to add in the new features we wanted. &lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://github.com/scrubber/scrubyt/tree/skimr&quot; rel=&quot;nofollow&quot;&gt;skimr&lt;/a&gt; branch is our first attempt at refactoring, but to do it we&amp;#8217;ve sacrificed quite a lot. A lot of functionality is currently missing, and the syntax has changed slightly. I wouldn&amp;#8217;t yet consider this to be a release candidate, but it has been getting used successfully for a few months now in production so I think it&amp;#8217;s worth a look.&lt;/p&gt;

&lt;h2&gt;Whats new?&lt;/h2&gt;

&lt;p&gt;Well apart from being a lot less code, it&amp;#8217;s significantly faster and requires much less RAM on larger web scrapes. This is in part due to the fact that you can now stream your results out to a file, rather than trying to hold your entire dataset in memory before dumping them. If you don&amp;#8217;t stream your results out to a file, the default is to return them as a Hash making it much easier to develop custom output handlers, or integrate the results into your existing ruby code.&lt;/p&gt;

&lt;h2&gt;Creating your own web crawler&lt;/h2&gt;

&lt;p&gt;To begin with, we will start with the tried and true google/ruby example that has served so well with previous scRUBYt! releases. So we start by defining a new Skimr extractor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll notice here we pass in an agent type. It&amp;#8217;s an optional parameter, and if you leave it out it will default to :standard which means a combination of mechanize/hpricot to parse your results. Others will become available in future releases to allow you to scrape AJAX heavy sites again. Next, to tell it what page we want to start at:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we run over to Google (the &lt;em&gt;ncr&lt;/em&gt; bit tells Google not to redirect me to a country specific site), because we&amp;#8217;re about to start a search:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hopefully the above is fairly obvious, we&amp;#8217;ve entered the term &amp;#8220;ruby&amp;#8221; into the field named &amp;#8220;q&amp;#8221;, and hit submit. Play along in &lt;a href=&quot;http://www.google.com/search?hl=en&amp;amp;q=ruby&amp;amp;btnG=Google+Search&amp;amp;aq=f&amp;amp;oq=&quot; rel=&quot;nofollow&quot;&gt;your browser&lt;/a&gt; so you can see what we are playing with.&lt;/p&gt;

&lt;h2&gt;Extracting data from the website&lt;/h2&gt;

&lt;p&gt;Okay, so we&amp;#8217;ve got the navigation part covered. Now we want to pull out a list of all the results, it&amp;#8217;s quite simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@extractor = Skimr::Extractor.new(:agent =&amp;gt; :standard) do
  fetch &amp;quot;http://www.google.com/ncr&amp;quot;
  fill_textfield &amp;quot;q&amp;quot;, &amp;quot;ruby&amp;quot;
  submit
  page_title &amp;quot;//h3[@class='r']&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just provide an XPath to the element on the page that you want, and scRUBYt! will extract all elements that fit that definition. As the results are now available as a Hash object we could simply do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; @extractor.results.first
=&amp;gt; {:page_title=&amp;gt;&amp;quot;Ruby Programming Language&amp;quot;}
&amp;gt;&amp;gt; @extractor.results.last
=&amp;gt; {:page_title=&amp;gt;&amp;quot;Welcome! [Ruby-Doc.org: Documenting the Ruby  Language]&amp;quot;}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;ll follow this up in a couple of days with some examples of scraping deeper pages, merging multiple result sets, some of the new features we&amp;#8217;ve included, and talk about some of the future enhancements that are coming soon.&lt;/p&gt;</description>
          <pubDate>Tue, 09 Dec 2008 10:14:45 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/12/09/web-spidering-and-data-extraction-with-scrubyt/</guid>
          <link>http://rubypond.com/articles/2008/12/09/web-spidering-and-data-extraction-with-scrubyt/</link>
        </item>
    
        <item>
          <title>Custom Starting Templates for Rails Apps</title>
          <description>&lt;p&gt;Okay, so I&amp;#8217;ve been a little slow on the uptake on this one. But for anybody else that missed it, you can now define your own standard setup for a rails app. (And kudos to &lt;a href=&quot;http://www.rubyrailways.com/hot-in-edge-rails-generate-rails-apps-from-templates/&quot; rel=&quot;nofollow&quot;&gt;Peter Szinek&lt;/a&gt;, who I work with on the leading ruby &lt;a href=&quot;http://scrubyt.org/&quot;&gt;web spider/data scraping&lt;/a&gt; library, for the heads up on this last week)&lt;/p&gt;

&lt;h2&gt;Reducing the time taken to start coding&lt;/h2&gt;

&lt;p&gt;That&amp;#8217;s essentially what this change does. Most of us probably have out preferred setup, especially if we&amp;#8217;ve deployed a few sites. Typically I create the rails directory structure, then pull in HAML, rspec, rspec on rails, my form helper, restful auth, etc. It&amp;#8217;s not terribly difficult, but it is laborious. Well someone else I once worked with, &lt;a href=&quot;http://www.jeremymcanally.com/&quot; rel=&quot;nofollow&quot;&gt;Jeremy McAnally&lt;/a&gt; (woo!, look at me name drop ;), created a great little tool called &lt;a href=&quot;http://github.com/jeremymcanally/rg/tree/master/&quot; rel=&quot;nofollow&quot;&gt;rg&lt;/a&gt; which would allow you to define your own templates for when you create a new application. Now just like engines has been pulled into the latest edge core to give rails the same ability as merb-slices, so too has rg now been pulled in to match the functionality offered by creating your own custom merb-stack.&lt;/p&gt;

&lt;h2&gt;How to create a custom rails template&lt;/h2&gt;

&lt;p&gt;So if like me you have your usual grab bag you want to setup when you start a new app, you can define your own &lt;em&gt;template.rb&lt;/em&gt; file like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;run &amp;quot;rm public/index.html&amp;quot;
git :init

plugin &amp;quot;rspec&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/dchelimsky/rspec.git&amp;quot;, :submodule =&amp;gt; true
plugin &amp;quot;rspec-rails&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/dchelimsky/rspec-rails.git&amp;quot;, :submodule =&amp;gt; true
plugin &amp;quot;exception-notifier&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/rails/exception_notification.git&amp;quot;, :submodule =&amp;gt; true
plugin &amp;quot;restful-authentication&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/technoweenie/restful-authentication.git&amp;quot;, :submodule =&amp;gt; true
plugin &amp;quot;semantic-form-builder&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/rubypond/semantic_form_builder.git&amp;quot;, :submodule =&amp;gt; true
plugin &amp;quot;paperclipped&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/kbingman/paperclipped.git&amp;quot;, :submodule =&amp;gt; tru

gem &amp;quot;will-paginate&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/mislav/will_paginage.git&amp;quot;
gem &amp;quot;haml&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/nex3/haml.git&amp;quot;
rake &amp;quot;gems:install&amp;quot;, :sudo =&amp;gt; true
run &amp;quot;haml --rails .&amp;quot;

route &amp;quot;map.login '/login', :controller =&amp;gt; 'sessions', :action =&amp;gt; 'new'&amp;quot;

rakefile(&amp;quot;cruise_controle.rake&amp;quot;) do
  &amp;lt;&amp;lt;-TASK
    desc &amp;quot;Run all the tests, including API and acceptance tests&amp;quot;
    task :cruise do
      Rake::Task['db:migrate'].invoke
      Rake::Task['spec'].invoke
      Rake::Task['spec:stories'].invoke
      Rake::Task['metrics:all'].invoke
      Rake::Task['flogger:record'].invoke
    end
  TASK
end

initializer 'form_builder.rb', &amp;lt;&amp;lt;-CODE
  ActionView::Base.default_form_builder = SemanticFormBuilder
CODE

generate(&amp;quot;authenticated&amp;quot;, &amp;quot;user session&amp;quot;)
generate(&amp;quot;rspec&amp;quot;)

rake(&amp;quot;db:migrate&amp;quot;)

git :add =&amp;gt; &amp;quot;.&amp;quot;
git :commit =&amp;gt; &amp;quot;-a -m 'Initial commit'&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is quite a lot going on there, I&amp;#8217;ll quickly run through what I&amp;#8217;ve done. Firstly, I&amp;#8217;ve deleted &lt;em&gt;index.html&lt;/em&gt; as I never use it. Next we initialise a local git repository and pull in all the plug-ins I want (as git submodules). Next we have a couple of gems I need, so we define them and install (using sudo) if they&amp;#8217;re not already on the system. I setup a route to the login page, create a rake task to run cruise, an initializer to change the default form builder to be my own. And then finally I create the user/session models for restful-authentication, migrate the database, and commit all the changes.&lt;/p&gt;

&lt;h2&gt;Running your custom template&lt;/h2&gt;

&lt;p&gt;Now to create a new rails app using this template do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rails my_new_app -m ~/template.rb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or alternatively if you work across various machines you can post the template up to a server (git, your own box, etc) and specify a full HTTP to the remote file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rails my_new_app -m http://gist.github.com/33443.txt&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Mon, 08 Dec 2008 12:33:23 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/12/08/custom-starting-templates-for-rails-apps/</guid>
          <link>http://rubypond.com/articles/2008/12/08/custom-starting-templates-for-rails-apps/</link>
        </item>
    
        <item>
          <title>Ruby on Rails Hosting Round-up</title>
          <description>&lt;p&gt;&lt;em&gt;UPDATE:&lt;/em&gt; I&amp;#8217;ve extended this post based on the feedback in some of the comments. So I haven&amp;#8217;t used all of the rails hosts listed here, but I&amp;#8217;ll make it clear which those are.&lt;/p&gt;

&lt;p&gt;Working for various clients and along side various colleagues over the years, I&amp;#8217;ve been witness to a whole number of hosting providers in the ruby/rails space. Some are great, others acceptable, and a few were just down right terrible. So how do you go about choosing which host is the right one for you? Read on&amp;#8230;&lt;/p&gt;

&lt;p&gt;One of the early things I came to appreciate when working with rails was how it made me get more involved with the rest of the eco-system on the server. Previously I&amp;#8217;d just copy an ASP/.Net app across a share, maybe restart IIS. Or I&amp;#8217;d upload some PHP and maybe setup a virtual host entry for Apache and be done with it. Now it&amp;#8217;s not uncommon to have to create a deploy user, install some gems, maybe download a few dependencies (imagemagick?) and compile them on the server. Not to mention setting up monit or god to monitor various processes. With all that in mind, I&amp;#8217;ve given up on paying the extra money to get a &lt;em&gt;&amp;#8220;managed service&amp;#8221;&lt;/em&gt;. More often than not it all goes out the window because I&amp;#8217;m using a package I compiled myself rather than the dated version in the package management system, or they just don&amp;#8217;t have enough of a clue on the ruby/rails front to be useful. So to make this a somewhat level playing field, keep in mind that I&amp;#8217;m working under that basis that anything software related you need to be able to resolve yourself with these providers (if they give you access). We will leave hardware up to them.&lt;/p&gt;

&lt;h2&gt;Unmanaged Rails Hosting&lt;/h2&gt;

&lt;p&gt;So without further ado, here&amp;#8217;s my list of personal experiences if you&amp;#8217;re willing to go the unmanaged route.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot; http://www.serverbeach.com/catalog/cust_ref_landing_new.php?REF=58X87H9SEH&quot; rel=&quot;nofollow&quot;&gt;Serverbeach&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This is the unmanaged brand of Peer1, and they&amp;#8217;re who I currently host all of my own production and development sites with. I really can&amp;#8217;t endorse them highly enough. You can have a low-end dedicated server for development purposes from as little as $75/month, and they&amp;#8217;ll often run specials so watch their page. I grabbed a quad-core dual xeon with 2GB of RAM, and a 2000GB transfer allowance for $179/month (they currently have RAID capable dual-core Xeons for $139). A choice of server locations if that is important to you, as well as hardware firewall, backup, and all the various offerings you come to expect. They also send a survey around each year and customers get to vote on what new offerings they should provide. Cloud computing was on the list this year, lets see if it turns out to be as competitive as EC2 and the like.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.rimuhosting.com/&quot; rel=&quot;nofollow&quot;&gt;Rimuhosting&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Another excellent provider. I&amp;#8217;ve used these guys as my main provider for quite a while until our needs got a little too much for a fully worked VPS, and their dedicated plans just didn&amp;#8217;t quite match the value Serverbeach offered. That being said, unless you&amp;#8217;ve got particularly high transfer or memory requirements I doubt you&amp;#8217;ll have any problems at all with what they offer. I still have one of our sites running over there, and a number of client sites, and I have no intention of moving.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.railsmachine.com/&quot; rel=&quot;nofollow&quot;&gt;RailsMachine&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;ve worked on these quite a bit for various clients, and I feel a little ho hum. There&amp;#8217;s not as though there is anything exactly wrong with the product they offer, I just think for the price point ($250/month for a dedicated CPU) it&amp;#8217;s a little on the expensive side for what you get. It&amp;#8217;s almost a cross between an unmanaged and fully managed setup. You pay the price of the latter but set a lot of it up yourself by running a series of scripts and installing local gems (as detailed on their wiki).&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.a2hosting.com/&quot; rel=&quot;nofollow&quot;&gt;A2Hosting&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Now I need to put a disclaimer on this one at the preface; I haven&amp;#8217;t used these guys in almost three years, and hopefully things have changed since then. However, at the time their rails support was dreadful. I only ever ran one site there which was a rather simple blog, and uploading images and resizing with rmagick (ala attachment_fu/paperclip) resulted in me bringing down what was obviously a seriously overloaded server. And from what I was informed it wasn&amp;#8217;t just my account which was affected, it would halt any VPS running on the same physical machine. After being unable to place any kind of CPU quota on my account to stop other from being affected, or having a box more suitable for running rails as advertised I had to take things elsewhere. Suffice to say, I&amp;#8217;ve not been back.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.slicehost.com/&quot; rel=&quot;nofollow&quot;&gt;Slicehost&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;ve not used them personally, but have worked closely with quite a few people who host their sites on them. For the money ($20/month), they&amp;#8217;re hard to beat. And if all you need is a VPS to run your blog, I&amp;#8217;d think you&amp;#8217;d be hard pressed beating them for value.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;https://www.linode.com/&quot; rel=&quot;nofollow&quot;&gt;Linode&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Another one I&amp;#8217;ve not used personally, but it got a few mentions within the comments of the article when I first posted it so I thought it was worthy of pointing out. They have their own management panel and run your setup using Xen. Prices start from US$19.95/month and include 200GB data transfer.&lt;/p&gt;

&lt;h2&gt;Managed Services&lt;/h2&gt;

&lt;p&gt;At the other end of the spectrum is the fully managed services. Take all the worry out of actually building your box and only concern yourself with deployment. If that&amp;#8217;s the kind of dream you think you&amp;#8217;re willing to pay for, then your options are:&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.engineyard.com/&quot; rel=&quot;nofollow&quot;&gt;Engine Yard&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;The big daddy in the ruby/rails hosting world, if you&amp;#8217;ve not heard of them you must obviously have been living under a rock. At $399+/month you&amp;#8217;re comparatively paying through the nose when measured against the unmangaged offers, but when the the employee lists consists of the likes of Ezra Zygumnowitcz, Yehuda Katz, Evan Phoenix, etc. then I don&amp;#8217;t think you&amp;#8217;re going to find a better crack squad of ruby experts to manage things for you.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.rackspace.com/&quot; rel=&quot;nofollow&quot;&gt;Rackspace&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;They&amp;#8217;ve been in the game for years, long before rails was on the scene, and they are seriously excellent for most hosting needs. I&amp;#8217;ve only used them a few times, and only have good things to say. However, feedback in the comments seems to indicate that for rails based apps their support is lacking. They don&amp;#8217;t advertise their price on their site, but expect it to be somewhere above $400/month. At that price, it&amp;#8217;s hard for them to be a serious consideration against EngineYard.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.peer1.com/&quot; rel=&quot;nofollow&quot;&gt;Peer1&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;ServerBeach back again with their managed offering. I can&amp;#8217;t really say much more other than their hardware is exceptional and their support when I&amp;#8217;ve needed it likewise. You&amp;#8217;ll need to contact them for details on price.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://www.railsmachine.com/&quot; rel=&quot;nofollow&quot;&gt;RailsMachine&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Another one back again with a managed offering, this time for $349/month. On top of your hosting monthly hosting fees it puts them above most the others in terms of cost. &lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There are a heap to choose from, and far too many for me to be able to give an experienced and qualified view on. Personally though, I&amp;#8217;m quite happy with my unmanaged dedicated servers and having a separate management contract for the ones that I need to maintain five 9 uptime with. It gives me the business continuity I want and the comfort of having a much closer personal relationship with a handful of people who actually know and understand my business, at a price that is significantly lower than most of the packaged deals.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d love to hear from others out there that have had experiences with other hosting providers though so please leave your thoughts, good or bad, in the comments section.&lt;/p&gt;

&lt;p&gt;Oh, and if you&amp;#8217;re after someone to help manage your server I use these guys &lt;a href=&quot;http://www.atalanta-systems.com/&quot; rel=&quot;nofollow&quot;&gt;Atalanta Systems&lt;/a&gt; and &lt;a href=&quot;http://www.facebook.com/pages/Bitfield-Consulting/6174254583&quot; rel=&quot;nofollow&quot;&gt;Bitfield Consulting&lt;/a&gt;&lt;/p&gt;</description>
          <pubDate>Thu, 04 Dec 2008 23:18:27 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/12/04/ruby-on-rails-hosting-round-up/</guid>
          <link>http://rubypond.com/articles/2008/12/04/ruby-on-rails-hosting-round-up/</link>
        </item>
    
        <item>
          <title>When (ruby) floating just isn't good enough</title>
          <description>&lt;p&gt;Hopefully we all know that when talking about numbers &amp;#8220;float&amp;#8221; means &amp;#8220;floating point&amp;#8221; and as such the number isn&amp;#8217;t entirely precise, it&amp;#8217;s just an approximation. Most of the time it&amp;#8217;s a good enough approximation to serve our needs, but when it comes to dealing with money it&amp;#8217;s best to play it safe and have the absolute precision we want. Otherwise all those .000001 of a cents can add up to a large sum.&lt;/p&gt;

&lt;h2&gt;Working with fixed point arithmetic&lt;/h2&gt;

&lt;p&gt;To get around the short-comings of using floating points, a fairly common and trivial task is simply multiply it to the number of significant digits we care about and then treat it as an integer. So for dealing with money, we would multiply the value &lt;em&gt;$120.19&lt;/em&gt; by 100 to end up with &lt;em&gt;12019&lt;/em&gt; cents. Any arithmetic we do, we do on the expanded cent value and we store that in the database. If we want to display a nicely format dollar value to the end user, we do that after we pull it back out from the database.&lt;/p&gt;

&lt;h2&gt;Losing money with Ruby&lt;/h2&gt;

&lt;p&gt;As I said, all this is rather trivial and many of you have probably had to do it in the past. So here is an excercise for the reader to follow along with at home. What do you think the following would output?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;quot;0.29&amp;quot;.to_f&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you answered 0.29 pat yourself on the back. Let&amp;#8217;s take it a step further:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;quot;0.29&amp;quot;.to_f * 100&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Who answered 29.0? Congratulations. Okay, and now to take home the full showcase and all the cash:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(&amp;quot;0.29&amp;quot;.to_f * 100).to_i&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Do we hear a 29 out there? Hooray! You&amp;#8217;re not alone, &lt;em&gt;but you&amp;#8217;re wrong&lt;/em&gt;. Fire up your nearest ruby console and give it a shot, you&amp;#8217;ll actually get _28_ as the output. If you&amp;#8217;ve made the same assumption yourself in the past, it&amp;#8217;d be worth going back and checking your code to make sure it works. Likewise if you&amp;#8217;re using a 3rd party library it&amp;#8217;s worth double-checking they&amp;#8217;ve done the correct implementation.&lt;/p&gt;

&lt;h2&gt;Doing ruby floating points and money properly&lt;/h2&gt;

&lt;p&gt;So how do you get around this problem? Well from reading the &lt;a href=&quot;http://www.ruby-doc.org/core/classes/Float.html#M000235&quot; rel=&quot;nofollow&quot;&gt;ruby docs on float&lt;/a&gt; I&amp;#8217;d still expect &lt;em&gt;.to&lt;/em&gt;i_ to work, but clearly it&amp;#8217;s not actually truncating the value as documented. Instead, you have to call &lt;em&gt;round()&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(&amp;quot;0.29&amp;quot;.to_f * 100).round&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alternatively, you can use the &lt;a href=&quot;http://github.com/FooBarWidget/money/tree/master&quot; rel=&quot;nofollow&quot;&gt;money gem&lt;/a&gt; as it does it properly.&lt;/p&gt;</description>
          <pubDate>Fri, 28 Nov 2008 15:05:23 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/11/28/when-ruby-floating-just-isnt-good-enough/</guid>
          <link>http://rubypond.com/articles/2008/11/28/when-ruby-floating-just-isnt-good-enough/</link>
        </item>
    
        <item>
          <title>Easily Generating Content For Your Site</title>
          <description>&lt;p&gt;Apologies for the lack of action here late, I&amp;#8217;ve got a long list of stuff I&amp;#8217;ve meant to be writing about but just not quite finding the time to fit it in around client work. I think I&amp;#8217;m going to just have to start allocating a time each fortnight into my schedule, but don&amp;#8217;t hold me to that. But while we are talking about content ideas, how about some help generating some for your own site?&lt;/p&gt;

&lt;p&gt;Part of the problem many people have, be they bloggers or just running their own small online business, is generating content ideas to help drive traffic. A quick and easy solution comes courtesy of the guys I&amp;#8217;m contracting to a few days a week at the moment, &lt;a href=&quot;http://www.wordtracker.com/&quot; rel=&quot;nofollow&quot;&gt;Wordtracker&lt;/a&gt;. The new &lt;a href=&quot;http://labs.wordtracker.com/keyword-questions/&quot; rel=&quot;nofollow&quot;&gt;Keyword Questions&lt;/a&gt; tool lets you enter in a seed word, and fires back the questions that people have asked on that topic from their database. Don&amp;#8217;t get too caught up in the numbers here, as it&amp;#8217;s only a (hopefully representative) sample of the total number of internet users. The most useful part of it is the actual questions that are being asked.&lt;/p&gt;

&lt;p&gt;Try doing a search for business on there. If you were running a site trying to target small businesses, it&amp;#8217;d be worthwhile considering putting up a series of posts dealing with creating a business plan, how to get money to start a business, and how to create an online business, etc. The same can be done with whatever niche/sector you are operating. And better yet, it gives you the exact keywords people are using to help with your SEO efforts.&lt;/p&gt;

&lt;p&gt;This tool came out on the back of just one of the content creation ideas in Wordtracker&amp;#8217;s &lt;a href=&quot;http://www.wordtracker.com/offers/kickass/&quot; rel=&quot;nofollow&quot;&gt;50 Kick-Ass Keyword Strategies&lt;/a&gt;. If you&amp;#8217;re looking for new simple ways to improve your visibility search engines it&amp;#8217;s well worth the investment. Given my experience working with them I&amp;#8217;m hoping I can feed some of the great SEO knowledge into various blog posts over time too.&lt;/p&gt;</description>
          <pubDate>Mon, 24 Nov 2008 08:46:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/11/24/easily-generating-content-for-your-site/</guid>
          <link>http://rubypond.com/articles/2008/11/24/easily-generating-content-for-your-site/</link>
        </item>
    
        <item>
          <title>Merbcamp Videos</title>
          <description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; They are all now available on the &lt;a href=&quot;http://merbcamp.com/video&quot; rel=&quot;nofollow&quot;&gt;merbcamp&lt;/a&gt; site.&lt;/p&gt;

&lt;p&gt;Unfortunately I only managed to capture the stream from day 2. But here are all the videos. I&amp;#8217;ll be posting them in downloadable formats later this evening. If you want to review my notes I took while watching the presentations, check out &lt;a href=&quot;/articles/2008/10/11/merbcamp---notes-from-the-edge/&quot;&gt;notes from merbcamp day 1&lt;/a&gt; and &lt;a href=&quot;/articles/2008/10/12/merbcamp---day-2/&quot;&gt;notes from merbcamp day 2&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/deploying-a-merb-app&quot;&gt;Deploying a Merb app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/real-time-web-apps-with-orbited-and-merb&quot;&gt;Real time web apps with Orbited and Merb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/learning-from-django&quot;&gt;Learning from Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/writing-a-merb-plugin-101&quot;&gt;Writing a Merb Plugin 101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/expanding-our-idea-of-the-background-web-with-merb&quot;&gt;Expanding our idea of the background web with Merb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/merb-qa-session&quot;&gt;Q&amp;A Session&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/driven-merb-a-user-story&quot;&gt;Driven Merb: A User Story&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/merb/merbcamp-08/merb-keynote&quot;&gt;Merb Keynote&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
          <pubDate>Fri, 17 Oct 2008 12:36:01 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/10/17/merbcamp-videos/</guid>
          <link>http://rubypond.com/articles/2008/10/17/merbcamp-videos/</link>
        </item>
    
        <item>
          <title>Merbcamp - Day 2</title>
          <description>&lt;p&gt;In case you missed the first installment, click to read &lt;a href=&quot;http://rubypond.com/articles/2008/10/11/merbcamp---notes-from-the-edge/&quot;&gt;day one at merbcamp&lt;/a&gt;. This is what happened on day 2:&lt;/p&gt;

&lt;h2&gt;Deploying a Merb app&lt;/h2&gt;

&lt;p&gt;&amp;#8220;Your number one priority when building a merb app should be deployment&amp;#8221;. It&amp;#8217;s going to make scaling much easier later. As a result, there are some decisions you need to consider very early on in the process.&lt;/p&gt;

&lt;h3&gt;Freezing&lt;/h3&gt;

&lt;p&gt;You&amp;#8217;ve got two ways to freeze merb and dependencies into your application folder:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thor merb:stable
thor merb:edge&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But should you freeze or not? And if so, which option should you take? The 3 options you&amp;#8217;ve got are:&lt;/p&gt;

&lt;h4&gt;Frozen gems&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Stable release&lt;/li&gt;
&lt;li&gt;Everything is contained within your app (in merb_root/gems)&lt;/li&gt;
&lt;li&gt;Start app with merb_root/bin/merb&lt;/li&gt;
&lt;li&gt;Maximum deployability&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Frozen git&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Edge release&lt;/li&gt;
&lt;li&gt;Everything is contained within your app (in merb_root/src)&lt;/li&gt;
&lt;li&gt;Start app with merb_root/bin/merb&lt;/li&gt;
&lt;li&gt;Maximum deployability&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;&amp;#8220;Thawed&amp;#8221;&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Stable or Edge&lt;/li&gt;
&lt;li&gt;Everything as gems&lt;/li&gt;
&lt;li&gt;Start app with wherever merb has been installed&lt;/li&gt;
&lt;li&gt;Least deployability, least recommended&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Managing your app dependencies with thor&lt;/h3&gt;

&lt;p&gt;Once you&amp;#8217;ve frozen everything within your app directory, you have two ways to upgrade your dependencies. Updating all of your frozen gems within your application from rubyforge or wherever:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thor merb:gems:refresh&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or rebuilding all of your native extensions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thor merb:gems:redploy&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Web servers&lt;/h3&gt;

&lt;p&gt;The main options on the front end are apache or nginx, pushing requests through to mongrel, thin, or ebb. Nothing really that different to rails here.&lt;/p&gt;

&lt;p&gt;The other option is passenger, again nothing different to rails here.&lt;/p&gt;

&lt;h3&gt;Starting and stopping merb&lt;/h3&gt;

&lt;p&gt;You&amp;#8217;ve got 2 options here:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;merb -k
merb -K&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;the latter starts merb gracefully, the latter forcefully. Graceful will clean up pid files. Forceful will allow the service to start regardless. New in the latest code base is the following enhancement:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kill -USR1 pid_here&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which will output the current config of the server (running on the PID you specify) as YAML. &lt;/p&gt;

&lt;p&gt;You&amp;#8217;ve also got merb-manage, which you pass in start/stop/restart/reload. Reload does a fast restart which means very very little downtime between starts because it keeps the config and gem dependencies but just reloads the app files.&lt;/p&gt;

&lt;p&gt;merb &amp;#8211;help is your friend to find out what other options you&amp;#8217;ve got&lt;/p&gt;

&lt;h3&gt;monitoring merb&lt;/h3&gt;

&lt;p&gt;collectd is a lightweight statistics collection daemon. Plugin based and network aware. A configuration definition looks like a fairly lightweight XML-style file. Includes a basic PERL CGI script which extracts data out and allows it to be viewed on a graph. Allows you to map things like the number of TCP connections over time, ruby process CPU time, memory usage, etc.&lt;/p&gt;

&lt;p&gt;collectd-nagios is a plugin that allows nagios to interrogate any statistic collected by collectd. Point it at a statistic and flag up the appropriate alert should it not be within acceptable bounds.&lt;/p&gt;

&lt;h3&gt;Configuration management&lt;/h3&gt;

&lt;p&gt;An intro to puppet for those that haven&amp;#8217;t used/seen it before. Allows you to describe how you want a various machine, machine type, etc. to be configured. What services need to be installed, running, and the required configurations files. Your manifests/configurations are managed via a version control system (svn, git, whatever you want). You check in your config changes, pull it out onto your puppet master and all your nodes will be updated with the required&lt;/p&gt;

&lt;h3&gt;Exception Handling&lt;/h3&gt;

&lt;p&gt;Use the merb_exceptions plugin and configure with the appropriate settings like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:exceptions:
  :app_name: Skippy
  :email_from: exceptions@skippy.com
  :email_addresses:
  - me@skippy.com
  :environments:
    - production&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure you&amp;#8217;ve got merb-mailer setup, and set your delivery method to sendmail to reduce the potential problems:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Merb::Mailer.delivery_method = :sendmail&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Named Instances&lt;/h3&gt;

&lt;p&gt;Within your configuration file you can give your instance a name, and it will mean you can easily identify processes when doing a process listing. The syntax is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Merb::Config.use do |c|
  c[:name] = 'skippy'
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Real time web apps with Orbited and Merb&lt;/h2&gt;

&lt;p&gt;What is Comet? It&amp;#8217;s real-time web apps and it&amp;#8217;s easy. Facebook should have known better, they didn&amp;#8217;t need to write a custom stack on top of erlang. The wheel doesn&amp;#8217;t need to be re-invented, we have the socket and protocol definitions that we need.&lt;/p&gt;

&lt;p&gt;In HTML5 we&amp;#8217;ve access to WebSocket, and you can create a new one like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;new WebSocket(&quot;ws://host.com&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we get 3 callbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;onread&lt;/li&gt;
&lt;li&gt;onopen&lt;/li&gt;
&lt;li&gt;onclose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Orbited is a python server that provides a WebSocket API within all browsers. The Orbited daemon acts as a security control between the browser and TCP, tunneling over HTTP. This means that you can implement push based services using protocols like XMPP to provide data to clients rather than the current AJAX polling approach. The list of protocols being implemented is much longer than I&amp;#8217;ll list here, but it&amp;#8217;s unlikely you&amp;#8217;ll be left wanting.&lt;/p&gt;

&lt;p&gt;Ultimately it means you can use HTTP where it&amp;#8217;s appropriate, and then more appropriate protocols when they are better suited to the task (i.e., messaging).&lt;/p&gt;

&lt;p&gt;It sounds like Orbited is a bit of an interim technology to back-port the WebSocket definition from HTML5 into today&amp;#8217;s browsers. Once HTML5 is implemented you&amp;#8217;ll be able to have native WebSocket support.&lt;/p&gt;

&lt;h2&gt;Writing a Merb plugin 101&lt;/h2&gt;

&lt;h3&gt;Merb::Slices&lt;/h3&gt;

&lt;p&gt;merb-slices are reusable and over-writable mini-apps. They are much better than generated code because every time you want to change your code, you don&amp;#8217;t need to re-generate the code you just pull in the update. If you&amp;#8217;ve got your own overrides there is no problem. Some of the most popular slices are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login form&lt;/li&gt;
&lt;li&gt;Password reminder&lt;/li&gt;
&lt;li&gt;Blog&lt;/li&gt;
&lt;li&gt;Forum&lt;/li&gt;
&lt;li&gt;Event Registration&lt;/li&gt;
&lt;li&gt;Admin Interface&lt;/li&gt;
&lt;li&gt;Tune Up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When should you use them? When you want to target application content.&lt;/p&gt;

&lt;h3&gt;Merb::Plugins&lt;/h3&gt;

&lt;p&gt;Firstly, they are &lt;strong&gt;not&lt;/strong&gt; DataMapper plugins (like the acts&lt;em&gt;as_* plugins). They are used when you want to extend the framework, but don&amp;#8217;t use alias&lt;/em&gt;method_chain. This was touched on briefly, and it seems that in the merb world it&amp;#8217;s about as evil as evil gets. Basically it&amp;#8217;s a hack that lets people write their own methods as a decorator around the underlying framework API to get their own implementation in where they need it. Merb has taken the approach of providing hooks at the relevant places you might need them.&lt;/p&gt;

&lt;h3&gt;Merb Hooks&lt;/h3&gt;

&lt;h4&gt;Merb::BootLoader&lt;/h4&gt;

&lt;p&gt;Is called when merb first starts up. You have access to at least two events (at the moment) within the boot up process:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Merb::BootLoader.before_app_loads
Merb::BootLoader.after_app_loads&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Using the Merb API&lt;/h3&gt;

&lt;p&gt;There are essentially 3 types of methods within the API. Private, public, and plugin methods. Don&amp;#8217;t ever touch the private ones, there is no guarantee they won&amp;#8217;t be changed in core without warning. If you don&amp;#8217;t have the hook you need, ask them for it. You can specify a version dependency within your plugin, and so long as you stick to the rules you&amp;#8217;re right to say that your plugin will work &amp;lt;= 2.0.&lt;/p&gt;

&lt;h3&gt;Testing Plugins&lt;/h3&gt;

&lt;p&gt;Make sure you test your plugins through the full stack, you want to make sure that the plugin you&amp;#8217;re using will work with the version of merb you are using. If you&amp;#8217;re mocking everything out, you&amp;#8217;ve got no guarantee of that.&lt;/p&gt;

&lt;h2&gt;Learning from Django&lt;/h2&gt;

&lt;p&gt;The django equivalent of merb-slices has proven to be awesome, so embrace them. On a project you&amp;#8217;ll likely end up with a heap of them but don&amp;#8217;t worry. The benefits from reusability are worth it, and they embrace the unix philosophy of do one thing, do it well, and work well together. Even simple django apps typically end up with a dozen or so slices.&lt;/p&gt;

&lt;p&gt;So move towards slice-centric development where the slice becomes the core way to develop. The end result is something like the project pinax in django. The merb project gluttonberg is heading in that direction.&lt;/p&gt;

&lt;p&gt;The merb routing kicks ass, hopefully django looks like that soon. &lt;/p&gt;

&lt;p&gt;Something that is missing in merb that django does have is automatic admin interface generation. It&amp;#8217;s not like rails scaffolding so it won&amp;#8217;t break when you implement model changes. It&amp;#8217;s tightly bound to the ORM though, and given merb&amp;#8217;s ORM-agnostic approach it could be difficult to implement on this side of the fence.&lt;/p&gt;

&lt;p&gt;Django also has generic controller generation, which sounds a lot like the make_resourceful type implementations in rails. You also get feed syndication almost for free.&lt;/p&gt;

&lt;p&gt;It also looks like django.contrib has some awesome re-usable components. An example given in the presentation was importing logic to handle capturing US social security numbers. You import the library, and you get for free the appropriate form and all the validation.&lt;/p&gt;

&lt;p&gt;The django docs have historically also kicked ass, and getting good docs makes adoption so much easier. Rdocs really don&amp;#8217;t cut it.&lt;/p&gt;

&lt;h2&gt;Driven Merb: A user story&lt;/h2&gt;

&lt;p&gt;A pretty quick presentation on the benefits of using user stories in development, and BDD. The high-level full stack tests fits nicely with Yehuda&amp;#8217;s &amp;#8220;test what you care about&amp;#8221; points from yesterday. We got some quick examples of running stories in both webrat and selenium. If you&amp;#8217;re new to stories, check out David Chemlimsky&amp;#8217;s stuff and rspec and the new story runner (called cucumber), they&amp;#8217;ll do it much more justice than my paraphrasing here.&lt;/p&gt;

&lt;h2&gt;From Rails to Merb (Merb team panel Q&amp;amp;A)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: What is thor, and how do we use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Rake was sort of a hack that became the lingua franca for making scripts in ruby, but it didn&amp;#8217;t support command line arguments so people provided a multitude of ways to get options out. Thor allows you to specify a command and provide a series of options, that was originally intended to run your own binaries. It&amp;#8217;s as easy to use as rake, but provides more options, and allows tasks to be system wide and not just application specific.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the core team doing to make merb easy to install and get up and running?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: You don&amp;#8217;t need git to run merb, you only need that if you want to run edge. You can install everything you need via gem. You will be able to do &amp;#8220;gem install merb&amp;#8221; and then &amp;#8220;merb-gen app&amp;#8221; to get up and running.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What do you see as the biggest barrier to growth of merb usage?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: The biggest barrier has been how fast it&amp;#8217;s been developing and how quickly things have been changing. Going 1.0 will be the biggest barrier knocker-downer on that front, as people can be happy that the API is solid and stable and won&amp;#8217;t be changing every week.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do you guys find time to organise yourself on various open source projects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: No sleep, and general addictions to OSS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the Engine Yard/Core team view on alternative ruby implementations such as Rubinius and JRuby, and does merb run on JRuby?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Yes it runs on JRuby. And merb will run on anything that rails runs on, Engine Yard&amp;#8217;s position is ruby is good and make ruby win. So support them all.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Short of improving stability and small evolutionary changes is there anything cool/big/different you&amp;#8217;d like to to introduce to merb in plugins/slice/etc?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Wait for the keynote&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: I have an app deployed with users, authentication, etc. how do I chunk it down to migrating with merb?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: merb-auth isn&amp;#8217;t going to dictate how your authentication is going to work, so you should just be able to port over your user model and the logic within. If you&amp;#8217;re using restful&lt;/em&gt;authentication by Rick Olson then there is a mixin you can use._&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How does core see Rubinius support within merb?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: As soon as it supports rails, we&amp;#8217;ll support it. There&amp;#8217;s lots of cool things in Rubinius that you can&amp;#8217;t do in MRI, so as soon as it&amp;#8217;s closer to production ready they&amp;#8217;ll be onto it. We won&amp;#8217;t limit merb to Rubinius once it&amp;#8217;s out though, we&amp;#8217;d look to support MagLev and co.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Just like RJS covers up javascript, is merb stack going to cover merb to the point where it would be painful to get under the hood?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Absolutely not, if it does then it&amp;#8217;s a bug. Merb stack is designed to generate the code you&amp;#8217;d have to do yourself, not hide you from merb core. You&amp;#8217;ll also be able to make your own stacks if you need to have your own standard setup.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: One of the things I dislike about rails is how the mindset of the rails core developers has changed as Rails has gained popularity. Do we have to worry about that here?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Absolutely not. If any of the core tenants of merb are violated Ezra will kill people :) Because the merb project isn&amp;#8217;t tied into specific applications that they&amp;#8217;re trying to build (unlike the 37signals apps that rails was extracted from), they&amp;#8217;re always thinking about the benefit to the community. That&amp;#8217;s not to say rails isn&amp;#8217;t thinking about the community, but the merb approach is less opinionated because they are dealing with a diversity of opinions and not a single approach.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do we support internationalization in merb? Did you abandon the rails internationalization solution?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: No we didn&amp;#8217;t abandon internationalization and we still want to do it, but we want to do it in the merb way. Matt A personally worked on the rails API, and the problem with the way it was done in rails wont work with merb. Merb&amp;#8217;s approach is all about performance and speed, and the original approach was slowing merb down. We will be working on it, but the only real solution is to do it in C. It&amp;#8217;s about half way done.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: With ruby 1.9 coming around in December, has merb come to support that?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: merb should run fine on it, but it hasn&amp;#8217;t been tested for quite a while. That being said, we still wonder if the API really is locked down for 1.9 and that there won&amp;#8217;t be any changes before December. The main problem is with support in other gems your app is dependent on. At this point, there is no clear guidance from the ruby core team so we have to wait until people are using 1.9&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: You guys on the panel are all ruby and merb hackers, but you need to help us get there. What help can you provide?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Go read interesting code and try and grok it and understand it, then hack and make sure you understand it. Try and fix bugs in frameworks. There are a bunch of good books out there, read blog, read code on github, check out your local user groups and IRC. Make sure things you&amp;#8217;re doing are fun and cool to keep your motivation levels high. Code things you&amp;#8217;re interested in. There are 2 merb books coming out, &amp;#8220;The Merb Way&amp;#8221; and &amp;#8220;Merb in Action&amp;#8221;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can you each talk about your workflow on a typical day with regard to coding?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: The general consensus seems to be to spike when working on something experimental. Then detailing a list of things to implement, that can be either some specs, an actual implementation against the still-to-be-developed API, a list of work, etc. then go make it work. Go speak to someone else about the problem to get another perspective, especially from someone who doesn&amp;#8217;t understand the problem you&amp;#8217;re working on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: If we see something that interests in merb and we want to contribute, what process do we follow?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Get in touch (mailing list, irc, etc.), check out lighthouse, or submit a patch. Come talk to them before you submit a patch though, you don&amp;#8217;t want to spend hours working on a patch and having it rejected because it doesn&amp;#8217;t fit the general approach guidelines. The process is usually fork the the repo, create a branch for each bug you fix so it can be cherry picked, fix it and don&amp;#8217;t send a pull request but create a patch and attach it to a lighthouse ticket or provide the branch to pull from (and keep it up to date with master so it&amp;#8217;s easier to apply when they get around to it).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What&amp;#8217;s your favourite deployment strategy?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A: Capistrano or Vlad, deploy to staging and if it works deploy to live. But always do it from a tag. And use ruby enterprise edition, it fixes garbage collection and allows you to efficiently share memory across child processes. When you deploy your app, you need to make sure that you use the thor task to rebuild the native gems so they&amp;#8217;re recompiled for the deployed platform&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Expanding our idea of the background web with Merb&lt;/h2&gt;

&lt;p&gt;HTML makes things look pretty, but all the interesting stuff happens in the background behind what you see in your web browser. &lt;/p&gt;

&lt;h3&gt;Running Background Tasks in Merb&lt;/h3&gt;

&lt;p&gt;You have a few ways to run tasks in the background. If you want to use cron, you can just setup some rake tasks. Within merb itself you have the &lt;em&gt;render&lt;em&gt;then&lt;/em&gt;call&lt;/em&gt; and &lt;em&gt;run_later&lt;/em&gt; methods. You can call them like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;render_then_call do
  Node.inactive.purge
end

run_later do
  Node.scan(Node.first)
end
render&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the presentation I couldn&amp;#8217;t glean what the effective difference is between the two calls.&lt;/p&gt;

&lt;h3&gt;WebServices in Merb&lt;/h3&gt;

&lt;p&gt;Merb handles RESTful web services with the provides, display, and render methods. An example definition that makes it possible is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Posts &lt; Application
  provides :json
  def show
    @post = Post.get(params[:id])
    display
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It will automatically assume you want to provide HTML as well, if you want &lt;strong&gt;only&lt;/strong&gt; JSON then you use &lt;em&gt;only&lt;/em&gt;provides_ instead of &lt;em&gt;provides&lt;/em&gt;. Merb&amp;#8217;s equivalent of the rails &lt;em&gt;respond&lt;/em&gt;to_ statement is a case statement:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;case content_type
when :html
  render
when :json
  display @post.to_json
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The rails respond_to block means a proc needs to be created and evaluated when you won&amp;#8217;t need to evaluate at least half of it (i.e., you only return one format). It&amp;#8217;s about 10x slower than the merb approach. You actually don&amp;#8217;t need the case statement normally though you should just call display and it will work out the format switching.&lt;/p&gt;

&lt;h2&gt;Keynote&lt;/h2&gt;

&lt;p&gt;Yehuda is talking about some of the bad press about &amp;#8220;ruby is slow&amp;#8221; and how the community response is usually &amp;#8220;Ok!&amp;#8221;, and that&amp;#8217;s just embarrassing. He want looking for some benchmarks and found that rails generally outperforms CakePHP, CodeIgniter and similar frameworks the people traditionally think are much faster than ruby. They got in the region of 3-4 requests/sec. So how does merb stack up? &lt;/p&gt;

&lt;h3&gt;Merb Performance Benchmarks&lt;/h3&gt;

&lt;p&gt;A simple &amp;#8220;hello world&amp;#8221; scenario was used to show that ruby isn&amp;#8217;t super slow, that if you go through the stack you still get reasonable performance. Returning a rack response directly from the router handled 3,500 req/sec. Doing a string render returned 2,000 req/sec. Rendering a template comes in at 1,500 req/sec.&lt;/p&gt;

&lt;p&gt;Compare that to Apache serving static HTML which got 4,000 req/sec. Comparing it to the PHP equivalent of &amp;#8220;hello world&amp;#8221; showed almost identical performance to the merb controller rendering string &amp;#8220;hello world&amp;#8221;. Things really get interesting when comparing it to rendering a full template vs. using PHP CodeIgniter which is meant to be the fastest PHP engine. CodeIgniter gets 300 req/sec, that&amp;#8217;s against the 1,500 req/sec you get from the standard merb setup. CakePHP was even worse with under 100 req/sec.&lt;/p&gt;

&lt;p&gt;The ruby leaders have incorrectly conceded the performance ground just because ruby is slow at fibonacci, but PHP is slow in other areas. It has to load entire frameworks up at runtime. Our web servers (rack/thin) are far more optimized and based in C.&lt;/p&gt;

&lt;h3&gt;Merb vs Rails vs Sinatra&lt;/h3&gt;

&lt;p&gt;Next was comparing merb against other ruby options. Returning directly from the merb router kills everything, but there aren&amp;#8217;t many scenarios you could use that. Sinatra is just slightly faster than returning from the merb controller, which both outperform Rails by a 3-4x. Rails itself still kills CakePHP.&lt;/p&gt;

&lt;h3&gt;The Future - Merb 2.0&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s going to stay modular, but it&amp;#8217;s also going to be integrated (back to that unix philosophy). Looking at django is an important part of moving forward because they&amp;#8217;ve done lots of things well, but it won&amp;#8217;t be so monolithic and a tangled web of dependencies. But the out of the box user experience should be just as pleasant. A consistent merb ORM so that you interface in a single way, and the ORM plugins will work out what underlying methods would be called in DataMapper, Sequel, or whatever you are using. These means the admin type interfaces django has would be possible.&lt;/p&gt;

&lt;p&gt;Mailer will move towards a messenger approach, mail isn&amp;#8217;t the only way you want to send notifications these days.&lt;/p&gt;

&lt;h3&gt;Moving towards Merb 2.0&lt;/h3&gt;

&lt;p&gt;The 1.0 release is a stake in the ground, the 1.x releases will be entirely backward compatible but they&amp;#8217;re just stable experiments and an incremental step towards 2.0. Don&amp;#8217;t consider any new changes between 1.0 and any 1.x to always be there, the 1.x releases are not the same stake in the ground. Bug fixes and additions to the stable release will be applied as 1.0.x.&lt;/p&gt;

&lt;h3&gt;How can you help?&lt;/h3&gt;

&lt;p&gt;Contribute to the central slice repository, but make sure they rigidly adhere to the public API and don&amp;#8217;t use any plugins or slices that aren&amp;#8217;t. Report missing functionality. Work on the wiki, you can&amp;#8217;t beat community driven documentation. Help test RC1. Report any missing documentation. List your site on &lt;a href=&quot;http://www.merbunity.com&quot; rel=&quot;nofollow&quot;&gt;Merbunity.com&lt;/a&gt;.&lt;/p&gt;</description>
          <pubDate>Sun, 12 Oct 2008 17:29:17 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/10/12/merbcamp---day-2/</guid>
          <link>http://rubypond.com/articles/2008/10/12/merbcamp---day-2/</link>
        </item>
    
        <item>
          <title>Merbcamp - notes from the edge</title>
          <description>&lt;p&gt;A recap on the presentations from the first day of the very first &lt;a href=&quot;http://www.merbcamp.com/&quot; rel=&quot;nofollow&quot;&gt;Merbcamp&lt;/a&gt;. If you want to read about day to, check this page &lt;a href=&quot;http://rubypond.com/articles/2008/10/12/merbcamp---day-2/&quot;&gt;Merbcamp - Day 2&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Ezra&amp;#8217;s Keynote&lt;/h2&gt;

&lt;p&gt;Ezra gave a great speech talking about merb, some of the design decisions that are directing it, but the two most interesting points for me were:&lt;/p&gt;

&lt;h3&gt;Minigems&lt;/h3&gt;

&lt;p&gt;A really useful drop-in replacement for rubygems. Instead of loading the full gem list into RAM (and into every mongrel instance of your app as a result) minigems loads them as required. The reported saving is around 10-20MB of RAM, depending on how many gems you have installed on your system. And using it is simple, instead of:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'rubygems'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you do: &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;begin 
  require 'minigems'
rescue LoadError 
  require 'rubygems'
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thanks to Fabien for all his hard work, go grab it from &lt;a href=&quot;http://github.com/fabien/minigems/tree/master&quot; rel=&quot;nofollow&quot;&gt;his github repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Nanite&lt;/h3&gt;

&lt;p&gt;A &amp;#8220;self-assembling fabric of daemons&amp;#8221; that Ezra has written. It&amp;#8217;s based on RabbitMQ, and essentially you create agents and mappers. Agents do the work, mappers keep track of who does what. And to keep running with what is written on the tin, agents are transient, persistent, and transactional.&lt;/p&gt;

&lt;p&gt;Essentially the agents ping the mappers on a regular basis with information on who they are, what they can do, and their current/average load. If the mapper doesn&amp;#8217;t hear from the agent within the timeout period, it&amp;#8217;s removed from the pool of workers. When new work comes in and is passed to the mapper, it can decide who to pass the work to based on any arbitrary rules. It can go to the agent with the lowest load, it can be broadcast to all agents, a random one, or any rule you decide. This is awesome if you&amp;#8217;re wanting to push work off into the cloud. Just dial up a new agent, it informs the mapper of who it is and what it can do, and there is zero configuration requirement&amp;#8230; just keep dialing them up as required. Additionally, you can just turn them off and the mapper will handle it gracefully. Ezra is looking to add in support for the merb rack interface so the same can be done for the actual merb process, just dial up merb web servers as nanite agents and scale your site on demand at the click of a button.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/ezmobius/nanite/tree/master/README&quot; rel=&quot;nofollow&quot;&gt;Go check it out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.slideshare.net/ezmobius/merb-nanite-presentation?type=powerpoint&quot; rel=&quot;nofollow&quot;&gt;slides&lt;/a&gt; and a &lt;a href=&quot;http://www.r3sty.com/vidz/keynote-ezra.dump&quot; rel=&quot;nofollow&quot;&gt;video&lt;/a&gt; of the presentation is now also available.&lt;/p&gt;

&lt;h2&gt;Merb plumbing: The router&lt;/h2&gt;

&lt;p&gt;This one ran way too quick for me to take any detailed technical notes on, but suffice to say that the routing in merb is absolutely amazing. Handling both domains and subdomains is a breeze, with code like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;match(:subdomain =&gt; /(.*)/).
to(:account =&gt; &quot;:subdomain[1]&quot;) do
  #application routes here...
end

r.match(%r[^/movies/(\d+)-(\d+)-(\d+)$]).
to(:controller =&gt; &quot;movies&quot;, :movie_id =&gt; &quot;[1][2][3]&quot;, :action =&gt; &quot;show&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, you can do pattern matching within the route definition, and then use the captures as parameters. You can also add in requirements on the parameters much like rails:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;match(&quot;/artices(/:year)&quot;, :year =&gt; &quot;[\d]*&quot;).&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or specify a route that has optional components:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;match(&quot;/artices(/:year(/:month(/:day)))/:title&quot;).&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It may be too subtle to notice here so I&amp;#8217;ll point it out; unlike rails the optional parts of the route don&amp;#8217;t have to be at the end. For this rule to be met, the requested path must start with &lt;em&gt;/artcies&lt;/em&gt; and have a &lt;em&gt;:title&lt;/em&gt; at the end, &lt;em&gt;:year&lt;/em&gt;, &lt;em&gt;:month&lt;/em&gt;, and &lt;em&gt;:day&lt;/em&gt; are all optional.&lt;/p&gt;

&lt;p&gt;Particularly impressive was Yehuda mentioning in the Q&amp;amp;A session how routes can initiate DB calls, and then pass the found objects directly into the controller. One call for matching the route, and then re-using the same object in the controller. Nifty!! Some more detailed usage examples have been put up in &lt;a href=&quot;http://pastie.textmate.org/92610&quot; rel=&quot;nofollow&quot;&gt;this pastie&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Merb Slices&lt;/h2&gt;

&lt;p&gt;They&amp;#8217;re kinda like engines in rails, without as much voodoo because of the way merb has opened up the necessary hooks to support them natively within core. Install commonly used pieces of functionality in your apps as a slice, and away you go&lt;/p&gt;

&lt;h3&gt;What if you want to customize?&lt;/h3&gt;

&lt;p&gt;You have a few options, and it depends on what it is you want to customize but your options essentially are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;monkey patch it (using overrides)&lt;/li&gt;
&lt;li&gt;use the &amp;#8220;patch&amp;#8221; rake task&lt;/li&gt;
&lt;li&gt;update settings within the config hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On that last one, each merb slice has it&amp;#8217;s own configuration has available at&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Merb::Slices::config[:blog_slice]&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Over-riding behaviour&lt;/h3&gt;

&lt;p&gt;Much like engines, you can use slices to create custom controller actions, custom models, or custom views. What happens if you don&amp;#8217;t like the way the behaviour in the slice works? Well go change it. If you want to natively support an action or format that the slice didn&amp;#8217;t come with, just go create the template. Your own monkey-patches exist in the &lt;em&gt;/slices&lt;/em&gt; directory within your app. Just add in the new models, views, controllers definitions, etc. They&amp;#8217;ll take precedence over any conflicting definitions within the slice.&lt;/p&gt;

&lt;h3&gt;Initializer&lt;/h3&gt;

&lt;p&gt;When a slice initializes, it gets quite a number of hooks available to determine what it should load and add in its own behaviour. The main load points are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declaring dependencies/boot loader&lt;/li&gt;
&lt;li&gt;Defining routes&lt;/li&gt;
&lt;li&gt;Event hooks (initializing engine, engine loaded, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Handling URLs&lt;/h3&gt;

&lt;p&gt;The URL helper method is handled by slice_url for your slices, so you use it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;slice_url(:controller =&gt; ...., :action =&gt; ...)
slice_url(:merb_auth_slice_password, :login)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The latter would give you the URL to the login route, as defined within the merb_auth slice&lt;/p&gt;

&lt;h3&gt;Being a good citizen&lt;/h3&gt;

&lt;p&gt;A few other points to keep in mind, you should namespace everything to prevent conflicts with the actual application that is including your slice. This includes models. You just namespace models like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MySlice::Post
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, package up any assets you depend on. The end-user can include them in their app with a rake task:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rake slices:myslice:copy_assets&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now the assets will be available in &lt;em&gt;/myslice/images/&amp;#8230;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/hassox/merb-camp-talks/tree/master&quot; rel=&quot;nofollow&quot;&gt;download the presentation here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Yehuda&amp;#8217;s Testing Philosophy&lt;/h2&gt;

&lt;p&gt;Basically the gist of this talk was that TDD (at least how most people do it) is useless as a means of regression testing. If you&amp;#8217;ve have to go back and change tests because you&amp;#8217;ve changed code then you no longer have any proof that your code still works. There is no existence of a test that tests your original intention. That being said, TDD is still good and Yehuda still uses it for development, but his approach is somewhat different.&lt;/p&gt;

&lt;p&gt;Yehuda&amp;#8217;s approach to testing rests on 3 fundamental principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you have broken application something should fail&lt;/li&gt;
&lt;li&gt;If you have a working application all tests should pass&lt;/li&gt;
&lt;li&gt;Test what you care about &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The latter point needs some clarification to prevent the &amp;#8220;Well, duh!&amp;#8221; response. You don&amp;#8217;t care about which methods are called, you care about the end result. Do you really care that you&amp;#8217;ve called &lt;em&gt;find&lt;/em&gt; on your model? Or that the output you&amp;#8217;re expecting has been displayed as intended to the end user?&lt;/p&gt;

&lt;p&gt;If you change views, helpers, etc. then usually tests fail because you&amp;#8217;ve changed code. The tests are incorrectly claiming that things are broken, but they&amp;#8217;re not. The site still works. Refactor tests into such a way that they don&amp;#8217;t break so easily, and you still have proof that everything still works.&lt;/p&gt;

&lt;p&gt;One point that came up in the Q&amp;amp;A: He thinks you should never mock your own code. If you&amp;#8217;ve got your own code, just test directly against it. Mocks should be used for web services or a 3rd party API. 3rd party providers should provide a mock framework for testing against.&lt;/p&gt;

&lt;p&gt;All very interesting, and I need to give it some more thought. I can see the underlying benefits from the number of times a minor change has taken a few hours to implement because of the impact on testing, not because of the complexity of the change. I do wonder what impact it has on tests also serving as documentation of your implementation though.&lt;/p&gt;

&lt;h2&gt;MerbAuth: Darwinian authentication&lt;/h2&gt;

&lt;p&gt;MerbAuto was originally the first plugin with multi-ORM support, and was a direct port of Restful Authentication from rails but it was awfully complex. Then slices came along, and merb-auth was born.&lt;/p&gt;

&lt;h3&gt;Authenticating the session&lt;/h3&gt;

&lt;p&gt;In the interest of reducing some of this complexity, merb-auth was re-written with a pretty major implementation change. Don&amp;#8217;t authenticate controller, we don&amp;#8217;t really care about it. Authenticate the session. It&amp;#8217;s the at the session level that we can determine who a user is, not on an individual controller. Thankfully, merb routing makes session available within the router. Not only does that mean that we can authenticate the session, but we can do it in the routing!!&lt;/p&gt;

&lt;h3&gt;Design Benefits&lt;/h3&gt;

&lt;p&gt;Merb routing sets response codes correctly from raises, so rather than a 302 redirect on failure you can raise an unauthorized response. Authentication is not user management, and your underlying user requirements could be vast so this is just an authentication framework and you&amp;#8217;re left to implement user admin/creation yourself. And it&amp;#8217;s just that, a framework and not a plugin. It allows you to build your own authentication for your application. &lt;/p&gt;

&lt;h3&gt;Implementation options&lt;/h3&gt;

&lt;p&gt;merb-auth includes a password slice which allows you to have both form  base authentication or regular HTTPbasic authentication. It also offers you two different ways to protect your application; either in the router or within a controller. To protect at the router level you just do the following&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protect do
  resources :admin
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in a controller:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;before :ensure_authenticated&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Why protect within a route?&lt;/h3&gt;

&lt;p&gt;The main benefit is that it is earlier in the request/response cycle, and so processing can stop right in the dispatcher and send the response straight back to rack. Within a controller you&amp;#8217;ll need to create a controller instance, possibly run some filters, etc.&lt;/p&gt;

&lt;h3&gt;Authentication strategies&lt;/h3&gt;

&lt;p&gt;A stratergy contains logic for authentication. You need to implement a run method, and then within it any logic you feel pertinent to authenticating a user. You can also declare many different strategies for various login types, say one for teachers and one for students.&lt;/p&gt;

&lt;p&gt;More details and actual code implementations are included &lt;a href=&quot;http://github.com/hassox/merb-camp-talks/tree/master&quot;&gt;in the presentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Damage control: A primer on Merb&lt;/h2&gt;

&lt;p&gt;This is an intro to merb and how to get everything installed and get up and running quickly. The usual things on how merb isn&amp;#8217;t opinionated and is very modular. If you want to get straight into it though, you can get opinionated and get a setup with the following franmeworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;helpers&lt;/li&gt;
&lt;li&gt;datamapper&lt;/li&gt;
&lt;li&gt;rspec&lt;/li&gt;
&lt;li&gt;merb-auth&lt;/li&gt;
&lt;li&gt;sqlite3&lt;/li&gt;
&lt;li&gt;jquery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get up and running quickly these days Yehuda has written a new gem called &lt;a href=&quot;http://smuby.org/articles/2008/07/rake_and_sake_thor.html&quot;&gt;thor&lt;/a&gt;. It&amp;#8217;s basically a cross between rake and sake, except that you can write the tasks in syntax that looks more like ruby as opposed to it&amp;#8217;s own custom DSL. Once you&amp;#8217;ve installed thor, you need the merb tasks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem install thor
thor install http://merbivore.com/merb.thor&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and now to install merb and it&amp;#8217;s dependencies you use thor&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thor merb:edge --install&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a useful piece of advice for those that like to drink the kool-aid a little too much, if you&amp;#8217;ve already got a perfectly good working app in rails there is really no point porting it to merb.&lt;/p&gt;

&lt;h2&gt;Keep a hot cache with merb-cache&lt;/h2&gt;

&lt;p&gt;The video stream died at this point so I&amp;#8217;ve nothing to talk about, I&amp;#8217;ll come back and update it retrospectively once I&amp;#8217;ve caught up. The same goes for the following topics. If anybody can kindly fill me in in the interim while I try and track down some streams&amp;#8230;&lt;/p&gt;

&lt;h2&gt;Using multiple databases in Merb: with special guest CouchDB&lt;/h2&gt;

&lt;h2&gt;DataMapper: the Ruby ORM that kicks butt and takes names&lt;/h2&gt;

&lt;h2&gt;Merb and Sequel&lt;/h2&gt;

&lt;h2&gt;jQuery on Merb&lt;/h2&gt;

&lt;p&gt;Yay! Someone publically pointing out why using the built in rails ajax/javascript helpers is generally a bad idea. Especially remote&lt;em&gt;form&lt;/em&gt;for. Javascript is part of the web stack, and you&amp;#8217;ll eventually get to a point where you actually need to know how to program in it so hiding behind the rails helpers can only help you for so long. Plus all the nasty violations you get re separating presentation from logic.&lt;/p&gt;

&lt;h3&gt;Testing with Javascript&lt;/h3&gt;

&lt;p&gt;For testing javascript there is ScrewUnit (check out &lt;a href=&quot;http://pivots.pivotallabs.com/users/nick/blog/articles/455-better-javascript-testing-through-screwunit&quot; rel=&quot;nofollow&quot;&gt;this post&lt;/a&gt; for more detail) 
which is a javascript port of rspec with before, after, and describe blocks. There is also a mocking framework for handling XHR so you can appropriately test your ajax requests.&lt;/p&gt;

&lt;p&gt;Testing with selenium is good for the full coverage and acceptance testing that a person would normally be doing. It can be a difficult to test everything you care about though.&lt;/p&gt;

&lt;h3&gt;Why can we use ruby to generate HTML and SQL, but not Javascript?&lt;/h3&gt;

&lt;p&gt;SQL is a mismatch for what we&amp;#8217;re trying to do, has&lt;em&gt;many, belongs&lt;/em&gt;to, and all the various helpers represent logic which isn&amp;#8217;t well defined in the SQL layer. And HAML is only a very very thin abstraction layer from HTML. Javascript is an entire language though, which isn&amp;#8217;t running on our environment it&amp;#8217;s running on the client PC and has it&amp;#8217;s own state. Most Javascript code generators don&amp;#8217;t work that well, and the point at which you need to actually know the language is hit much earlier in the development of a project than it is for something like SQL. That being said, it&amp;#8217;s still useful to have someone who actually knows SQL on your team.&lt;/p&gt;</description>
          <pubDate>Sat, 11 Oct 2008 18:21:14 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/10/11/merbcamp---notes-from-the-edge/</guid>
          <link>http://rubypond.com/articles/2008/10/11/merbcamp---notes-from-the-edge/</link>
        </item>
    
        <item>
          <title>DataMapper Migrations</title>
          <description>&lt;p&gt;I&amp;#8217;ve been working on some merb related things of late, and I&amp;#8217;m planning on writing a more detailed article on creating a merb application from scratch as so many of the tutorials out there kind of leave you hanging. In the interim though, I&amp;#8217;m just going to touch on a little nugget of information that isn&amp;#8217;t very well publicised regarding DataMapper, one of the ORMs that gets used with merb.&lt;/p&gt;

&lt;h2&gt;ActiveRecord Style Migrations with DataMapper&lt;/h2&gt;

&lt;p&gt;That&amp;#8217;s right, you aren&amp;#8217;t left having to wrestle with the command line and &lt;em&gt;ALTER TABLE&lt;/em&gt; statements just because you&amp;#8217;ve left ActiveRecord behind. All the migration joy you&amp;#8217;ve come to love with ruby on rails can come and live with you happily with merb and DataMapper.&lt;/p&gt;

&lt;p&gt;First things first, you&amp;#8217;ll want to generate a new migration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;merb-gen migration my_migration&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We should now have a file named &lt;em&gt;001_my_migration.rb&lt;/em&gt; and if we look at it, it won&amp;#8217;t be too foreign based on our ActiveRecord experiences:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;migration 2, :my_migration do
  up do
  end

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

&lt;p&gt;To pad it out with some code that is actually useful, add in the definitions for what you want done:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;migration 2, :my_migration do
  up do
    create_table(:posts) do
      column(:id, Integer, :serial =&gt; true)
      column(:title, String, :size =&gt; 255)
      column(:description, Text)
      column(:published, Boolean)
      column(:created_at, DateTime)
      column(:updated_at, DateTime)
    end
  end

  down do
    drop_table(:posts)
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Running the DataMapper Migration&lt;/h2&gt;

&lt;p&gt;And now that we&amp;#8217;ve got the migration we are happy with, applying it to our underlying database is just a matter of the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rake dm:db:migrate&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Sun, 05 Oct 2008 21:20:20 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/10/05/datamapper-migrations/</guid>
          <link>http://rubypond.com/articles/2008/10/05/datamapper-migrations/</link>
        </item>
    
        <item>
          <title>Introducing Map.ly, collaborative mapping</title>
          <description>&lt;p&gt;From the necessity is the mother of all invention category, I introduce a new product I've hastily cobbled together over the past week or so. Map.ly is a means of 'sharing directions, locations, and maps' with other people.&lt;/p&gt;


&lt;p&gt;It is still very much in development, I'm loathe to call it beta as it's probably closer to alpha but still; So what is it's purpose? My girlfriend is forever having to plan meetings and trips for the people in her team, and trying to herd these sheep &lt;strong&gt;ahem&lt;/strong&gt; I meant orientate her colleagues in foreign cities can be tricky. She needed something to accompany their printed itinerary showing all the various locations they'd need to be during their stay, and where they were in relation to each other. And print out a google map for each location seemed needlessly difficult and not that helpful, we wanted to plot everything on the one map if possible.&lt;/p&gt;


&lt;p&gt;Enter Map.ly. Double click where you want to place a marker, enter in the name and some details, and save. You'll get a nice short URL back to the map that you can pass around and you can all add your own markers to it. I think support in IE might currently be a little bit flaky, I'll check later today. And there are a number of features still in the pipeline (getting directions between points, entering in addresses, etc.) but I'm hoping it will prove to be something useful. So go &lt;a href=&quot;http://map.ly/&quot;&gt;give someone some directions to somewhere&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;And most useful to the geeks out there, is that it's forced me to resurrect a long since dead gem I once wrote for mapping as I felt YM4R and the other Map API gems just weren't ruby enough. Once the feature set is locked in, I'll release an updated version allowing you to do all the cool things that get implemented on Map.ly.&lt;/p&gt;
</description>
          <pubDate>Tue, 12 Aug 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/08/12/introducing-map-ly-collaborative-mapping/</guid>
          <link>http://rubypond.com/articles/2008/08/12/introducing-map-ly-collaborative-mapping/</link>
        </item>
    
        <item>
          <title>Nginx Intermediary SSL Certificates and Passphrases</title>
          <description>&lt;p&gt;I've had to do this 3 or 4 times in the past 12 months, and each time I waste a good chunk of time trying to re-discover how to do it. So this post is as much for my own documentation sake as it is sharing the love. If you've ever bought an SSL certificate from GoDaddy or a similar provider that provides and intermediary certificate to include, you might have run into a bit of a problem trying to work out how to include it in your nginx config. Well it's actually pretty straight-forward, provided you remember the steps.&lt;/p&gt;


&lt;h2&gt;Merging the site and intermediary SSL certificates&lt;/h2&gt;


&lt;p&gt;First thing you'll need to do is create a new certificate, which is just the one for your site and the intermediary merged together. In Apache you'd specify them both individually. Nginx only allows you to specify one, so lets put them in the same file:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;
cat rubypond.com.crt &gt;&gt; rubypond.com.crt.merged
cat intermediate_bundle.crt &gt;&gt; rubypond.com.crt.merged
&lt;/code&gt;
&lt;/pre&gt;

&lt;h2&gt;Removing SSL Passphrase&lt;/h2&gt;


&lt;p&gt;The next step, is to remove the passphrase off the key for the site. I'd love to keep it on, but it means nginx can't be restarted without an operator at the console to enter in the passphrase every time which is definitely less than ideal. So to remove the passphrase from your key, I'll first back it up and then take it off with openssl:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;
mv rubypond.key rubypond.key.passphrased
openssl rsa -in rubypond.key.passphrased -out rubypond.key
&lt;/code&gt;
&lt;/pre&gt;

&lt;h2&gt;Configuring Nginx to use your new SSL certificate&lt;/h2&gt;


&lt;p&gt;This config is taken straight from my earlier article on &lt;a href=&quot;http://rubypond.com/articles/2008/02/01/setting-up-nginx-ssl-and-virtual-hosts/&quot;&gt;setting up nginx, ssl, and virtual hosts&lt;/a&gt;, but I'll include it here just for good measure too:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;
server {
  listen 443;
  server_name myserver.com;  

  ssl on;
  ssl_certificate /etc/nginx/certs/rubypond.com.crt.merged; 
  ssl_certificate_key /etc/nginx/certs/rubypond.key; 

  # put the rest of your server configuration here.

  location / {
     proxy_set_header X-FORWARDED_PROTO https;

     # put your config here
  }
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Just be sure to point the certificate entry to the new merged certificate, the key at the now un-passphrased key, and restart nginx. Done.&lt;/p&gt;
</description>
          <pubDate>Mon, 11 Aug 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/08/11/nginx-intermediary-ssl-certificates-and-passphrases/</guid>
          <link>http://rubypond.com/articles/2008/08/11/nginx-intermediary-ssl-certificates-and-passphrases/</link>
        </item>
    
        <item>
          <title>The complete guide to setting up Starling</title>
          <description>&lt;p&gt;We wanted to push some long running tasks off to the background so that we didn't tie up a mongrel needlessly. I've wrestled (and won!) with backgroundrb in the past, but it just seemed like a chore. And they've since changed the API enough to mean it would be back to the drawing board, so we may as well assess some of the other options. So without too much further ado, the complete guide to installing, using, and monitoring starling.&lt;/p&gt;


&lt;p&gt;For those that haven't heard &lt;a href=&quot;http://rubyforge.org/projects/starling/&quot; rel=&quot;nofollow&quot;&gt;Starling&lt;/a&gt; is the back-end queuing system that Twitter use. And despite the stability issues Twitter have, if initial impressions are anything to go by I don't think Starling is the reason. It's fairly light, sits on top of MemCache, and is very quick. The initial lure to Starling though was via the Workling plug-in. We could get a prototype out the door using just the Spawn workling, and then when a queue became important switch over.&lt;/p&gt;


&lt;h2&gt;Installing Workling&lt;/h2&gt;


&lt;p&gt;We're going to take the same approach I did, and get a prototype background process happening with Spawn first. So let's install Workling and Spawn:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
script/plugin install http://svn.playtype.net/plugins/workling/
script/plugin install http://spawn.rubyforge.org/svn/spawn/
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Now in your environment (environment.rb? an initializer? you decide) add the following:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
Workling::Remote.dispatcher = Workling::Remote::Runners::SpawnRunner.new
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Done!&lt;/p&gt;


&lt;h2&gt;Creating A Workling Background Worker&lt;/h2&gt;


&lt;p&gt;Now it's time to create a worker, basically to define what it is exactly that should be executed in the background. For the same of illustration, I'm just going to loop and create some records. I create the follow &lt;em&gt;app/workers/example_worker.rb&lt;/em&gt; file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class ExampleWorker &lt; Workling::Base

  def create_new_records
    1000.times do
      Item.create :some_name =&gt; options[:some_name]
    end
  end 

end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Calling Your New Workling Background Worker&lt;/h2&gt;


&lt;p&gt;Now in whichever controller would normally need to start this task, you can place a call to the workling worker:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ExampleWorker.async_create_new_records(:some_name =&gt; &quot;This Person&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Workling will create a new method for us to call, by prefixing out method name with &lt;em&gt;async_&lt;/em&gt; to allow us to call it asynchronously. Pass in a hash of values you want to use into the method, workling will add a key named &lt;em&gt;:uid&lt;/em&gt; containing the unique identifier assigned to this task.&lt;/p&gt;

&lt;p&gt;And now we're done here too! This will use Spawn to fork the job, take it out of the mongrel process, and let your rails stack continue and not hold up your other users.&lt;/p&gt;

&lt;h2&gt;Installing Starling&lt;/h2&gt;

&lt;p&gt;Install Starling by grabbing the gem and the MemCache Client (which strangely has a dependency on ZenTest which I need to investigated):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install memcache-client starling&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the dependencies are installed, we need to start up the required services. You're going to need the Starling daemon running, as well as the workling client. I'd rather not have Starling run as root so first I create a user, and then give it somewhere to create it's pid and spool files (you can probably skip this and run as root on your local dev box):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo /usr/sbin/adduser -s /sbin/nologin starling
sudo mkdir -p /var/spool/starling
sudo mkdir -p /var/run/starling
sudo chown starling:starling /var/spool/starling
sudo chown starling:starling /var/run/starling&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now time to start up the services:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo -u starling starling -P /var/run/starling/starling.pid -d
script/workling_starling_client start&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A note of particular importance here. The workling_starling_client will run in whatever environment &lt;strong&gt;RAILS_ENV&lt;/strong&gt; is set to, and is not passed in via a command line option. It also does some fruity things with loading up your workers at run time, so if you're running development and test on the one box you'll need to stop the workling client and restart it each time you want to change environments (or best yet, set your rake:spec/rake:test task to do it for you).&lt;/p&gt;

&lt;h2&gt;Switching Over To Starling For Background Processing&lt;/h2&gt;

&lt;p&gt;Switching between background processing systems is pretty simple, we just update the environment setting we made earlier to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Workling::Remote.dispatcher = Workling::Remote::Runners::StarlingRunner.new&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's it, business as usual!&lt;/p&gt;

&lt;h2&gt;Monitoring the sucker&lt;/h2&gt;

&lt;p&gt;It is all fine and dandy having it up and running now, but it'd be nice to keep it that way. That's where god comes in and some tomfoolery with our &lt;em&gt;app.god&lt;/em&gt; config. If you've not already done so, I suggest you read my previous article on &lt;a href=&quot;http://rubypond.com/articles/2008/04/07/rails-god-config/&quot;&gt;monitoring rails with god&lt;/a&gt; which talks about creating a generic config file in your rails app so you don't need to manage god configs for each instance.&lt;/p&gt;

&lt;p&gt;I'm going to change the example &lt;em&gt;app.god&lt;/em&gt; in that article to look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Rubypond
  attr_reader :ports, :server_names, :workling_client

  def initialize
    @ports = [5000, 5001]
    @server_names = &quot;www.rubypond.com rubypond.com&quot; 
    @workling_client = true
  end
end

@apps &lt;&lt; Rubypond.new&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And within the &lt;em&gt;god.conf&lt;/em&gt; on the server I'll add the following methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def configure_workling_client(w, rails_root,  app_name)
  w.uid = &quot;mongrel&quot; 
  w.gid = &quot;webserver&quot; 
  w.name = &quot;#{app_name}-workling&quot; 
  w.group = &quot;#{app_name}&quot; 
  w.interval = 30.seconds
  w.start = &quot;RAILS_ENV=production #{rails_root}/script/workling_starling_client start&quot; 
  w.stop = &quot;#{rails_root}/script/workling_starling_client stop&quot; 
  w.restart = &quot;#{rails_root}/script/workling_starling_client restart&quot; 
  w.pid_file = &quot;#{rails_root}/log/workling.pid&quot; 

  w.behavior(:clean_pid_file)
end

def monitor_app(w)
  start_if_not_running(w)
  restart_if_resource_hog(w)
  monitor_lifecycle(w)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Okay, so &lt;em&gt;monitor_app&lt;/em&gt; is actually just renaming &lt;em&gt;monitor_rails_app&lt;/em&gt; to be more generic. Make sure you change references everywhere though. Elsewhere in the &lt;em&gt;god.conf&lt;/em&gt; file we had a block similar to the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@apps.each do |app|
  app_name = app.class.name.downcase
  rails_root = &quot;/var/www/apps/#{app_name}/current&quot; 

  app.ports.each do |port|
    God.watch do |w|
      configure_mongrel(w, rails_root, app_name, port)
      monitor_rails_app(w)
    end
  end

  God.watch do |w|
    configure_workling_client(w, rails_root, app_name)
    monitor_app(w)
  end if app.respond_to? :workling_client
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last &lt;em&gt;God.watch&lt;/em&gt; there is where the magic happens. It will look at the app we've defined in &lt;em&gt;app.god&lt;/em&gt;, and if we've provided an attribute called :workling_client then it will automatically monitor a workling client for this app. We're not quite done yet though. We also need Starling to be running, but that's not on a per app basis we just have one for the server. So I'm just going to insert this directly into &lt;em&gt;god.conf&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;God.watch do |w|
  w.name = &quot;starling&quot; 
  w.group = &quot;starlings&quot; 
  w.uid = &quot;starling&quot; 
  w.gid = &quot;starling&quot; 
  w.interval = 30.seconds # default
  w.start = &quot;/usr/bin/starling -P /var/run/starling/starling.pid -d&quot; 
  w.start_grace = 20.seconds
  w.restart_grace = 20.seconds
  w.pid_file = &quot;/var/run/starling/starling.pid&quot; 
  w.behavior(:clean_pid_file)

  monitor_app(w)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now restart god to take the new config, deploy you changes to your rails app, and cross your fingers ;)&lt;/p&gt;

</description>
          <pubDate>Thu, 17 Jul 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/07/17/the-complete-guide-to-setting-up-starling/</guid>
          <link>http://rubypond.com/articles/2008/07/17/the-complete-guide-to-setting-up-starling/</link>
        </item>
    
        <item>
          <title>Sexy Forms in Rails</title>
          <description>&lt;p&gt;I've been meaning to release this for quite a while now, I've finally got around to packaging it up for some form of public consumption. Basically, I got sick of having to manually create label tags for each of my form inputs. They should be there by default so that users with visual or other impairments have enough additional information to use the site. I'm also lazy, and would have a tendency to forget to put them in otherwise. I also wanted a consistent way to display any additional contextual information, so here it is.&lt;/p&gt;

&lt;p&gt;I'll go through the code in detail here, but I'll keep it updated with any changes and available for download at the &lt;a href=&quot;http://github.com/rubypond/semantic_form_builder/tree&quot; rel=&quot;nofollow&quot;&gt;semantic form builder git repo&lt;/a&gt;. So now on to the code.&lt;/p&gt;

&lt;p&gt;It started with a custom FormBuilder.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class SemanticFormBuilder &amp;lt; ActionView::Helpers::FormBuilder
  include SemanticFormHelper

  def field_settings(method, options = {}, tag_value = nil)
    field_name = &quot;#{@object_name}_#{method.to_s}&quot; 
    default_label = tag_value.nil? ? &quot;#{method.to_s.gsub(/\_/, &quot; &quot;)}&quot; : &quot;#{tag_value.to_s.gsub(/\_/, &quot; &quot;)}&quot; 
    label = options[:label] ? options.delete(:label) : default_label
    options[:class] ||= &quot;&quot; 
    options[:class] += options[:required] ? &quot; required&quot; : &quot;&quot; 
    label += &quot;&amp;lt;strong&gt;&amp;lt;sup&gt;*&amp;lt;/sup&gt;&amp;lt;/strong&gt;&quot; if options[:required]
    [field_name, label, options]
  end

  def text_field(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;text&quot;, field_name, label, super, options)
  end

  def file_field(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;file&quot;, field_name, label, super, options)
  end

  def datetime_select(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;datetime&quot;, field_name, label, super, options)
  end

  def date_select(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;date&quot;, field_name, label, super, options)
  end

  def radio_button(method, tag_value, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;radio&quot;, field_name, label, super, options)
  end

  def check_box(method, options = {}, checked_value = &quot;1&quot;, unchecked_value = &quot;0&quot;)
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;check-box&quot;, field_name, label, super, options)
  end

  def select(method, choices, options = {}, html_options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;select&quot;, field_name, label, super, options)
  end

  def time_zone_select(method, choices, options = {}, html_options = {})
    field_name, label, options = field_settings(method, options)
    # wrapping(&quot;time-zone-select&quot;, field_name, label, super, options)
    select_box = this_check_box = @template.select(@object_name, method, choices, options.merge(:object =&gt; @object), html_options)
    wrapping(&quot;time-zone-select&quot;, field_name, label, select_box, options)    
  end

  def password_field(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;password&quot;, field_name, label, super, options)
  end

  def text_area(method, options = {})
    field_name, label, options = field_settings(method, options)
    wrapping(&quot;textarea&quot;, field_name, label, super, options)
  end

  def submit(method, options = {})
    field_name, label, options = field_settings(method, options.merge( :label =&gt; &quot;&amp;amp;nbsp;&quot;))
    wrapping(&quot;submit&quot;, field_name, label, super, options)
  end

  def submit_and_cancel(submit_name, cancel_name, options = {})
    submit_button = @template.submit_tag(submit_name, options)
    cancel_button = @template.submit_tag(cancel_name, options)
    wrapping(&quot;submit&quot;, nil, &quot;&quot;, submit_button+cancel_button, options)
  end

  def radio_button_group(method, values, options = {})
    selections = []
    values.each do |value|
      if value.is_a?(Hash)
        tag_value = value[:value]
        label = value[:label]
        help = value.delete(:help)
      else
        tag_value = value
        value_text = value
      end
      radio_button = @template.radio_button(@object_name, method, tag_value, options.merge(:object =&gt; @object, :help =&gt; help))
      selections &amp;lt;&amp;lt; boolean_field_wrapper(
                        radio_button, &quot;#{@object_name}_#{method.to_s}&quot;,
                        tag_value, value_text)
    end
    selections    
    field_name, label, options = field_settings(method, options)
    semantic_group(&quot;radio&quot;, field_name, label, selections, options)    
  end

  def check_box_group(method, values, options = {})
    selections = []
    values.each do |value|
      if value.is_a?(Hash)
        checked_value = value[:checked_value]
        unchecked_value = value[:unchecked_value]
        value_text = value[:label]
        help = value.delete(:help)
      else
        checked_value = 1
        unchecked_value = 0
        value_text = value
      end
      check_box = @template.check_box(@object_name, method, options.merge(:object =&gt; @object), checked_value, unchecked_value)
      selections &amp;lt;&amp;lt; boolean_field_wrapper(
                        check_box, &quot;#{@object_name}_#{method.to_s}&quot;,
                        checked_value, value_text)
    end
    field_name, label, options = field_settings(method, options)
    semantic_group(&quot;check-box&quot;, field_name, label, selections, options)    
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Personally I think they are a terribly underused aspect of the Rails framework. Anyway, stepping through what we've got here. We inherit from &lt;em&gt;ActionView::Helpers::FormBuilder&lt;/em&gt; and then begin overriding the various tags that will be called within a &lt;em&gt;form_for&lt;/em&gt;. All we do for most methods is call &lt;em&gt;field_settings&lt;/em&gt; followed by &lt;em&gt;wrapping&lt;/em&gt;. In the method &lt;em&gt;field_settings&lt;/em&gt; we set the name of the field to the standard rails convention like person_first_name (&lt;em&gt;@object&lt;/em&gt; is created for us automatically by &lt;em&gt;form_for&lt;/em&gt; so we don't need to worry about it here). Next we set the label text to display for this form input, it will default to something sensible (generally the name of the field you are generating the input for) or you can override it per input by passing &lt;em&gt;:label&lt;/em&gt; in as an option. And finally, we check if you have passed &lt;em&gt;:required =&gt; true&lt;/em&gt; in and if so we set a required class so we can style it differently. All the relevant info gets returned, so we can pass it into the &lt;em&gt;wrapping&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;So where exactly is wrapping? I've moved it out into a helper, as I wanted to use this functionality in regular &lt;em&gt;form_tag&lt;/em&gt; calls as well as &lt;em&gt;form_for&lt;/em&gt;. So take a look in &lt;em&gt;semantic_form_helper&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module SemanticFormHelper

  def wrapping(type, field_name, label, field, options = {})
    help = %Q{&amp;lt;span class=&quot;help&quot;&gt;#{options[:help]}&amp;lt;/span&gt;} if options[:help]
    to_return = []
    to_return &amp;lt;&amp;lt; %Q{ &amp;lt;div class=&quot;#{type}-field #{options[:class]}&quot;&gt;}
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;label for=&quot;#{field_name}&quot;&gt;#{label}#{help}&amp;lt;/label&gt;} unless [&quot;radio&quot;,&quot;check&quot;, &quot;submit&quot;].include?(type)
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;div class=&quot;input&quot;&gt;}
    to_return &amp;lt;&amp;lt; field
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;label for=&quot;#{field_name}&quot;&gt;#{label}&amp;lt;/label&gt;} if [&quot;radio&quot;,&quot;check&quot;].include?(type)    
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;/div&gt;&amp;lt;/div&gt;}
  end

  def semantic_group(type, field_name, label, fields, options = {})
    help = %Q{&amp;lt;span class=&quot;help&quot;&gt;#{options[:help]}&amp;lt;/span&gt;} if options[:help]
    to_return = []
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;div class=&quot;#{type}-fields #{options[:class]}&quot;&gt;}
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;label for=&quot;#{field_name}&quot;&gt;#{label}#{help}&amp;lt;/label&gt;}
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;div class=&quot;input&quot;&gt;}    
    to_return &amp;lt;&amp;lt; fields.join
    to_return &amp;lt;&amp;lt; %Q{&amp;lt;/div&gt;&amp;lt;/div&gt;}
  end

  def boolean_field_wrapper(input, name, value, text, help = nil)
    field = []
    field &amp;lt;&amp;lt; %Q{&amp;lt;label&gt;#{input} #{text}&amp;lt;/label&gt;}
    field &amp;lt;&amp;lt; %Q{&amp;lt;div class=&quot;help&quot;&gt;#{help}&amp;lt;/div&gt;} if help
    field
  end

  def check_box_tag_group(name, values, options = {})
    selections = []
    values.each do |item|
      if item.is_a?(Hash)
        value = item[:value]
        text = item[:label]
        help = item.delete(:help)
      else
        value = item
        text = item
      end
      box = check_box_tag(name, value)
      selections &amp;lt;&amp;lt; boolean_field_wrapper(box, name, value, text)
    end
    label = options[:label]
    semantic_group(&quot;check-box&quot;, name, label, selections, options)    
  end      

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are 3 cases to look at initially. Wrapping a normal input, wrapping a boolean input (like a check box), and wrapping a group of check boxes. For wrapping a normal input, we create a label on the left and insert the field into a div on the right. I've got the boolean one there for the 'remember me?' type of scenario on a login page, where it looked to make more sense to have the label to the right of the checkbox rather than the left. And finally, wrapping a group of elements which isn't handled at all well in the current Rails setup. Overwhelmed yet? Let's just look at how you use it then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;% form_for @document do |f|
  field_set_tag &quot;Form Details&quot; do %&gt;
    &amp;lt;%= f.date_select :date, :required =&gt; true, :help =&gt; &quot;date the something happened&quot; %&gt;
    &amp;lt;%= f.text_field :number, :required =&gt; true, :help =&gt; &quot;the reference number for this thing&quot; %&gt;
    &amp;lt;%= f.select :external_id, [[&quot;Choose an option...&quot;,&quot;&quot;]] + @externals.map{|c| [c.name, c.id]}, :required =&gt; true, :label =&gt; &quot;options&quot;, :help =&gt; &quot;select something from the list&quot; %&gt;
    &amp;lt;%= check_box_tag_group &quot;document[other_items][]&quot;, @others.map{|u| { :value =&gt; u.id, :label =&gt; u.description }}, :label =&gt; &quot;including these?&quot;, :help =&gt; &quot;tick the whatever boxes are appropriate for this&amp;amp;nbsp;thing&quot; %&gt;
    &amp;lt;%= f.text_field :name, :help =&gt; &quot;what was Willis talkin' about?&quot; %&gt;
    &amp;lt;%= f.check_box :list, :label =&gt; &quot;mailing list&quot;, :help =&gt; &quot;can we send you a bunch of spam?&quot; %&gt;
    &amp;lt;%= f.submit_and_cancel(&quot;save&quot;, &quot;cancel&quot;) %&gt;
&amp;lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You'll see we can pass in &lt;em&gt;:required =&gt; true&lt;/em&gt; to visually identify required fields to the user. If we don't like the form name (like the generic &lt;strong&gt;'list'&lt;/strong&gt; attribute, then we can override with &lt;em&gt;:label =&gt;&lt;/em&gt;. And if there is additional contextual help to provide, we've got &lt;em&gt;:help =&gt;&lt;/em&gt;. We've also got a pretty way of showing a selection of check boxes with &lt;em&gt;check_box_tag_group&lt;/em&gt;, but you'll have to specify the field name yourself. I've also put a convenience method in called &lt;em&gt;submit_and_cancel&lt;/em&gt; that takes the text for a submit, and cancel button respectively. Catching the cancel action is up to you though.&lt;/p&gt;

&lt;a href=&quot;http://s3.amazonaws.com:/rubypond/page_attachments/214/sexy-forms-in-rails.png&quot; rel=&quot;nofollow&quot;&gt; &lt;img src=&quot;http://s3.amazonaws.com:/rubypond/page_attachments/214/sexy-forms-in-rails_preview.png&quot; size=&quot;preview&quot;&gt;&lt;/a&gt;

&lt;p&gt;And voila! The finished product. Any problems with it, please let me know or fork and fix/pull request on github. I've tested it on Safari 3, Firefox 2/3, and IE7. No idea what it looks like on IE6 just yet.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;UPDATE&lt;/b&gt;: It's now a plugin, &lt;a href=&quot;http://rubypond.com/articles/2008/08/01/pluginized-sexy-forms-in-rails/&quot;&gt;sexy and semantic forms are now available as a plugin&lt;/a&gt;&lt;/p&gt;

</description>
          <pubDate>Wed, 16 Jul 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/07/16/sexy-forms-in-rails/</guid>
          <link>http://rubypond.com/articles/2008/07/16/sexy-forms-in-rails/</link>
        </item>
    
        <item>
          <title>Useful Flash Messages in Rails</title>
          <description>&lt;p&gt;Inevitably somewhere in your rails app you display flash messages to your users to inform them that an action has (or hasn't) taken place. Sometimes they need to provide more info, maybe you've just created some new information for them. Why make them sit around, or wonder where they need to go next when you can take them straight to it in the message itself?&lt;/p&gt;

&lt;p&gt;I've ripped this code out of a project I've been working on and made it a little more generic. Initially I was going to just insert a link in the flash message, but as I was rightly pointed out by my pair and &lt;a href=&quot;http://effectif.com/&quot;&gt;elegant coder extraordinaire&lt;/a&gt;, that would mean I'd be polluting my controller with logic and content that should be handled by the view. How do we solve a problem like pollution?&lt;/p&gt;

&lt;p&gt;First, we updated the controller so that the flash message now looked something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;flash[:error] = &quot;Username and password do not match. If you have 
                   forgotten your password you can %s&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;em&gt;%s&lt;/em&gt; is there to use a string substitution later. If you wanted to insert your link somewhere else, move the &lt;em&gt;%s&lt;/em&gt;. Next, we created a new key in flash to hold our additional information (the link path and text):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;flash[:error_item] = [&quot;reset it&amp;amp;nbsp;here&quot;, forgot_path]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Quite simply, it's an array with the first item being the text and the second the path. Now for handling it within our view, here's what I've got in &lt;strong&gt;application_helper.rb&lt;/strong&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;FLASH_NOTICE_KEYS = [:error, :notice, :warning]

  def flash_messages
    return unless messages = flash.keys.select{|k| FLASH_NOTICE_KEYS.include?(k)}
    formatted_messages = messages.map do |type|      
      content_tag :div, :class =&gt; type.to_s do
        message_for_item(flash[type], flash[&quot;#{type}_item&quot;.to_sym])
      end
    end
    formatted_messages.join
  end

  def message_for_item(message, item = nil)
    if item.is_a?(Array)
      message % link_to(*item)
    else
      message % item
    end
  end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reason for the constant is that I don't use just &lt;em&gt;:error&lt;/em&gt; and &lt;em&gt;:notice&lt;/em&gt;, I've also got &lt;em&gt;:warning&lt;/em&gt; for times when something needs action but not because of something the user has done wrong (I don't want to make them feel bad when they've not had the opportunity to be good!). In flash messages I exit out on the first line if we don't have content to process for the flashes I expect to output (&lt;em&gt;:error&lt;/em&gt;, &lt;em&gt;:notice&lt;/em&gt;, and &lt;em&gt;:warning&lt;/em&gt;) otherwise I loop over each and create a &lt;em&gt;div&lt;/em&gt; to contain the message. The class on the &lt;em&gt;div&lt;/em&gt; will be either &lt;em&gt;error&lt;/em&gt;, &lt;em&gt;notice&lt;/em&gt; or &lt;em&gt;warning&lt;/em&gt; so you can style it properly. We defer working out the content to &lt;em&gt;message_for_item&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;message_for_item&lt;/em&gt; I check if the input is an Array, and if so I use the build in string substitution method to insert the link in the relevant place. As you may notice, I've called splat on &lt;strong&gt;item&lt;/strong&gt; by putting an asterisk in front of it. That means your array can essentially just be the parameters you'd pass in to &lt;strong&gt;link_to&lt;/strong&gt;, allowing you to add additional classes or options if you wish. If it's not an array, I skip the link to and just to the substitution. This will handle traditional flash messages as well as some that might want substitution of a string or other object. Wherever you'd previously inserted your flash messages, now you call:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;%= flash_messages%&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and the end result is something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://s3.amazonaws.com:/rubypond/page_attachments/210/Picture_3.png&quot; rel=&quot;nofollow&quot;&gt; &lt;img src=&quot;http://s3.amazonaws.com:/rubypond/page_attachments/210/Picture_3_preview.png&quot; size=&quot;preview&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;So what else could you do with this? Well we extended it to be a little more intelligent based on the object that was passed in. You could also use it as part of a before filter if you've got flash messages that are relatively similar across actions on controllers. Just put &lt;em&gt;%s&lt;/em&gt; in the bit to substitute, and then at the relevant part of your action you can insert the a string into &lt;em&gt;flash[:error_item]&lt;/em&gt; or the appropriate key, and have it displayed. Like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;before_filter :set_message, :only =&gt; [:create, :update]

  def create
    @order = Order.create!(params[:order])
    flash[:notice_item] = &quot;#{@order.items} items&quot; 
  end

  def update
    @order = Order.find(params[:id])
    @order.update_attributes(params[:order])
    flash[:notice_item] = &quot;#{@order.items} items&quot; 
  end

  private
    def set_message

      flash[:notice] = &quot;Thank you, we have updated your order with %s&quot; 
    end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I hope it helps. Coming up next, my sexy form builder!&lt;/p&gt;</description>
          <pubDate>Fri, 11 Jul 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/07/11/useful-flash-messages-in-rails/</guid>
          <link>http://rubypond.com/articles/2008/07/11/useful-flash-messages-in-rails/</link>
        </item>
    
        <item>
          <title>Make your own IM bot in Ruby, and interface it with your Rails app</title>
          <description>&lt;p&gt;In a super secret project I'm currently working on, I've been looking for ways of making it easier for people to interact with the system without the need to log in to the website. That's included the obvious things like having a RESTful API so they can put their own services and interfaces on top, but that only works for developers or 3rd party application providers. What about your average Joe on the street, how come they get forced into having to log in to the site to update their data, etc.? Why not provide a means of carrying out simple tasks in an application they probably already have? And so an Instant Messaging interface was designed to send a instruction to a robot, and it's relatively simple to get setup.&lt;/p&gt;


&lt;p&gt;The best thing about it is that we help give more control and time back to the user, hopefully making the system more appealing to use. No more breaking your train of thought while you go log into a site to check something, just a quick message to a bot and you can forget about it. Or conversely, you wont defer the task because the overhead in writing a reminder is possibly more than the time it would take to just do it. And for those fans of the Getting Things Done (GTD) approach to task management, it means a whole range of tasks can be suddenly just 'get done' in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Getting_Things_Done#Process&quot; rel=&quot;nofollow&quot;&gt;process phase&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;So how do we give such amazing power and flexibility to our users? First you're going to need to install the &lt;a href=&quot;http://github.com/ln/xmpp4r/tree/master&quot; rel=&quot;nofollow&quot;&gt;xmpp4r gem&lt;/a&gt; which at the time of writing doesn't seem to play nice with the new version of rubygems (I think it's to do with the way new rubygems preserves permissions). The problem appears to be fixed in version 0.3.2.99, but only 0.3.2 is available as a gem. So in the interim, we are going to have to download it directly from the git repository and build it ourselves:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git://github.com/ln/xmpp4r.git xmpp4r
cd xmpp4r
rake gem:install
sudo gem install xmpp4r-simple&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now some ruby code. Connecting is straight-forward:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'rubygems'  
require 'xmpp4r-simple'
messenger = Jabber::Simple.new('my-bot@gmail.com', &quot;bot-password&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As is sending a message:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;messenger.deliver(&quot;a-real-person@gmail.com&quot;, &quot;Why hello there Mr. Person, your bot is here now!&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you wish to have your service sit around and respond to messages, then something you'll need something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;while true
  messenger.received_messages do |msg|  
    puts msg.body  
    messenger.deliver(&quot;a-real-person@gmail.com&quot;, &quot;Got your message, thanks!&quot;)  
  end  
  sleep 2  
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now just to point out for those that aren't paying close attention, the above code does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a loop that we will continually go over&lt;/li&gt;
&lt;li&gt;Call &lt;strong&gt;received_messages&lt;/strong&gt; and pass any messages into a block, iterating over each one at a time&lt;/li&gt;
&lt;li&gt;Stop processing for 2 seconds so the system can take a break and we don't use up all of the resources&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Of particular importance once again, I've created an infinite loop here to listen to incoming messages. &lt;b&gt;DO NOT put this code in a rails app&lt;/b&gt;, this is the kind of process that needs to be handled outside of rails as a supporting but background task. If you try and kick it off via rails it will process indefinitely and tie up one of your mongrel instances until it dies and likely degrade the performance of your site in the process.&lt;/p&gt;


&lt;p&gt;That's all well and good, but wasn't the whole point of this to give our users a more convenient way to interface with our site and &lt;strong&gt;their&lt;/strong&gt; data? Let us have a look a a slightly more useful implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'rubygems'  
require 'xmpp4r-simple'
messenger = Jabber::Simple.new('my-bot@gmail.com', &quot;bot-password&quot;)
while true
  messenger.received_messages do |msg|
    user = User.find_by_im_name(msg.from)
    if user
      case msg.body
      when /^help /i
        messenger.deliver(msg.from, &quot;Valid commands are......&quot;)  
      when /^status /i
        user.status = msg.body.sub(/^status /i)
        user.save
        messenger.deliver(msg.from, &quot;Thanks #{user.first_name}, your status has been updated&quot;)  
      when /^balance\?/i
        messenger.deliver(msg.from, &quot;#{user.first_name}, your current remaining balance is #{user.remaining_balance}&quot;)  
      else
        messenger.deliver(msg.from, &quot;Sorry #{user.first_name}, I didn't understand that. Message me with 'help' for a list of commands&quot;)  
      end
    else
      messenger.deliver(msg.from, &quot;Sorry, but we've not got this account registered on our system. Sign-up or update your details at http://www.mysite.com/&quot;)  
    end    
  end  
  sleep 2  
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The easiest way to have this run now is to call it via &lt;strong&gt;script/runner&lt;/strong&gt; so that we can get access to our ActiveRecord models and interface with the underlying data. All you need to do is kick this off with an init script, setup something like &lt;a href=&quot;http://rubypond.com/articles/2007/12/28/touched-by-god-process-monitoring/&quot;&gt;god for process monitoring&lt;/a&gt; to ensure it stays alive and keeps within some same memory and CPU constraints.&lt;/p&gt;</description>
          <pubDate>Thu, 26 Jun 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/06/26/make-your-own-im-bot-in-ruby-and-interface-it-with-your-rails-app/</guid>
          <link>http://rubypond.com/articles/2008/06/26/make-your-own-im-bot-in-ruby-and-interface-it-with-your-rails-app/</link>
        </item>
    
        <item>
          <title>Ruby and Microformats</title>
          <description>&lt;p&gt;Heard about &lt;a href=&quot;http://microformats.org/&quot; rel=&quot;nofollow&quot;&gt;microformats&lt;/a&gt; ? Want to know how to consume them within your rails app? It's a suprisingly simple task. But why would you bother? Well lets take a somewhat practical example. What if on your site you wanted to include a list of upcoming events that you were either attending or might be of use to your users? Say for example, &lt;a href=&quot;http://upcoming.yahoo.com/search/?quick_date=next_7_days&amp;amp;search_placeid=DevLebebApj4RVbtaQ&amp;amp;rt=0&quot; rel=&quot;nofollow&quot;&gt;events in the UK for the next 30 days&lt;/a&gt;&lt;/p&gt;

            
&lt;p&gt;The first thing you need to do, is go grab &lt;a href=&quot;http://mofo.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;mofo&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install mofo&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now include it in your ruby/ruby on rails application:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'mofo'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, find the URL of the page you want to consume that is exposing it's data as a microformat (read the &lt;a href=&quot;http://www.microformats.org/&quot; rel=&quot;nofollow&quot;&gt;microformats&lt;/a&gt; website for various formats that are available and details on how they are implemented). And within our controller method, we will go and fetch the appropriate information from &lt;a href=&quot;http://upcoming.yahoo.com/search/?quick_date=next_7_days&amp;amp;search_placeid=DevLebebApj4RVbtaQ&amp;amp;rt=0&quot; rel=&quot;nofollow&quot;&gt;Upcoming&lt;/a&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;@events = hCalendar.find 'http://upcoming.yahoo.com/search/?quick_date=next_7_days&amp;amp;search_placeid=DevLebebApj4RVbtaQ&amp;amp;rt=0'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And within our view we could do something like the following (ignore the lack of partials and other useful things, this is just for demonstration purposes):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;ol&amp;gt;
&amp;lt;% @events.each do |event| %&amp;gt;
  &amp;lt;li&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;a href=&amp;quot;&amp;lt;%event.url%&amp;gt;&amp;quot;&amp;gt;&amp;lt;%=event.summary%&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;%=event.location%&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;%=event.dtstart.strftime(&amp;quot;%d %B&amp;quot;)%&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/ol&amp;gt;&lt;/code&gt;&lt;/pre&gt;

Of course, being good little net citizens we should probably also make the list into a microformat too just in case someone else wants to try and consume it from our site, so the addition of a few class attributes and a title tag or two will sort that out:

&lt;pre&gt;&lt;code&gt;&amp;lt;ol class=&amp;quot;vcalendar&amp;quot;&amp;gt;
&amp;lt;% @events.each do |event| %&amp;gt;
  &amp;lt;li class=&amp;quot;vevent&amp;quot;&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;a href=&amp;quot;&amp;lt;%event.url%&amp;gt;&amp;quot; class=&amp;quot;url summary&amp;quot;&amp;gt;&amp;lt;%=event.summary%&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;p class=&amp;quot;location&amp;quot;&amp;gt;&amp;lt;%=event.location%&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p class=&amp;quot;dtstart&amp;quot; title=&amp;quot;&amp;lt;%=event.dtstart.strftime(&amp;quot;%Y-%m-%d&amp;quot;)%&amp;gt;&amp;quot;&amp;gt;&amp;lt;%=event.dtstart.strftime(&amp;quot;%d %B&amp;quot;)%&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/ol&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Keep in mind, the current implementation will send off a request to &lt;a href=&quot;http://upcoming.yahoo.com/&quot; rel=&quot;nofollow&quot;&gt;upcoming.yahoo.com&lt;/a&gt; every time someone loads your page and could seriously harm performance, I'd recommend caching the results either to file or directly into a model/table and then having a process that regularly checks and updates the data at a certain interval.&lt;/p&gt;

&lt;p&gt;The possibilities here and endless, and you don't have to consume and re-display but you could create your own mashup for your personal use. Many shopping sites now include review information as a microformat, TripIt makes all of my itineraries available the same way. My recent interest has been spurred on by a site I'm working on where most of the data will be available as a microformat, hopefully letting 3rd parties develop uses for the site that I'd never imagined.&lt;/p&gt;</description>
          <pubDate>Thu, 19 Jun 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/06/19/ruby-and-microformats/</guid>
          <link>http://rubypond.com/articles/2008/06/19/ruby-and-microformats/</link>
        </item>
    
        <item>
          <title>Bulk insertion of data with ActiveRecord</title>
          <description>&lt;p&gt;Apologies to all for the extended hiatus, I was in the US for a month on holiday; and then I just got lazy. Anyway, I'm back and plugging someone else's extension. I came across ActiveRecord Extension last night, and was quite frankly dumbfounded that 1) I hadn't come across it before, and 2) More people weren't using it. In short, it will let you use ActiveRecord to batch insert multiple rows in a single query, rather than looping over the Model#create method and getting all the overhead that comes with it (and the hundred insert statements).&lt;/p&gt;
            
&lt;p&gt;Zach Dennis has written a great little plugin called &lt;a href=&quot;http://www.continuousthinking.com/tags/arext&quot; rel=&quot;nofollow&quot;&gt;ActiveRecord::Extensions&lt;/a&gt; which makes the bulk inserts almost as painless as your regular create.&lt;/p&gt;

&lt;p&gt;First, install the gem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install ar-extensions&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Include it in your app (you could put it in &lt;em&gt;environment.rb&lt;/em&gt; if you're going to use it a lot, for now I'll place it in my model definition in &lt;em&gt;user.rb&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'ar-extensions'
class User
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then to use it, it really couldn't be more straightforward. Use the following in your controller or rake task to import your data:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;fields = [:first_name, :last_name, :email]
data = [[&quot;glenn&quot;, &quot;gillen&quot;, &quot;foo@bar.com&quot;],
        [&quot;john&quot;, &quot;jones&quot;, &quot;jim@bar.com&quot;],
        [&quot;steve&quot;, &quot;smith&quot;, &quot;bar@foo.com&quot;]]

User.import fields, data&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we're done, 3 new rows have been inserted into the &lt;em&gt;users&lt;/em&gt; table, with just the single query. Any more questions, the &lt;a href=&quot;http://continuous.rubyforge.org/ar-extensions/rdoc/&quot; rel=&quot;nofollow&quot;&gt;RDocs are here&lt;/a&gt;&lt;/p&gt;</description>
          <pubDate>Wed, 18 Jun 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/06/18/bulk-insertion-of-data-with-activerecord/</guid>
          <link>http://rubypond.com/articles/2008/06/18/bulk-insertion-of-data-with-activerecord/</link>
        </item>
    
        <item>
          <title>Monitoring Backgroundrb with God</title>
          <description>I mentioned yesterday that I'd elaborate on how to extend our &lt;em&gt;app.god&lt;/em&gt; config so that god process monitoring automatically becomes aware of our changes. Well for those that can't wait, Graham who I pair with on the majority of my work beat me to the punch with with his post on &lt;a href=&quot;http://effectif.com/2008/4/8/monitoring-backgroundrb-with-god&quot; rel=&quot;nofollow&quot;&gt;Monitoring BackgroundRB with God&lt;/a&gt;. And at the end of the day English is his native language, so it's probably an easier read (I speak Australian).
</description>
          <pubDate>Wed, 09 Apr 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/04/09/monitoring-backgroundrb-with-god/</guid>
          <link>http://rubypond.com/articles/2008/04/09/monitoring-backgroundrb-with-god/</link>
        </item>
    
        <item>
          <title>Letting nginx automatically detect new rails apps</title>
          <description>&lt;p&gt;Following on from my post yesterday explaining &lt;a href=&quot;/articles/2008/04/07/rails-god-config/&quot;&gt;how to let god automatically detect any new rails apps&lt;/a&gt; is few capistrano and config tweaks. This time the changes will let nginx use the same config file we created to so that setting up a new upstream and rails config is as simple as a call to &lt;em&gt;deploy:setup&lt;/em&gt; in capistrano.&lt;/p&gt;


&lt;h2&gt;Make sure you've setup app.god&lt;/h2&gt;


&lt;p&gt;These changes have a dependency on the changes from my previous post, so be sure to follow the steps on creating &lt;em&gt;app.god&lt;/em&gt; to &lt;a href=&quot;/articles/2008/04/07/rails-god-config/&quot;&gt;dynamically configure god for rails&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;Create a new nginx task for capistrano&lt;/h2&gt;


&lt;p&gt;Within your &lt;em&gt;deploy.rb&lt;/em&gt; you want to insert this snippet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namespace :deploy do

  after &quot;deploy:setup&quot;, &quot;deploy:nginx:setup&quot; 

  namespace :nginx do
    desc 'Setup nginx upstream config'
    task :setup, :roles=&gt;:app do
      @apps = []
      eval(open(&quot;./config/app.god&quot;).read)
      nginx_upstream_config = []
      @apps.each do |app|
        upstream_name = app.class.to_s.downcase.gsub(/.*::/,&quot;&quot;)
        nginx_upstream_config &lt;&lt; &quot;upstream #{upstream_name} {\n&quot; 
        app.ports.each do |port|
          nginx_upstream_config &lt;&lt; &quot;\tserver 127.0.0.1:#{port};\n&quot; 
        end
        nginx_upstream_config &lt;&lt; &quot;}\n&quot; 

        nginx_upstream_config &lt;&lt; &lt;&lt;-EOF
        server {
          listen 80;
          client_max_body_size 50M;
          server_name #{app.server_names};
          root #{deploy_to}/current/public;
          access_log  /var/log/nginx.#{application}.access.log  main;

          if (-f $document_root/system/maintenance.html) {
            rewrite  ^(.*)$  /system/maintenance.html last;
            break;
          }

          location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;
            proxy_max_temp_file_size 0;

            if (-f $request_filename) { 
              break; 
            }

            if (-f $request_filename/index.html) {
              rewrite (.*) $1/index.html break;
            }

            if (-f $request_filename.html) {
              rewrite (.*) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://#{upstream_name};
              break;
            }
          }

          error_page   500 502 503 504  /500.html;
          location = /500.html {
            root   #{deploy_to}/current/public;
          }
        }        
        EOF

      end

      put nginx_upstream_config, &quot;#{shared_path}/config/nginx.conf&quot; 
      sudo &quot;ln -sf #{shared_path}/config/nginx.conf #{deploy_to}/current/nginx.conf&quot; 
      sudo &quot;mkdir -p /etc/nginx&quot; 
      sudo &quot;ln -sf #{deploy_to}/current/nginx.conf /etc/nginx/#{application}.conf&quot; 
      sudo &quot;/etc/init.d/nginx restart&quot; 
    end
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I'll run through what is happening here. Within &lt;em&gt;deploy:nginx:setup&lt;/em&gt; we first instantiate the &lt;em&gt;@apps&lt;/em&gt; variable, so that the &lt;em&gt;app.god&lt;/em&gt; we created previously has an instance to insert itself into. We then read in and execute &lt;em&gt;app.god&lt;/em&gt;, which means @apps will be populated with our application now.&lt;/p&gt;

&lt;p&gt;Now for each application (why would we have more than one? I'll explain at the end) we loop over and create an nginx upstream definition, with each of the ports specified within &lt;em&gt;app.god&lt;/em&gt;. Next is to create the standard nginx/rails config (feel free to change to suit your own needs), push it up to the server, and then link it into &lt;em&gt;/etc/nginx/application_name.conf&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;Required changes in nginx&lt;/h2&gt;


&lt;p&gt;The only thing you need to do within your &lt;em&gt;nginx.conf&lt;/em&gt; file is add the following line at the end of your &lt;i&gt;http&lt;/i&gt; service definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;include /etc/nginx/*.conf;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now, when you run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cap deploy:setup&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Capistrano will not just setup the rails directory structures, but will also update the nginx config to make it aware of your new application. It also means that your application specific nginx config now resides in your rails directory structure. Should you decide to take the application off the server, the nginx config disappears when the app does.&lt;/p&gt;

&lt;h2&gt;So why do you use @apps to specify the application?&lt;/h2&gt;

&lt;p&gt;Well with the god config from the previous post, god is dealing with every rails application on the server and stores the list of them within @apps. However, with this in most cases we are only dealing with one (the app we are deploying) so it's somewhat redundant. I say in most cases because there have been times when we've deployed the same application twice on the same server, running on different ports and accessible from different URLs. This meant we could do the following in &lt;em&gt;app.god&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Rubypond

  def initialize
    @ports = [8061, 8062, 8063]
  end
end

@apps &lt;&lt; Rubypond.new

class RubypondLabs
  attr_reader :name, :ports, :prefix

  def initialize
    @name = &quot;jetstream&quot; 
    @ports = [8071, 8072, 8073, 8074]
    @prefix = &quot;/labs&quot; 
  end
end

@apps &lt;&lt; RubypondLabs.new&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next up, how to extend what we've done so far to manage backgroundrb for us too.&lt;/p&gt;</description>
          <pubDate>Tue, 08 Apr 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/04/08/letting-nginx-automatically-detect-new-rails-apps/</guid>
          <link>http://rubypond.com/articles/2008/04/08/letting-nginx-automatically-detect-new-rails-apps/</link>
        </item>
    
        <item>
          <title>Rails god config</title>
          <description>&lt;p&gt;If you're anything like me, you're not a big one for shelling out needless money to host the various development sites your working on. That inevitably means you'll end up with a whole host of small applications running on the one server, each needing a mongrel or two, and of course you want to make sure they are up and running. Thanks to the wonder that is ruby (and god) we can easily set it up to automatically become aware of any new apps we deploy via capistrano.&lt;/p&gt;

&lt;h2&gt;Enter app.god&lt;/h2&gt;

&lt;p&gt;Don't stress if you've never heard of &lt;em&gt;app.god&lt;/em&gt;, it's a convention we've taken on where I'm currently working so chances are it doesn't exist outside my own little world. Here's what it looks like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Rubypond
  attr_reader :ports, :server_names

  def initialize
    @ports = [5000, 5001]
    @server_names = &quot;www.rubypond.com rubypond.com&quot; 
  end
end

@apps &lt;&lt; Rubypond.new&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we do is define a new class named after whatever we want to call our application, and then create a new instance off it in an array names &lt;em&gt;@apps&lt;/em&gt;. Next step, making &lt;em&gt;god&lt;/em&gt; aware of these config files.&lt;/p&gt;

&lt;h2&gt;Setting up god.conf&lt;/h2&gt;


&lt;p&gt;If we are going to be running multiple rails apps on the one server, there is going to be a lot of duplication with the config files. Life will be much easy if we extract the common bits into some methods that we can call at the appropriate time to create our god watch:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;def configure_mongrel(w, rails_root,  app_name, port)
  w.uid = &quot;mongrel&quot; 
  w.gid = &quot;webserver&quot; 
  w.name = &quot;#{app_name}-#{port}&quot; 
  w.group = &quot;#{app_name}&quot; 
  w.interval = 30.seconds
  w.start = &quot;mongrel_rails start -c #{rails_root} -p #{port} -P #{rails_root}/log/mongrel.#{port}.pid -e production -d&quot; 
  w.stop = &quot;mongrel_rails stop -P #{rails_root}/log/mongrel.#{port}.pid&quot; 
  w.restart = &quot;mongrel_rails restart -P #{rails_root}/log/mongrel.#{port}.pid&quot; 
  w.pid_file = &quot;#{rails_root}/log/mongrel.#{port}.pid&quot; 

  w.behavior(:clean_pid_file)
end

def start_if_not_running(w)
  w.start_if do |start|
    start.condition(:process_running) do |c|
      c.interval = 5.seconds
      c.running = false
    end
  end
end

def restart_if_resource_hog(w)
  w.restart_if do |restart|
    restart.condition(:memory_usage) do |c|
      c.notify = &quot;glenn&quot; 
      c.above = 150.megabytes
      c.times = [3,5]
    end

    restart.condition(:cpu_usage) do |c|
      c.notify = &quot;glenn&quot; 
      c.above = 50.percent
      c.times = 5
    end
  end
end

def monitor_lifecycle(w)
  w.lifecycle do |on|
    on.condition(:flapping) do |c|
      c.notify = &quot;glenn&quot; 
      c.to_state = [:start, :restart]
      c.times = 5
      c.within = 5.minutes
      c.transition = :unmonitored
      c.retry_in = 10.minutes
      c.retry_times = 5
      c.retry_within = 2.hours
    end
  end
end

def monitor_rails_app(w)
  start_if_not_running(w)
  restart_if_resource_hog(w)
  monitor_lifecycle(w)
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Letting god know about our rails apps&lt;/h2&gt;

&lt;p&gt;Next thing we want god to know about all our rails apps, we can use a standard ruby trick to traverse the appropriate directory tree for find our &lt;em&gt;app.god&lt;/em&gt; configs, and then load them in using the ruby load command:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;@apps = []
Dir[&quot;/var/www/apps/*/current/config/*.god&quot;].each { |config| load config}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And because of the way we've instantiated our classes in each config, @apps will now be an array of applications we want to configure. So we can iterate over each, and plug in the appropriate values:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@apps.each do |app|
  app_name = app.class.name.downcase
  rails_root = &quot;/var/www/apps/#{app_name}/current&quot; 

  app.ports.each do |port|
    God.watch do |w|
      configure_mongrel(w, rails_root, app_name, port)
      monitor_rails_app(w)
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all you need to do when you deploy a new application is make sure you have the &lt;em&gt;config/app.god&lt;/em&gt; file and restart your god instance, and it will automatically monitor your new application. Sweet! Next up I'll run through a capistrano task to complete the deal by using the same config to setup nginx. So, we may as well seal the deal by ensuring that happens in capistrano (in your &lt;em&gt;deploy.rb&lt;/em&gt; file):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;after &quot;deploy:setup&quot;, &quot;deploy:god:restart&quot; 

namespace :deploy do

  namespace :god do

    task :restart, :roles=&gt;:app do
      sudo &quot;/etc/init.d/god restart&quot; 
    end

  end
end&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Mon, 07 Apr 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/04/07/rails-god-config/</guid>
          <link>http://rubypond.com/articles/2008/04/07/rails-god-config/</link>
        </item>
    
        <item>
          <title>Using rspec have_tag</title>
          <description>&lt;p&gt;Not everyone realises that that rspec have&lt;em&gt;tag assertion is simply a wrapper for the Test::Unit assert&lt;/em&gt;select. And even if you do, do you really know how powerful a tool it is? I&amp;#8217;ve seen many tests and specs where people jump through a whole heap of hoops to check that the desired element exists, well no more! Fresh for today, a quick run down on some of the most useful and powerful selectors you can use with have&lt;em&gt;tag (and by default, assert&lt;/em&gt;select too).&lt;/p&gt;

&lt;h2&gt;Basic rspec have_tag usage&lt;/h2&gt;

&lt;p&gt;Alright, so the most basic of tests is to see if an element exists:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we aren&amp;#8217;t fussy, so long as any &amp;lt;li&amp;gt; element exists the assertion will pass. We can be a little more specific by also requiring that &amp;lt;li&amp;gt; tag to contain certain text:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li&quot;, :text =&gt; &quot;I'm a list item&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it will match &lt;em&gt;&amp;lt;li&amp;gt;I&amp;#8217;m a list item&amp;lt;/li&amp;gt;&lt;/em&gt;. And taking baby steps again, we can ensure that the list item has been given a specific class, ID, or both with one of the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li.my_class&quot;, :text =&gt; &quot;I'm a list item&quot;)
response.should have_tag(&quot;li#my_element_id&quot;, :text =&gt; &quot;I'm a list item&quot;)
response.should have_tag(&quot;li#my_element_id.my_class&quot;, :text =&gt; &quot;I'm a list item&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can essentially reference the elements exactly as you would in a CSS file.&lt;/p&gt;

&lt;h2&gt;Matching element attributes with have_tag&lt;/h2&gt;

&lt;p&gt;What if you want to ensure that something other than a class or ID exists on the element? Well again just like in CSS have_tag in rspec will let you target elements containing attributes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;img[alt=My accessible text]&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will check that a tag like &lt;em&gt;&amp;lt;img alt=&amp;#8221;My accessible text&amp;#8221;&amp;gt;&lt;/em&gt; exists somewhere in the result rendered by you view. You can extend this further with wildcard and pattern matchers on the attributes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;img[alt~=readable accessible usable]&quot;) # Match any of these words
response.should have_tag(&quot;img[alt^=My]&quot;) # Match attribute beginning with &quot;My&quot;
response.should have_tag(&quot;img[alt$=text]&quot;) # Match attribute ending with &quot;text&quot;
response.should have_tag(&quot;img[alt*=essibl]&quot;) # Match &quot;essibl&quot; anywhere in attribute
response.should have_tag(&quot;img[alt]&quot;) # Match any img element with alt attribute&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Advanced rspec have_tag CSS selectors&lt;/h2&gt;

&lt;p&gt;Taking it up a notch are some of the more advanced CSS selectors. In reality, I rarely (if ever) need to use these, but they&amp;#8217;re handy to have for those tricky situations where you&amp;#8217;d otherwise have to construct a loop to go through all the element manually. Assume we have a list of elements like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;ul&gt;
    &amp;lt;li&gt;I'm element 1&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 2&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 3&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 4&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 5&amp;lt;/li&gt;
  &amp;lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We could use the following assertions to get the respective elements based on their order:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li:nth-child(2)&quot;, :text =&gt; &quot;I'm element 2&quot;)
response.should have_tag(&quot;li:nth-last-child(2)&quot;, :text =&gt; &quot;I'm element 4&quot;)
response.should have_tag(&quot;ul:first-child&quot;, :text =&gt; &quot;I'm element 1&quot;)
response.should have_tag(&quot;ul:last-child&quot;, :text =&gt; &quot;I'm element 5&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can take a similar approach to retrieve elements based on their type. Consider the following chunk of HTML:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div&gt;
    &amp;lt;h1&gt;My big heading!&amp;lt;/h1&gt;
    &amp;lt;p&gt;I've got some paragraph text&amp;lt;/p&gt;
    &amp;lt;h2&gt;My smaller heading...&amp;lt;/h2&gt;
    &amp;lt;p&gt;I'm going to describe the list below&amp;lt;/p&gt;
    &amp;lt;ul&gt;
      &amp;lt;li&gt;I'm list 1&amp;lt;/li&gt;
      &amp;lt;li&gt;I'm list 2&amp;lt;/li&gt;
      &amp;lt;li&gt;I'm list 3&amp;lt;/li&gt;
    &amp;lt;/ul&gt;
  &amp;lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and then the have_tag selectors to get those elements:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;p:nth-of-type(2)&quot;, :text =&gt; &quot;I'm going to describe the list below&quot;)
response.should have_tag(&quot;li:nth-last-of-type(2)&quot;, :text =&gt; &quot;I'm list 2&quot;)
response.should have_tag(&quot;p:first-of-type&quot;, :text =&gt; &quot;I've got some paragraph text&quot;)
response.should have_tag(&quot;p:last-of-type&quot;, :text =&gt; &quot;I'm going to describe the list below&quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Using formulas in nth- specified selectors&lt;/h2&gt;

&lt;p&gt;As you see, we can target an element that is a specific child in the order of the DOM hierarchy. What about testing the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;ul&gt;
    &amp;lt;li class=&quot;highlight&quot;&gt;I'm element 1&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 2&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 3&amp;lt;/li&gt;
    &amp;lt;li class=&quot;highlight&quot;&gt;I'm element 4&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 5&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 6&amp;lt;/li&gt;
    &amp;lt;li class=&quot;highlight&quot;&gt;I'm element 7&amp;lt;/li&gt;
    &amp;lt;li&gt;I'm element 8&amp;lt;/li&gt;
  &amp;lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How would we test that all the appropriate elements have had their additional class applied? Well the easiest way would be to provide a formula to the &lt;em&gt;nth-&lt;/em&gt; selector types.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li:nth-of-type(3n+1).highlight&quot;, :count =&gt; 3)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That will ensure that every third &lt;em&gt;&amp;lt;li&amp;gt;&lt;/em&gt; element, starting at number 1, will have the highlight class applied and that we return exactly 3 matches.&lt;/p&gt;

&lt;h2&gt;Asserting the expected number of matches with rspec have_tag ##&lt;/h2&gt;

&lt;p&gt;As you saw in the previous example, it&amp;#8217;s quite simple to specify exactly how many matches should be returned. But what if you don&amp;#8217;t know? (note: I can&amp;#8217;t think of a valid reason why you wouldn&amp;#8217;t if you are mocking out your tests correctly, but I digress) Then you can specify an upper or lower limit or a range:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag(&quot;li:nth-of-type(3n+1).highlight&quot;, :maximum =&gt; 4)
response.should have_tag(&quot;li:nth-of-type(3n+1).highlight&quot;, :minimum =&gt; 1)
response.should have_tag(&quot;li:nth-of-type(3n+1).highlight&quot;, 1..4)&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Iterating over child elements in a block ##&lt;/h2&gt;

&lt;p&gt;Now imagine you have a page with more than one form on it. One for posting comments to a blog, one for logging in maybe? We want to test that the login form exists (and is going to the correct path), and that there are input elements for username and password within that form. Check this out:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;response.should have_tag &quot;form[action=/sessions]&quot; do
  with_tag &quot;input[type=text][name=username]&quot;
  with_tag &quot;input[type=password][name=password]&quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Neat eh?&lt;/p&gt;</description>
          <pubDate>Mon, 31 Mar 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/03/31/using-rspec-have_tag/</guid>
          <link>http://rubypond.com/articles/2008/03/31/using-rspec-have_tag/</link>
        </item>
    
        <item>
          <title>Moving over to Git</title>
          <description>&lt;p&gt;So you&amp;#8217;ve seen that Rails/Capistrano now natively supports Git? You&amp;#8217;ve bearing hearing all the hype about it but don&amp;#8217;t really know what it is, how to use it, or how to install it. But like most, you know it was invented by that Linus guy that invented Linux, so it can&amp;#8217;t be all bad. Well then come jump on board!&lt;/p&gt;

&lt;h2&gt;What is Git?&lt;/h2&gt;

&lt;p&gt;Git is a distributed version control system (you can skip this bit if you&amp;#8217;ve
used mercurial). If you can imagine &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt;, but without
the need to check back to a central server you&amp;#8217;re probably about half way
there. Without the concept of a central server, it means I can check out code
and develop until my heart is content on my laptop, while in transit, without
an internet connection. While &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt; wouldn&amp;#8217;t stop me
from doing this it did prevent me from committing any check-ins during this
period. That&amp;#8217;s problematic if I&amp;#8217;ve a particularly long trip (on a plane) as I
then end up checking in a large chunk of functionality in one single big
commit and I wont be able to undo just a portion of it. It&amp;#8217;s particularly good
with a distributed team (which often happens these days with coders all around
the world) as I can check out, check in, and not fear that I&amp;#8217;m occasionally
breaking someone else&amp;#8217;s code until it comes time to bundle up all my work and
submit it to the core code base. I get all the benefits of tiny atomic commits
so that I can easily undo just a small change, and none of the failings of
running your own &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt; repository as a silo.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s because, while there is no dependency on a central server, you can
commit and checkout to and from a central Git server whenever you like. Even
better, you can commit and checkout directly with a colleague or any other
user who has pulled a copy of the code and bypass the server altogether (e.g.,
two remote developers working on the same code who don&amp;#8217;t want to disrupt the
central repo just yet).&lt;/p&gt;

&lt;h2&gt;Installing Git on linux&lt;/h2&gt;

&lt;p&gt;If you&amp;#8217;re on a linux distro you may very well find you already have Git
installed. If you don&amp;#8217;t, it should be available as a package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo yum install git-core&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installing Git on Mac &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; (or installing Git from source)&lt;/h2&gt;

&lt;p&gt;For the Mac &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; users out there it will probably be
easiest to install it from source. The following commands should get you
there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://kernel.org/pub/software/scm/git/git-1.5.4.tar.bz2
wget http://www.kernel.org/pub/software/scm/git/git-manpages-1.5.4.tar.bz2
tar xjvf git-1.5.4.tar.bz2
cd git-1.5.4
./configure
make
sudo make install
cd ..
sudo tar xjvf git-manpages-1.5.4.tar.bz2 -C /usr/local/share/man&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&amp;#8217;re so inclined, now would probably be a good time to change to default
settings to get coloured output and a whole host of nifty shortcuts and
improvements. Check out this &lt;a
href=&quot;http://wincent.com/knowledge-base/Git_quickstart&quot;&gt;git quickstart
guide&lt;/a&gt; for a list of them&lt;/p&gt;

&lt;h2&gt;Using Git&lt;/h2&gt;

&lt;p&gt;If you&amp;#8217;ve used mercurial before this should all seem like second nature. If
you&amp;#8217;re used to &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt;, then there is only a minor
learning curve. The thing you need to keep in mind is that your local working
copy of the checkout, is also a server. So when you do a commit, you are
really only saving it to your local machine. Likewise, if you did a checkout,
you&amp;#8217;re doing it on the local machine. If you want to update your local copy
from a remote server like you would in &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt; you need
to &lt;em&gt;pull&lt;/em&gt;, to send your updates somewhere else you need to
&lt;em&gt;push&lt;/em&gt;. Let&amp;#8217;s quickly go through how you&amp;#8217;d checkout a working copy, and
make some changes to it. Firstly, you need to create a local clone of the
repository:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git://domain.com/path/to/git/repository my_local_dir&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create a new directory called &lt;em&gt;my&lt;em&gt;local&lt;/em&gt;dir&lt;/em&gt; and pull in a
copy of the the repository from the remote server. Next you make some changes
locally to the files and try to check them in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd my_local_dir
git commit -a&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will commit all local changes, to your local server. Now it&amp;#8217;s time to
&lt;em&gt;push&lt;/em&gt; those changes back upstream:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what if we want to check if there are any changes from the remote server?
Well we just &lt;em&gt;pull&lt;/em&gt; them in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git pull&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Creating a remote Git repository&lt;/h2&gt;

&lt;p&gt;That&amp;#8217;s all well and good if you&amp;#8217;ve got a repository already setup to check out
from. But what if you want to create your own. Well you can go with a hosted
option from providers like &lt;a href=&quot;http://github.com/&quot;&gt;GitHub&lt;/a&gt; or &lt;a
href=&quot;http://gitorious.org/&quot;&gt;Gitorious&lt;/a&gt; or if you are the &lt;span
class=&quot;caps&quot;&gt;DIY&lt;/span&gt; type, host your own. Go to the remote server location
where you want to have your repo and:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir myrepo.git
cd myrepo.git
git --bare init&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now obviously we&amp;#8217;ve created a directory and initialised a new Git repository
within it here. What the &lt;em&gt;bare&lt;/em&gt; option does is inform Git that this
won&amp;#8217;t be a working copy. We don&amp;#8217;t need to waste disk with the actual files
here, we just need to version control information and the changes (delta)
between files.&lt;/p&gt;

&lt;p&gt;You&amp;#8217;ve probably got a local codebase that you now want to check into your
brand new remote repo so you can code away, check in, remotely back it up, and
have others contribute. So locally:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd myapp
git init
git add .
git commit -m &quot;Initial check in&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we&amp;#8217;ve done here is initialise the local Git repository in our myapp
directory, add all the files in, and then commit the new files. All that is
left to do is let this repository know about a remote host, and then push our
changes there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git remote add origin ssh://remote.myserver.com/path/to/repo/myapp.git
git push origin master&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This lets the local repository know to treat the remote server as the origin
of the source, followed by a command to push our local master copy up to the
origin server. From now on, you can send any changes to the server with a
simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s it! Following shortly, how to port your existing &lt;span
class=&quot;caps&quot;&gt;SVN&lt;/span&gt; projects over and/or peacefully let Git and &lt;span
class=&quot;caps&quot;&gt;SVN&lt;/span&gt; projects co-exist.&lt;/p&gt;</description>
          <pubDate>Fri, 28 Mar 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/03/28/moving-over-to-git/</guid>
          <link>http://rubypond.com/articles/2008/03/28/moving-over-to-git/</link>
        </item>
    
        <item>
          <title>17 Rails plug-ins you should be using</title>
          <description>So you're pretty happy with your rails-fu, but are you using all the plug-ins you could be to make life easier for you and your users? The following is a list of plugins I use on almost all, or if not the vast majority of, projects I work on these days. As soon as I've setup my rails directory tree, I install these bad boys too.

&lt;h2&gt;&lt;a href=&quot;http://www.juixe.com/techknow/index.php/2006/06/18/acts-as-commentable-plugin/&quot; rel=&quot;nofollow&quot;&gt;acts_as_commentable&lt;/a&gt;&lt;/h2&gt; The quickest and easiest way to be able to add comments to an ActiveRecord model. Don't think just comments in the 'blog' sense though, I've used it in numerous places to act as a means of users providing feedback and notes on specific items.

&lt;h2&gt;&lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot; rel=&quot;nofollow&quot;&gt;acts_as_ferret&lt;/a&gt;&lt;/h2&gt; Ferret is a ruby port of the Apache/Java Lucene project which enables quick full-text searching. acts_as_ferret is simply a way of integrating that into rails easily, allowing you to do a full text scan across one or multiple ActiveRecord models in just a few lines of code.

&lt;h2&gt;&lt;a href=&quot;http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids/&quot; rel=&quot;nofollow&quot;&gt;acts_as_taggable_on_steroids&lt;/a&gt;&lt;/h2&gt; Taggable on steroids is a big step up from the original taggable plugin from DHH. It lets you do tagging like you see on most social networking sites simply, but will also calculate the cloud size of a specific term for you so you can highlight the most/least popular terms (like I do on this site).

&lt;h2&gt;&lt;a href=&quot;http://pragdave.pragprog.com/pragdave/2006/02/annotate_models.html&quot; rel=&quot;nofollow&quot;&gt;annotate_models&lt;/a&gt;&lt;/h2&gt; There are quite a few times where I'm needing to debug something on a server, or need to explain to someone else what an underlying table for an ActiveRecord model looks like and opening up a SQL session just seems overkill. Step in annotate_models, a handy rake task that will put the schema in a comment block at the top of your model. No more voodoo about where attributes are coming from, or confusion over what the underlying structure is.

&lt;h2&gt;&lt;a href=&quot;http://svn.techno-weenie.net/projects/plugins/attachment_fu/&quot; rel=&quot;nofollow&quot;&gt;attachment_fu&lt;/a&gt;&lt;/h2&gt; Rick Olson's upgrade to the original acts_as_attachment is a must have. It will handle image uploads and cropping/re-sizing, storage in a database/file system/AmazonS3 oh, and it works on more than just images! Upload those PDF and other attachments until your heart is content.

&lt;h2&gt;&lt;a href=&quot;http://nubyonrails.com/articles/autotest-rails&quot; rel=&quot;nofollow&quot;&gt;autotest&lt;/a&gt;&lt;/h2&gt; I can't imagine life without autotest hooked up with growl notifications on my macbook. You define your specs and follow your TDD/BDD approach to development and autotest will automatically keep track of what files you are editing and what tests need to be re-run. No need to wait for the whole test stack to execute to see the impact of one change, as soon as you hit save autotest will run just the required tests. Neat!

&lt;h2&gt;&lt;a href=&quot;http://backgroundrb.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;backgroundrb&lt;/a&gt;&lt;/h2&gt; There is nothing worse than tying up a mongrel instance with a long running process, especially one you don't necessarily need an instant user response on (maybe resizing an image? generating a report?). So push the task off the backgroundrb and let it take it's sweet time without affecting the rest of the site.

&lt;h2&gt;&lt;a href=&quot;http://svn.techno-weenie.net/projects/plugins/exception_logger/&quot; rel=&quot;nofollow&quot;&gt;exception_logger&lt;/a&gt;&lt;/h2&gt; Exception logger will trap any exceptions that are raised and store them to a database, and then provides a web interface for you to manage them. Much easier than trawling log files for problems.

&lt;h2&gt;&lt;a href=&quot;http://haml.hamptoncatlin.com/&quot; rel=&quot;nofollow&quot;&gt;haml&lt;/a&gt;&lt;/h2&gt; Hampton has made HTML fun again, and helped make it more structured and semantically correct in the process. HAML is a killer templating system to replace (or run along side if you wish) ERB. It really is worth a look, although it's benefit didn't fully smack me in the face until I ported an old project across to it.

&lt;h2&gt;&lt;a href=&quot;http://www.danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype&quot; rel=&quot;nofollow&quot;&gt;lowpro&lt;/a&gt;&lt;/h2&gt; Dan Webb wrote lowpro as a way of unobtrusively adding javascript into your rails applications. It wasn't until reading through his blog I realised how terrible (in terms of backward compatibility and separation of presentation and code) the standard rails way of doing things was.

&lt;h2&gt;&lt;a href=&quot;http://mr.hamptoncatlin.com/&quot; rel=&quot;nofollow&quot;&gt;make_resourceful&lt;/a&gt;&lt;/h2&gt; Hampton strikes again with a plug-in that could cut your RESTful controllers down to as little as 3 lines in some instances. I posted about how to &lt;a href=&quot;/articles/2007/11/27/simplifying-rails-controllers-with-make_resourceful/&quot; rel=&quot;nofollow&quot;&gt;simplify RESTful controllers&lt;/a&gt; last year

&lt;h2&gt;&lt;a href=&quot;http://www.danwebb.net/2006/11/17/rjs-minus-r&quot; rel=&quot;nofollow&quot;&gt;minus r&lt;/a&gt;&lt;/h2&gt; Dan Webb's back with more javascript help. This time, making RJS templates even easier by allowing you to enter straight javascript into them and not a bunch of ruby that has to be parsed.

&lt;h2&gt;&lt;a href=&quot;http://agilewebdevelopment.com/plugins/query_analyzer&quot; rel=&quot;nofollow&quot;&gt;query_analyzer&lt;/a&gt;&lt;/h2&gt; So how exactly to you know what to do to improve the performance of your rails up? query_analyzer certainly puts you on the right track for anything ActiveRecord related by outputting the sql EXPLAIN results into your log file. Then you can view the query execution path and work out what would be best served by having indexes added to them.

&lt;h2&gt;&lt;a href=&quot;https://terralien.devguard.com/svn/projects/plugins/query_trace/&quot; rel=&quot;nofollow&quot;&gt;query_trace&lt;/a&gt;&lt;/h2&gt; Knowing how to improve your queries is one thing, but how about you stop them being called altogether? Sounds like a useful task, until you try and identify exactly where that 'select * from users' is being called. Enter query_trace, to tell you where the problem is.

&lt;h2&gt;&lt;a href=&quot;http://weblog.techno-weenie.net/2006/8/1/restful-authentication-plugin&quot; rel=&quot;nofollow&quot;&gt;restful authentication&lt;/a&gt;&lt;/h2&gt; The quickest and easiest way to add in users, signup/login capabilities, and notification/confirmation emails. If you've not heard of this and used it you must have been living under a rock for 18 months.

&lt;h2&gt;&lt;a href=&quot;http://rspec.info/&quot; rel=&quot;nofollow&quot;&gt;rspec and rspec_on_rails&lt;/a&gt;&lt;/h2&gt; The new fashionable kid on the block from a testing perspective. I love the way the BDD approach generates tests that my non-IT counterparts can read, understand, and agree that it meets their requirements.

&lt;h2&gt;&lt;a href=&quot;http://errtheblog.com/posts/56-im-paginating-again&quot; rel=&quot;nofollow&quot;&gt;will_paginate&lt;/a&gt;&lt;/h2&gt; My new favourite pagination plugin out of the many trying to replace the one that has been removed from Rails 2.0. It's just so simple to both implement and test.</description>
          <pubDate>Mon, 18 Feb 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/02/18/17-rails-plug-ins-you-should-be-using/</guid>
          <link>http://rubypond.com/articles/2008/02/18/17-rails-plug-ins-you-should-be-using/</link>
        </item>
    
        <item>
          <title>Improved timezones in Rails 2.1</title>
          <description>&lt;p&gt;The latest release of rails has made the &lt;a href=&quot;http://rubypond.com/articles/2007/12/06/correctly-handling-multiple-time-zones-in-ruby-on-rails/&quot;&gt;handling of timezones in rails&lt;/a&gt; even easier. No longer do you need to install a couple of plugins, although you still need the &lt;em&gt;tzinfo&lt;/em&gt; gem.&lt;/p&gt;
            
&lt;p&gt;With the new baked in support for timezones in rails you can ignore the previous article on &lt;a href=&quot;http://rubypond.com/articles/2007/12/06/correctly-handling-multiple-time-zones-in-ruby-on-rails/&quot;&gt;how to support timezones in rails 1.2.x&lt;/a&gt;. Now all you need to do is set the desired timezone you want to be working in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time.zone = &quot;Pacific Time (US &amp;amp; Canada)&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Behind the scenes the date will be saved as UTC, but the appropriate timezone conversion will happen for you whenever you output a date or datetime.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; Time.zone = &amp;quot;Pacific Time (US &amp;amp;amp; Canada)&amp;quot; 
&amp;gt; @post = Post.find :first
&amp;gt; @post.created_at
=&amp;gt; Fri, 08 Feb 2008 09:00:00 PST -08:00
&amp;gt; @post.created_at = Time.utc 2008, 1, 1
&amp;gt; @post.created_at
=&amp;gt; Mon, 31 Dec 2007 16:00:00 PST -08:00&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It also makes it a breeze to display timezones that are customised to your end-users locality with a before filter:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ApplicationsController &amp;lt; ApplicationController
  before_filter :set_timezone

  private
    def set_timezone
      Time.zone = current_user.time_zone || &quot;Pacific Time (US &amp;amp; Canada)&quot; 
    end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alternatively you can specify a default timezone in your &lt;em&gt;environment.rb&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Rails::Initializer.run do |config|
  config.time_zone = &quot;Pacific Time (US &amp;amp; Canada)&quot; 
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh and of course &lt;em&gt;Time.now&lt;/em&gt; will still return the time according to the server, if you want the current time in the user's local timezone then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time.zone.now&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Fri, 08 Feb 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/02/08/improved-timezones-in-rails-2-1/</guid>
          <link>http://rubypond.com/articles/2008/02/08/improved-timezones-in-rails-2-1/</link>
        </item>
    
        <item>
          <title>Improving rails app and mongrel performance with Thin</title>
          <description>&lt;p&gt;&lt;a href=&quot;http://code.macournoyer.com/thin/&quot; rel=&quot;nofollow&quot;&gt;Thin&lt;/a&gt; is a replacement webserver for mongrel* that further improves the already lightening performance of mongrel. Installation is a breeze, performance is fantastic, but it's still in alpha so use with caution.&lt;/p&gt;
      
&lt;p&gt;As you can see in the chart above (taken from the &lt;a href=&quot;http://code.macournoyer.com/thin/&quot; rel=&quot;nofollow&quot;&gt;Thin&lt;/a&gt; website, I've not had a chance to verify independently), the improvement while handling 10 concurrent connections isn't exactly an order of magnitude larger. But you'll see that as concurrency increases, performance holds steady unlike using mongrel. This is because it's using &lt;a href=&quot;http://rubyeventmachine.com/&quot; rel=&quot;nofollow&quot;&gt;EventMachine&lt;/a&gt; network I/O library to handle incoming requests much quicker than mongrel can. But mongrel is super quick at parsing HTML and Marc recognised that, so Thin still uses mongrel to handle that aspect (and uses &lt;a href=&quot;http://rack.rubyforge.org/&quot;&gt;Rack&lt;/a&gt; to talk to it).&lt;/p&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;It's a gem, so it's easy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install thin&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Configuration&lt;/h2&gt;

&lt;p&gt;If you want to just get straight into it, you can start up a thin server with the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd /to/my_rails_app
thin start&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If however you want to setup a cluster similar to you have with your mongrel cluster, and then run those instances so it will continue to work with your upstream config in nginx do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thin config -C config/thin.yml --servers 3 --port 5000 --chdir
thin start -C config/thin.yml&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That will create a config file with 3 instances starting at port 5000.&lt;/p&gt;

&lt;h2&gt;Improving Thin performance with unix sockets&lt;/h2&gt;

&lt;p&gt;But we can do one better than that. Thin also supports a feature not often seen in the ruby webserver world, but one you've probably seen with MySQL. It can enable access to the webserver via a unix socket. What's the point? Well it means that communication doesn't have to got back through the internal ethernet interface with the associated TCP overhead. And thankfully, nginx has support for accessing upstreams via a socket. You can start a server as sockets with the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thin start --server 3 --socket /tmp/thin.sock&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That will create 3 sockets in &lt;em&gt;/tmp/&lt;/em&gt;, named &lt;em&gt;thin.0.sock&lt;/em&gt;, &lt;em&gt;thin.1.sock&lt;/em&gt;, and &lt;em&gt;thin.2.sock&lt;/em&gt;. All that is left to do is update your &lt;em&gt;nginx.conf&lt;/em&gt; to use these as your upstream:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;upstream  my_server {
  server   unix:/tmp/thin.0.sock;
  server   unix:/tmp/thin.1.sock;
  server   unix:/tmp/thin.2.sock;
}&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Wed, 06 Feb 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/02/06/improving-rails-app-and-mongrel-performance-with-thin/</guid>
          <link>http://rubypond.com/articles/2008/02/06/improving-rails-app-and-mongrel-performance-with-thin/</link>
        </item>
    
        <item>
          <title>Setting up nginx, ssl, and virtual hosts</title>
          <description>&lt;h2&gt;installing nginx&lt;/h2&gt;

&lt;p&gt;To install nginx you have a few options depending on the flavour of operating system you are running. You can either install it via a package manager, or download the source and compile it yourself. Using the package manager will mean you will get the latest known stable version for your OS, and have to worry less about working out dependencies or conflicts. However, you may be a version or two behind the official release.&lt;/p&gt;

&lt;h3&gt;installing nginx via yum/apt-get/rpm&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;ve got a preferred package manager on your system then it should be as easy as one of the following (choose whichever is appropriate):
    sudo yum install nginx
    sudo apt-get install nginx&lt;/p&gt;

&lt;p&gt;Alternatively you can download the rpm and install using that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget ftp://ftp.univie.ac.at/systems/linux/fedora/updates/9/i386.newkey/nginx-0.6.32-1.fc9.i386.rpm
rpm -Uvh nginx-0.6.32-1.fc9.i386.rpm&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;installing nginx via source&lt;/h3&gt;

&lt;p&gt;If none of the above is suitable, then you&amp;#8217;re off to compile it on your own. The following should do the trick and include the libraries/packages we need:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://sysoev.ru/nginx/nginx-0.7.2.tar.gz
tar zxvf nginx-0.7.2.tar.gz
cd nginx-0.7.2
./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/sbin --with-debug --with-http_ssl_module
make
sudo make install
sudo nginx&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;configuring an nginx virtual host&lt;/h2&gt;

&lt;p&gt;Now that it&amp;#8217;s up and running, time to configure nginx to know about a virtual host (or two) on your system. For now, lets just serve some static content so we get a feel for the config files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo nano /usr/local/nginx/conf/nginx.conf&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll see the default nginx config file, in recent versions it&amp;#8217;s fairly well commented to help you understand what is going on. Scroll down and find the definition that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen       80;
      server_name  _;

      #charset koi8-r;

      #access_log  logs/host.access.log  main;

      location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
      }

      error_page  404              /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
      }
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;I wont go into too much detail here, the important thing to note is where the root location is. Here&amp;#8217;s is specified as &lt;em&gt;/usr/share/nginx/html&lt;/em&gt;, which means a request to http://yoursite.com/directory/file.html is going to try and serve the file on your server from &lt;em&gt;/usr/share/nginx/html/directory/file.html&lt;/em&gt;. To create a new virtual host lets change this definition to look more like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen       80;
      server_name  www.yoursite.com;
      root   /var/www/yoursite.com/html;

      location / {                
        index  index.html index.htm;
      }
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;Now all requests coming in to http://www.yoursite.com will be handled by this definition, but &lt;strong&gt;only&lt;/strong&gt; requests for www.yoursite.com. If you want to handle another domain within this definition you can just put an additional server name in like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server_name  www.yoursite.com www.othersite.com;&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;Alternatively, if you want to have www.othersite.com serve up content from a different location you would just add another server definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen       80;
      server_name  www.yoursite.com;
      root   /var/www/yoursite.com/html;

      location / {                
        index  index.html index.htm;
      }
    }

    server {
      listen       80;
      server_name  www.othersite.com;
      root   /var/www/othersite.com/html;

      location / {                
        index  index.html index.htm;
      }
    }&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;configuring nginx for your rails app&lt;/h2&gt;

&lt;p&gt;The hosts are setup, now we can have one of them start serving some rails apps. Lets change the virtual host definition we had above for www.yoursite.com to look like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen 80;
      server_name  www.yoursite.com;
      root   /var/www/apps/yoursite/current/public;

      # Set the max size for file uploads to 50Mb
      client_max_body_size 50M;

      # this rewrites all the requests to the maintenance.html
      # page if it exists in the doc root. This is for capistrano's
      # disable web task
      if (-f $document_root/system/maintenance.html) {
        rewrite  ^(.*)$  /system/maintenance.html last;
        break;
      }

      location / {
        # needed to forward user's IP address to rails
        proxy_set_header  X-Real-IP  $remote_addr;

        # needed for HTTPS
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect false;
        proxy_max_temp_file_size 0;

        # If the file exists as a static file serve it directly without
        # running all the other rewrite tests on it
        if (-f $request_filename) { 
          break; 
        }

        # check for index.html for directory index
        # if its there on the filesystem then rewite 
        # the url to add /index.html to the end of it
        # and then break to send it to the next config rules.
        if (-f $request_filename/index.html) {
          rewrite (.*) $1/index.html break;
        }

        # this is the meat of the rails page caching config
        # it adds .html to the end of the url and then checks
        # the filesystem for that file. If it exists, then we
        # rewite the url to have explicit .html on the end 
        # and then send it on its way to the next config rule.
        # if there is no file on the fs then it sets all the 
        # necessary headers and proxies to our upstream mongrels
        if (-f $request_filename.html) {
          rewrite (.*) $1.html break;
        }

        if (!-f $request_filename) {
          proxy_pass http://railsapp;
          break;
        }
      }
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;What we have here is a series of rules that match the requested file against some regular expressions and underlying filesystem files. To tell nginx to serve any content that it finds matching the full requested path, starting in the directory defined as &lt;em&gt;root&lt;/em&gt; we do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (-f $request_filename) { 
      break; 
    }
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If that doesn&amp;#8217;t work, we assume it need to be served by the rails app so we send it through using this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (!-f $request_filename) {
      proxy_pass http://railsapp;
      break;
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;But what does &lt;em&gt;http://railsapp&lt;/em&gt; mean? No such server exists! Within nginx we need to define an upstream proxy. This will allow us to wrap all our mongrels up within a single definition, and nginx can take care of sending it through to the instances in the back end. To define the &lt;em&gt;railsapp&lt;/em&gt; upstream mongrels we add the following outside our server definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;upstream railsapp {
      server 127.0.0.1:3000;
      server 127.0.0.1:3001;
      server 127.0.0.1:3002;
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;h2&gt;setting up your nginx ssl server&lt;/h2&gt;

&lt;p&gt;What if we want to serve out site over HTTPS for security reasons? No problem! We just add a server definition that listens on the correct port (that&amp;#8217;s 443 for those of you playing along at home). So our definition would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen 443;
      server_name  www.yoursite.com;
      root   /var/www/apps/yoursite/current/public;

      # Rest of config here...&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;redirecting all traffic to your ssl server&lt;/h2&gt;

&lt;p&gt;To be extra secure, we&amp;#8217;ve decided that we want &lt;strong&gt;all&lt;/strong&gt; traffic to be handled over SSL. Well we can use the &lt;a href=&quot;http://dev.rubyonrails.org/svn/rails/plugins/ssl_requirement/README&quot; rel=&quot;nofollow&quot;&gt;ssl_requirement&lt;/a&gt; plugin in our rails app to completely prevent non-HTTPS access, just incase. We can also add this server definition to our nginx config to re-direct anybody who mistakenly links to the plain old HTTP address:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen 80;
      server_name www.yoursite.com;
      rewrite ^/(.*) https://yoursite.com/$1 permanent;
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;h2&gt;setting nginx error pages&lt;/h2&gt;

&lt;p&gt;Nginx will display some standard error messages should there be a problem, they&amp;#8217;re about as attractive as the standard ones that come with rails though. If you want to jazz them up and make the whole experience less jarring for your users then update these lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error_page   404 500 502 503 504  /http_error.html;
      location = /http_error.html {
      root   /var/www/errors;
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;And point it to the file you want to come up for all your errors. If you want to differentiate between various errors then configure each one individually:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error_page   500 502 503 504  /50x.html;
      location = /50x.html {
      root   /var/www/errors;
    }
    error_page   404   /404.html;
      location = /404.html {
      root   /var/www/errors;
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;h2&gt;directing nginx log output&lt;/h2&gt;

&lt;p&gt;If you&amp;#8217;re running multiple virtual hosts, it will probably pay to give each a log file of it&amp;#8217;s own rather than having a single jumbled mess to worry about. Basically any configuration you provide in the &lt;em&gt;http&lt;/em&gt; definition you can re-define on a per-server basis within each &lt;em&gt;server&lt;/em&gt; definition. So simply add these lines into the relevant virtual host/server definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
      listen 80;
      server_name  www.yoursite.com;
      root   /var/www/apps/yoursite/current/public;

      access_log  /var/log/nginx/yoursite.access.log  main;
      error_log  /var/log/nginx/yoursite.error.log  debug;

      # Rest of config...
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;h2&gt;make nginx serve cache content from a custom location&lt;/h2&gt;

&lt;p&gt;Some people may cache their rail output into a custom directory (and why wouldn&amp;#8217;t you, it makes clearing the cache so much easier). If that&amp;#8217;s the case, the usual nginx/rails configuration won&amp;#8217;t work as expected. Your site will still work, you&amp;#8217;ll just not be making the most of letting nginx serve your static content. To resolve it, add these lines in before the section that passes the request to your upstream proxy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (-f /cache$request_filename) { 
      rewrite (.*) /cache$1 break;
      break; 
    }

    if (-f /cache$request_filename.html) { 
      rewrite (.*) /cache$1.html break;
      break; 
    }&lt;/code&gt;&lt;/pre&gt;    

&lt;p&gt;Where &lt;em&gt;/public/cache&lt;/em&gt; is where you are storing all of your cached content. Obviously, alter to fit accordingly.&lt;/p&gt;</description>
          <pubDate>Fri, 01 Feb 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/02/01/setting-up-nginx-ssl-and-virtual-hosts/</guid>
          <link>http://rubypond.com/articles/2008/02/01/setting-up-nginx-ssl-and-virtual-hosts/</link>
        </item>
    
        <item>
          <title>Free ATOM feed loving</title>
          <description>&lt;p&gt;Chris over at Err the Blog have a great article about how you can very quickly and easily &lt;a href=&quot;http://errtheblog.com/posts/78-feeds-for-free&quot; rel=&quot;nofollow&quot;&gt;create ATOM syndication of your content&lt;/a&gt; with a gem called mofo.&lt;/p&gt;


&lt;h2&gt;What are microformats?&lt;/h2&gt;

&lt;p&gt;I'll avoid any misrepresentation by taking the definition straight from the &lt;a href=&quot;http://microformats.org/&quot; rel=&quot;nofollow&quot;&gt;microformats site&lt;/a&gt;
&lt;blockquote&gt;
Designed for humans first and machines second, microformats are a set of simple, open data formats built upon existing and widely adopted standards
Basically what it means in practice is that if you've written well structured and semantically correct (X)HTML code, then with the sprinkling of a few additional class definitions or attributes you can extend what you've already got to support microformats.
&lt;/blockquote&gt;&lt;/p&gt;

&lt;h2&gt;What are some example microformats?&lt;/h2&gt;

&lt;p&gt;There are already formats defined for &lt;a href=&quot;http://microformats.org/wiki/hcard&quot; rel=&quot;nofollow&quot;&gt;people, places, and business cards&lt;/a&gt;, &lt;a href=&quot;http://microformats.org/wiki/hcalendar&quot; rel=&quot;nofollow&quot;&gt;events and calendaring&lt;/a&gt;, &lt;a href=&quot;http://microformats.org/wiki/vote-links&quot; rel=&quot;nofollow&quot;&gt;voting&lt;/a&gt;, &lt;a href=&quot;http://microformats.org/wiki/hreview&quot; rel=&quot;nofollow&quot;&gt;reviews&lt;/a&gt;, &lt;a href=&quot;http://www.gmpg.org/xfn/&quot; rel=&quot;nofollow&quot;&gt;friends and connections&lt;/a&gt;, and &lt;a href=&quot;http://microformats.org/wiki/rel-tag&quot; rel=&quot;nofollow&quot;&gt;tags&lt;/a&gt; to name but just a select few.&lt;/p&gt;

&lt;h2&gt;Okay, so how do we turn this into a ATOM feed?&lt;/h2&gt;

&lt;p&gt;Well here is what the entry for this article in the main page listing would currently look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&amp;quot;entry&amp;quot;&amp;gt;
  &amp;lt;span class=&amp;quot;header&amp;quot;&amp;gt;
    &amp;lt;h3&amp;gt;&amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/&amp;quot;&amp;gt;Free ATOM feed loving&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
    &amp;lt;p class=&amp;quot;info&amp;quot;&amp;gt;Posted by glenn gillen on Jan 23, 2008&amp;lt;/p&amp;gt;
    &amp;lt;p class=&amp;quot;info tag_line&amp;quot;&amp;gt;Posted in &amp;lt;a href=&amp;quot;/tag/microformats&amp;quot;&amp;gt;microformats&amp;lt;/a&amp;gt;, &amp;lt;a href=&amp;quot;/tag/atom&amp;quot;&amp;gt;atom&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/span&amp;gt;
  &amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/&amp;quot;&amp;gt;&amp;lt;img alt=&amp;quot;&amp;quot; size=&amp;quot;preview&amp;quot; src=&amp;quot;&amp;quot;/&amp;gt;&amp;lt;/a&amp;gt;
  &amp;lt;br/&amp;gt;
  &amp;lt;p&amp;gt;Chris over at Err the Blog have a great article about how you can very quickly and easily
     &amp;lt;a href=&amp;quot;http://errtheblog.com/posts/78-feeds-for-free&amp;quot;&amp;gt;with a gem called mofo.&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/#extended&amp;quot;&amp;gt;More...&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And all it would take to turn it into a microformat hEntry is to make it the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&amp;quot;entry hentry&amp;quot;&amp;gt;
  &amp;lt;span class=&amp;quot;header&amp;quot;&amp;gt;
    &amp;lt;h3&amp;gt;&amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/&amp;quot; class=&amp;quot;entry-title&amp;quot;&amp;gt;Free ATOM feed loving&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
    &amp;lt;p class=&amp;quot;info&amp;quot;&amp;gt;Posted by &amp;lt;span class=&amp;quot;author vcard fn&amp;quot;&amp;gt;glenn gillen&amp;lt;/span&amp;gt; on &amp;lt;abbr class=&amp;quot;updated&amp;quot; title=&amp;quot;2008-01-23T09:00:00Z&amp;quot;&amp;gt;Jan 23, 2008&amp;lt;/abbr&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p class=&amp;quot;info tag_line&amp;quot;&amp;gt;Posted in &amp;lt;a href=&amp;quot;/tag/microformats&amp;quot;&amp;gt;microformats&amp;lt;/a&amp;gt;, &amp;lt;a href=&amp;quot;/tag/atom&amp;quot;&amp;gt;atom&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/span&amp;gt;
  &amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/&amp;quot;&amp;gt;&amp;lt;img alt=&amp;quot;&amp;quot; size=&amp;quot;preview&amp;quot; src=&amp;quot;&amp;quot;/&amp;gt;&amp;lt;/a&amp;gt;
  &amp;lt;br/&amp;gt;
  &amp;lt;p class=&amp;quot;entry-content&amp;quot;&amp;gt;Chris over at Err the Blog have a great article about how you can very quickly and easily
     &amp;lt;a href=&amp;quot;http://errtheblog.com/posts/78-feeds-for-free&amp;quot;&amp;gt;with a gem called mofo.&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;a href=&amp;quot;/articles/2008/01/23/free-atom-feed-loving/#extended&amp;quot;&amp;gt;More...&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just to highlight it incase you missed it. There is a new &lt;em&gt;hentry&lt;/em&gt; class on the container div, a new &lt;em&gt;entry-title&lt;/em&gt; on the link to the entry, a span defining a vcard around my name, and the readable date has an &lt;em&gt;abbr&lt;/em&gt; tag to translate it back into something the computer prefers. And finally, the &lt;em&gt;p&lt;/em&gt; containing the content has had an &lt;em&gt;entry-content&lt;/em&gt; class applied.&lt;/p&gt;

&lt;p&gt;So that takes care of outputting it in as a microformat, but what use is that unless you've got something to consume it? How about we use mofo to render our view, extract the microformats, and then publish them as a feed for inclusion in your favourite reader? Add something like this to your controller:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def index
  @posts = Post.find(:all)
  respond_to do |format|
    format.html 
    format.rss do
      target = url_for(:action =&gt; :index, :format =&gt; &quot;html&quot;)
      render :xml =&gt; hEntry.find(target).to_atom(:title =&gt; 'whatever')
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Great! So tell me how to install it already!&lt;/h2&gt;

&lt;p&gt;Literally a 1-2-3:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install mofo
cd rails_app/vendor/plugins
gem unpack mofo&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Wed, 23 Jan 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/01/23/free-atom-feed-loving/</guid>
          <link>http://rubypond.com/articles/2008/01/23/free-atom-feed-loving/</link>
        </item>
    
        <item>
          <title>Playing with Merb</title>
          <description>&lt;p&gt;So there has been quite a lot of talk of late about &lt;a href=&quot;http://www.merbivore.com/&quot;&gt;merb&lt;/a&gt;, the new up and comer vying for the rails crown. It was initially developed by Ezra of EngineYard fame, and it's generally considered that 'They know their stuff'(tm). So what is merb? Is it a viable alternative to rails? How easy/hard is the migration from one to the other?&lt;/p&gt;


&lt;p&gt;I figured it was long overdue that I take a look.&lt;/p&gt;
  
  
    &lt;h2&gt;What is Merb? How is it different to Ruby on Rails?&lt;/h2&gt;


&lt;p&gt;Merb is a Rails-inspired MVC framework for web application development. It's major point of difference with Rails is that it's not so prescriptive on what external libraries you have to use. Don't like prototype/scriptaculous? Swap it out for &lt;a href=&quot;http://jquery.com/&quot;&gt;JQuery&lt;/a&gt; or &lt;a href=&quot;http://mootools.net/&quot;&gt;Moo&lt;/a&gt;. Don't like ActiveRecord? Try &lt;a href=&quot;http://datamapper.org/&quot;&gt;DataMapper&lt;/a&gt; or &lt;a href=&quot;http://sequel.rubyforge.org/&quot;&gt;Sequel&lt;/a&gt; instead. One of the implications of this is that it means that no longer do you have to fire up a cluster of mongrels to compensate for the fact that aspects of rails aren't thread safe.&lt;/p&gt;


&lt;h2&gt;Getting started with Merb&lt;/h2&gt;


&lt;p&gt;Installing it is simple as Ezra and the crew have made it available as a gem.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install merb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then to create a new application skeleton and get started it's just:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;merb my_app&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So far it should seem fairly familiar! But how do we start playing with our database?&lt;/p&gt;


&lt;h2&gt;Connecting to a database&lt;/h2&gt;

&lt;p&gt;Well because merb doesn't impose any decisions on what ORM to use, you need to install your own. You can stick with ActiveRecord if you like, but let's try something new.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install datamapper merb_datamapper do_mysql&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We've just installed the DataMapper ORM, the merb interface, and the mysql drivers. Next thing to do to test connecting to a database is setup the connection, and create a model. Update the &lt;em&gt;config/dependencies.rb&lt;/em&gt; file and uncomment the following line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;### Uncomment for DataMapper ORM
use_orm :datamapper&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we need to create a &lt;em&gt;config/database.yml&lt;/em&gt; file which should be nothing shocking to look at:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;---
# This is a sample database file for the DataMapper ORM
:development: &amp;defaults
  :adapter: mysql
  :database: myapp_development
  :username: root
  :password:
  :host: localhost

:test:
  &lt;&lt;: *defaults
  :database: myapp_test

:production:
  &lt;&lt;: *defaults
  :database: myapp_production&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and now the joy of creating a model:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;script/generate model person --skip-migration&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Skip migrations? Are you mad? Do I have to go back creating tables myself? Bear with me here, I'll touch on migrations shortly. Next I'll define some properties on my model in &lt;em&gt;apps/models/person.rb&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Person &lt; DataMapper::Base
  property :name, :string
  property :dob, :date
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Migrations with DataMapper&lt;/h2&gt;

&lt;p&gt;So we've planned out our model, added in the properties we need. Now if only we could add/retrieve records to/from a table? Creating the required schema in the database is one line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rake dm:db:automigrate&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's right, DataMapper has automated migrations. It will infer from your model definitions what fields need to exist and create them as appropriate. It'll also take care of primary and foreign keys too! You need to be careful though, because remove a column from the model definition and the next time you automigrate you'll lose that column in the DB too.&lt;/p&gt;

&lt;h2&gt;So what about the views? What templating systems do I have?&lt;/h2&gt;

&lt;p&gt;Okay, so creating models isn't too difficult or different from rails. Thankfully the same is true of views too. You can use erubius if you like, but to keep things as close to my version of 'normal' as possible I'm sticking with HAML. So it's really business as usual on this front. Create your views as you normally would, and it should 'just work'&lt;/p&gt;

&lt;p&gt;Watch this space for a deeper end-to-end tutorial or screen cast where I'll have a full basic app. Feel free to shoot through any ideas you have.&lt;/p&gt;</description>
          <pubDate>Thu, 17 Jan 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/01/17/playing-with-merb/</guid>
          <link>http://rubypond.com/articles/2008/01/17/playing-with-merb/</link>
        </item>
    
        <item>
          <title>Testing web services with rspec</title>
          <description>&lt;p&gt;So you've come over to testing with rspec and it first the bill on most occasions. There are still a few areas though, like decent integration testing, where you still fall back to Test::Unit. So what about testing web services? Sure, ActionWebService is no longer part of rails core but a number of my clients have legacy systems we need to talk to, or 3rd party applications that have been built around SOAP. And at the end of the day, they're still a damn sight better than many of the other alternatives even if it's not part of the new church of REST.&lt;/p&gt;

&lt;p&gt;So now it's time to combine the best of the old-school with the best of the new, SOAP meets RSpec&lt;/p&gt;

&lt;p&gt;Start with a normal rspec controller spec, with two minor changes. Here's an example from a recent project:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../spec_helper'
require 'action_web_service/test_invoke'

describe MySOAPController do
   
  before do
    @account_xml = &lt;&lt;-EOF
      &lt;account&gt;
        ... some elements here ...
      &lt;/account&gt;
    EOF
    
  end
    
  it &quot;should parse account xml and return true if successful&quot; do
    User.should_receive(:create)
    result = invoke :AddAccount, @account_xml
    result.should eql(true)
  end
  
  it &quot;should parse account xml and return false if data is invalid&quot; do
    User.should_not_receive(:create)
    result = invoke :AddAccount, &quot;no xml here!&quot;
    result.should eql(false)
  end
  
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only noticeable differences here are that we've got an additional include reference:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'action_web_service/test_invoke'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and that rather than raising a get/post/put/delete to retrieve the data, we call invoke against the API and return the result to a local variable to later call assertions on, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;result = invoke :AddAccount, @account_xml&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The syntax is invoke followed by the method name you wish to call, and then whatever parameters the method is expecting. In this instance it receives an XML string as the only parameter, and is expected to return a boolean response&lt;/p&gt;</description>
          <pubDate>Mon, 07 Jan 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/01/07/testing-web-services-with-rspec/</guid>
          <link>http://rubypond.com/articles/2008/01/07/testing-web-services-with-rspec/</link>
        </item>
    
        <item>
          <title>Unobtrusive javascript with lowpro</title>
          <description>&lt;p&gt;Dan Webb's &lt;a href=&quot;http://www.danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype&quot; rel=&quot;nofollow&quot;&gt;lowpro&lt;/a&gt; library has been around for quite a while now, but if the sites I frequent are anything to go by it's adoption is far from widespread. Why? Frankly, I don't know. It's a brilliant library and if you're already using things like prototype and scriptaculous but you're not all over lowpro then there is a good chance you need to be seriously smacked around a bit.&lt;/p&gt;


&lt;p&gt;Rails comes with a heap of built-in helpers for doing useful things like autocomplete boxes and inline editing. But at the end of the day, while the implementation from the developers perspective is relatively clean the actual code they generate sucks major ass. If you view source on the output, you'll find that there is lots of javascript now embedded within the HTML document. Not only is the HTML no longer just describing the structure of the page, but in many cases you've created a dependency on the end user to have javascript to be able to use your site. It also means to test your site properly, you &lt;em&gt;have&lt;/em&gt; to be using something like selenium as the standard rails test framework(s) won't execute your javascript.&lt;/p&gt;


&lt;h2&gt;How does lowpro help?&lt;/h2&gt;


&lt;p&gt;It means you focus on developing a site that works for &lt;em&gt;everyone&lt;/em&gt; to begin with. No stinking javascript, no silly business or aesthetic logic being inserted into your HTML. Instead, you have a traditional HTML (and CSS) only site that works for all browsers, all users, all of the time. &lt;em&gt;Then&lt;/em&gt; you go about having lowpro add in the logic you require at run-time to improve the user experience for those that support it.&lt;/p&gt;


	&lt;h2&gt;Installing and setting up lowpro&lt;/h2&gt;


&lt;p&gt;Firstly grab the 0.2.0 release &lt;a href=&quot;http://svn.danwebb.net/external/lowpro/tags/rel-0.2/dist/lowpro-0.2.zip&quot; rel=&quot;nofollow&quot;&gt;from here&lt;/a&gt; and unzip the files into your project. Now this library is dependent on prototype, so if you're using jquery or something else that'll be the topic of a later discussion. Next you have to include prototype and lowpro in your HTML. None of this is rails specific, and none of it is going to involve ruby. It's back to old-skool javascript skills. Here's what you need to include:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script src=&amp;quot;/js/prototype.js&amp;quot; type=&amp;quot;text/javascipt&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/js/lowpro.js&amp;quot; type=&amp;quot;text/javascipt&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Using lowpro&lt;/h2&gt;


&lt;p&gt;So this is obviously the most important bit. Forget everything you used to know about onload, onmouseover, onclick, etc. Now you create a javascript file to contain all the logic you need and who needs to respond to what. Replace &amp;lt;body onload=&quot;alert('hello!')&quot;&gt; with:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Event.onReady(function() {
  alert('hello!');
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The brilliant things about attaching the event in this fashion is that rather than executing after the entire document has finished loading (which can include images and &lt;em&gt;everything&lt;/em&gt;), it will fire as soon as the browser has parsed the HTML and knows the document layout (or once the DOM had loaded for those up with the lingo). That means you can have the actions fire as soon as the document has loaded, but before the user sees anything.&lt;/p&gt;

&lt;p&gt;But what about those mouse over and mouse click events? You've got a button called &lt;em&gt;'foo'&lt;/em&gt; that you want to say boo when you click on it, likewise you've got all of links with the class of &lt;em&gt;'bar'&lt;/em&gt; that you want to highlight whenever the mouse passes over them. It's as simple as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Event.observe($('foo'), 'click', function(e) {
    alert('boo!');
});

Event.addBehavior({
    'a.bar:mouseover' : function(e) {
      this.visualEffect('highlight');
    }
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there we go, &lt;em&gt;#foo&lt;/em&gt; now has an onclick event applied to it. Meanwhile every link with a class of &lt;em&gt;bar&lt;/em&gt; has had a mouseover event applied. You can of course nest and stack these events until your heart is content. Kudos once again to Dan for such an awesome library&lt;/p&gt;</description>
          <pubDate>Thu, 03 Jan 2008 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2008/01/03/unobtrusive-javascript-with-lowpro/</guid>
          <link>http://rubypond.com/articles/2008/01/03/unobtrusive-javascript-with-lowpro/</link>
        </item>
    
        <item>
          <title>Touched by god (process monitoring)</title>
          <description>&lt;p&gt;The tag ling from the &lt;a href=&quot;http://god.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;god website&lt;/a&gt; simply states &lt;em&gt;'Like monit, only awesome'&lt;/em&gt;, and having played with it for a couple of days over the break now I have to agree. Monit was very handy at the time, but I found myself growing increasingly frustrated with it when things wouldn't restart properly (stuck sockets with backgroundrb being an example), and it's lack of logging only compounded the situation.&lt;/p&gt;


&lt;p&gt;And then I found god.&lt;/p&gt;


&lt;p&gt;All blasphemy aside, this tool really is awesome. The scripts are in ruby so you can be as creative as you want, it has in built support to add in your own behaviour hooks (like a clean_socket action on trying to restart backgroundrb) and best of all it provides incredibly in-depth logging, request-able on a per process basis.&lt;/p&gt;


&lt;h2&gt;Installing god&lt;/h2&gt;


&lt;p&gt;It's a gem, so installation couldn't be easier:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;
sudo gem install god
&lt;/code&gt;
&lt;/pre&gt;

&lt;h2&gt;Configuring god&lt;/h2&gt;


&lt;p&gt;Next step was to setup a config file. I called mine &lt;em&gt;/etc/god.conf&lt;/em&gt; and set it up to dynamically include any thing in &lt;em&gt;/etc/god.d/&lt;/em&gt; like so:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
God.load &quot;/etc/god.d/*.god&quot; 
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;For another client who is running a server with multiple applications, we set it up so that the god config could actually be deployed with the rails applications, so the &lt;em&gt;/etc/god.conf&lt;/em&gt; file looked like:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
God.load &quot;/var/www/apps/*/current/config/*.god&quot; 
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;But now onto the nitty gritty of what is actually in those application specific configs. Here's an example from this site:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;app_root = &quot;/var/www/apps/rubypond/current&quot; 

%w{10000 10001}.each do |port|
  God.watch do |w|
    w.name = &quot;rubypond-mongrel-#{port}&quot; 
    w.group =&quot;rubypond&quot; 
    w.uid = &quot;mongrel&quot; 
    w.interval = 30.seconds # default
    w.start = &quot;mongrel_rails start -c #{app_root} -p #{port} \
      -P #{app_root}/log/mongrel.#{port}.pid  -d -e production&quot; 
    w.stop = &quot;mongrel_rails stop -P #{app_root}/log/mongrel.#{port}.pid&quot; 
    w.restart = &quot;mongrel_rails restart -P #{app_root}/log/mongrel.#{port}.pid&quot; 
    w.start_grace = 10.seconds
    w.restart_grace = 10.seconds
    w.pid_file = File.join(app_root, &quot;log/mongrel.#{port}.pid&quot;)

    w.behavior(:clean_pid_file)

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.interval = 5.seconds
        c.running = false
      end
    end

    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
        c.above = 100.megabytes
        c.times = [3, 5] # 3 out of 5 intervals
      end

      restart.condition(:cpu_usage) do |c|
        c.above = 50.percent
        c.times = 5
      end
    end

    # lifecycle
    w.lifecycle do |on|
      on.condition(:flapping) do |c|
        c.to_state = [:start, :restart]
        c.times = 5
        c.within = 5.minute
        c.transition = :unmonitored
        c.retry_in = 10.minutes
        c.retry_times = 5
        c.retry_within = 2.hours
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hopefully the intention of the config is relatively clear. For the given ports (10000 and 10001) create a new god watch that has these properties and these SLAs. The thing that may need clarifying is what exactly is flapping? Well it's the state god goes into when it tries to start your service, and it instantly terminates for whatever reason. In the example, if these occurs 5 times within 5 minutes then the process will be unmonitored for a further 10 minutes, before trying again. This will go on for 2 hours before finally giving up. Another cool thing is that you don't always need to explicitly provide a restart command, god is intelligent enough to assume that if one doesn't exist it should use start and then stop instead.&lt;/p&gt;


&lt;h2&gt;Monitoring MySQL with god&lt;/h2&gt;


&lt;p&gt;But hey, why constrain it just to rails apps? Here's the config to get MySQL into the Garden of Eden:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;God.watch do |w|
  w.name = 'mysql'
  w.interval = 30.seconds # default
  w.start = &quot;cd /etc/init.d &amp;&amp; ./mysqld start&quot; 
  w.stop = &quot;cd /etc/init.d &amp;&amp; ./mysqld start&quot; 
  w.restart = &quot;cd /etc/init.d &amp;&amp; ./mysqld restart&quot; 
  w.start_grace = 10.seconds
  w.restart_grace = 10.seconds
  w.pid_file = '/var/run/mysqld/mysqld.pid'
  w.behavior(:clean_pid_file)

  w.start_if do |start|
    start.condition(:process_running) do |c|
      c.interval = 5.seconds
      c.running = false
    end
  end

  # lifecycle
  w.lifecycle do |on|
    on.condition(:flapping) do |c|
      c.to_state = [:start, :restart]
      c.times = 5
      c.within = 5.minute
      c.transition = :unmonitored
      c.retry_in = 10.minutes
      c.retry_times = 5
      c.retry_within = 2.hours
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Email and notifications&lt;/h2&gt;


It's all well and good having god keep the system up and accessibly, but it's still nice to know when things have gone wrong so you can try and prevent it from occurring again. You'll need to add some email settings to the top of &lt;em&gt;/etc/god.conf&lt;/em&gt;, be sure to change them to something appropriate for your server:


&lt;pre&gt;&lt;code&gt;God::Contacts::Email.message_settings = {
  :from =&gt; 'god@rubypond-example.com'
}

God::Contacts::Email.server_settings = {
  :address =&gt; &quot;localhost&quot;,
  :port =&gt; 25,
  :domain =&gt; &quot;rubypond.com&quot;,
  :authentication =&gt; :plain,
  :user_name =&gt; &quot;glenn&quot;,
  :password =&gt; &quot;password&quot; 
}

God.contact(:email) do |c|
  c.name = 'glenn'
  c.email = 'glenn@example.com'
end&lt;/code&gt;&lt;/pre&gt;

Then you need to add a notification to the transition state you want to be alerted of:


&lt;pre&gt;&lt;code&gt;w.transition(:up, :start) do |on|
  on.condition(:process_exits) do |c|
    c.notify = 'tom'
  end
end&lt;/code&gt;&lt;/pre&gt;

Tada! And there you have it, a whole bunch of god-like goodness. I'll follow up with another article with some more app specific configs, and how to extend with your own behaviours.</description>
          <pubDate>Fri, 28 Dec 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/12/28/touched-by-god-process-monitoring/</guid>
          <link>http://rubypond.com/articles/2007/12/28/touched-by-god-process-monitoring/</link>
        </item>
    
        <item>
          <title>A handy ruby utility (belt)</title>
          <description>&lt;p&gt;Giles Bowkett has created a very handy gem called &lt;a href=&quot;http://utilitybelt.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;utility belt&lt;/a&gt;. For those that find themselves forever delving into script/console or IRB, this can make life seem oh-so-fantastic.&lt;/p&gt;

&lt;p&gt;I won't bore you with the syntax and full feature list here, as Giles has &lt;a href=&quot;http://utilitybelt.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;already extensively done that&lt;/a&gt;. But a quick short list of the ones I've already found useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated indentation&lt;/li&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;li&gt;Command line AmazonS3 access&lt;/li&gt;
&lt;li&gt;Pastie integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quick, go grab it now while stocks last!&lt;/p&gt;</description>
          <pubDate>Mon, 17 Dec 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/12/17/a-handy-ruby-utility-belt/</guid>
          <link>http://rubypond.com/articles/2007/12/17/a-handy-ruby-utility-belt/</link>
        </item>
    
        <item>
          <title>New Error Handling in Rails 2.0</title>
          <description>&lt;p&gt;Rails 2.0 has added in a very cool way to trap errors without a bunch of messy nested rescue blocks or case statements.&lt;/p&gt;


&lt;p&gt;The ticket that added all the magic is &lt;a href=&quot;http://dev.rubyonrails.org/changeset/7597&quot; rel=&quot;nofollow&quot;&gt;here&lt;/a&gt;. And it couldn't come too soon as I immediately had a project that needed it. Check out what I was looking at doing:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class AccountsController &lt; ActionController::Base

  def rescue_action_in_public(exception)
    case exception
      when Account::Overdrawn
        flash[:error] = &quot;Sorry the account this transaction would make this account overdrawn&quot; 
        redirect_to account_path(params[:account])
      when Account::Suspended
        flash[:error] = &quot;Sorry the account you are trying to use has been suspended, please contact customer services&quot; 
        redirect_to account_path(params[:account])
      when ActiveRecord::RecordNotFound
        flash[:error] = &quot;No such account could be found&quot; 
        redirect_to user_path(current_user)
      else
        super
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and now with the new exception handling:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class AccountsController &lt; ActionController::Base
  rescue_from Account::Overdrawn, :with =&gt; :overdrawn
  rescue_from Account::Suspended, :with =&gt; :suspended
  rescue_from ActiveRecord::RecordNotFound, :with =&gt; :not_found

  protected
    def overdrawn
      flash[:error] = &quot;Sorry the account this transaction would make this account overdrawn&quot; 
      redirect_to account_path(params[:account])
    end

    def suspended
      flash[:error] = &quot;Sorry the account you are trying to use has been suspended, please contact customer services&quot; 
      redirect_to account_path(params[:account])
    end

    def not_found
      flash[:error] = &quot;No such account could be found&quot; 
      redirect_to user_path(current_user)
    end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;woohoo!! Much cleaner and more descriptive of my intentions&lt;/p&gt;</description>
          <pubDate>Thu, 13 Dec 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/12/13/new-error-handling-in-rails-2-0/</guid>
          <link>http://rubypond.com/articles/2007/12/13/new-error-handling-in-rails-2-0/</link>
        </item>
    
        <item>
          <title>Testing XML output in rspec and rails</title>
          <description>Have you ever tried testing that you get the expected XML output from your rails &lt;em&gt;respond_to&lt;/em&gt; block? Did you take the lazy way like me and think it would be as simple as comparing the body of the response with a string matching the expectant XML? Well there is a problem, if you've got multiple attributes on any elements you can't always guarantee the order that the attributes will be output. So lets do it properly, and check it is valid XML and has the attributes we want.


I was working on a project needed a graph of election results. The flash graphing object I was using required XML output, which was easy with an appropriate rails &lt;em&gt;respond_to&lt;/em&gt; block. However testing it wasn't as straight forward, or so I though initially.


After banging my head for an hour or so I realised that the built in &lt;em&gt;have_tag&lt;/em&gt; method and support for css selectors would give me everything I needed:


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../../spec_helper'

describe &quot;When viewing an election category as XML&quot; do

  include ModelHelpers

  before(:each) do
    @election = mock_model(Election, setup_election_helper)
    assigns[:election] = @election
    render 'election/show.xml.builder'
  end

  it &quot;should export valid XML for inclusing in flash charts&quot; do
    response.should have_tag(&quot;chart[caption='Test Election'][xAxisName='Nominee'][yAxisName='Votes']&quot;)
    response.should have_tag(&quot;chart set[value=100][label='nominee 1']&quot;)
    response.should have_tag(&quot;chart set[value=200][label='nominee 2']&quot;)
    response.should have_tag(&quot;chart set[value=200][label='nominee 3']&quot;)
    response.should have_tag(&quot;chart set[value=200][label='nominee 4']&quot;)
    response.should have_tag(&quot;chart set[value=200][label='nominee 5']&quot;)            
  end

end&lt;/code&gt;&lt;/pre&gt;

I'd dabbled with using hpricot to parse the output and traverse through the tree to ensure the elements are all where they should be, but this meets the requirements perfectly. However, it may be worth wrapping the hpricot methods in customer rspec matchers in the long term to make the assertions more readable. For the specific situation though (generating XML to meet the spec of a 3rd party app) I'm happy enough with the result.
          
</description>
          <pubDate>Mon, 10 Dec 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/12/10/testing-xml-output-in-rspec-and-rails/</guid>
          <link>http://rubypond.com/articles/2007/12/10/testing-xml-output-in-rspec-and-rails/</link>
        </item>
    
        <item>
          <title>Correctly handling multiple time zones in ruby on rails</title>
          <description>&lt;p&gt;A recent client I was working for had the unfortunate situation where we'd 
both independently assumed we understood the requirements, without realising
a missing piece of complexity. It was around time zones. The system was
implemented with a cut-off date being US EST, but most of their clientele
are in LA so it needed to be US PST. What is a developer to do?&lt;/p&gt;


&lt;p&gt;Well it turns out that &lt;a href=&quot;http://hackd.wordpress.com/2007/11/23/sexy-time-zones-in-ruby-on-rails-with-timezone_fu/&quot; rel=&quot;nofollow&quot;&gt;timezone_fu&lt;/a&gt; will come to the rescue.&lt;/p&gt;


&lt;h2&gt;Installing time zone support into your rails app&lt;/h2&gt;


&lt;p&gt;Getting timezone_fu working with an existing rails app is a cinch, the only
dependency is on the &lt;a href=&quot;http://tzinfo.rubyforge.org/&quot; rel=&quot;nofollow&quot;&gt;TZInfo&lt;/a&gt; package, so best you
grab that now:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;
sudo gem install tzinfo
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;And the install the plugin in your rails app:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;
./script/plugin install http://www.thrivesmart.com/open_source/timezone_fu
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Now before we do anything, make sure that we are defaulting to UTC time in 
&lt;em&gt;environment.rb&lt;/em&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ENV['TZ'] = 'UTC'&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Migrating your models so they know about time zones&lt;/h2&gt;


&lt;p&gt;Next, take your model that you want to apply your dates to. In my scenario it
was an election which had a start and end date for when voting could occur. First
thing I needed to do was to add a field to record the time zone that the dates
were to be handled in:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class AddTimezoneToElections &lt; ActiveRecord::Migration
  def self.up
    add_column :elections, :timezone, :string
  end

  def self.down
    remove_column :elections, :timezone
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then amend my model definition in &lt;em&gt;election.rb&lt;/em&gt; to add in the time zone 
helper:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class Election &lt; ActiveRecord::Base
  has_timezone :fields =&gt; [:start_at, :end_at], 
               :default_timezone =&gt; &quot;America/Los_Angeles&quot;,
               :time_format =&gt; &quot;%I:%M %p on %A %d %B %Y&quot; 
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Storing and retrieving time zones in your rails app&lt;/h2&gt;


&lt;p&gt;The wonderful thing about this setup is that dates saved or retrieved from the
model using the normal attribute accessors will displayed in the local time (as
determined by whatever you save in the timezone field). I've also used all of
the attributes to show their usage, but you can safely leave &lt;em cite=&quot;d&quot;&gt;efault_timezone&lt;/em&gt; and
&lt;em cite=&quot;t&quot;&gt;ime_format&lt;/em&gt; off if you desire. The latter is a strftime string format outlining
how to format the string, so we can get something like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; @election.display_end_at
=&amp;gt; &amp;quot;08:10 PM on Wednesday 20 February 2008&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately though the strftime method used by the &lt;em&gt;display_attribute&lt;/em&gt; helpers
still thinks that the timezone is in UTC format (I'll hopefully get around to a
patch shortly), so within my views to display the date with the timezone it is 
actually more like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&lt;%= &quot;#{@election.display_end_at} #{TZInfo::Timezone.get_proxy(@election.timezone).strftime(&quot;%Z&quot;)}&quot; %&gt;&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Thu, 06 Dec 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/12/06/correctly-handling-multiple-time-zones-in-ruby-on-rails/</guid>
          <link>http://rubypond.com/articles/2007/12/06/correctly-handling-multiple-time-zones-in-ruby-on-rails/</link>
        </item>
    
        <item>
          <title>Simplifying rails controllers with make_resourceful</title>
          <description>&lt;p&gt;See the content of the picture above? Wouldn't it be wonderful if you could reduce all of your controllers down to 3 lines? Well you can't do &lt;em&gt;all&lt;/em&gt; of them, but if you are adhering the a RESTful approach then chances are most of the controllers can be condensed considerably using &lt;a href=&quot;http://mr.hamptoncatlin.com/&quot;&gt;make_resourceful&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Firstly I have to thank &lt;a href=&quot;http://www.jeremymcanally.com/&quot; rel=&quot;nofollow&quot;&gt;Jeremy McAnally&lt;/a&gt; for putting me onto this wonderful new plugin for rails. He used it in a project we were working on together and I've used it almost everywhere since. It's from the Hampton Catlin who is also known for the excellent &lt;a href=&quot;http://haml.hamptoncatlin.com/&quot; rel=&quot;nofollow&quot;&gt;haml&lt;/a&gt; plugin/templating engine.&lt;/p.


&lt;h2&gt;So what is make_resourceful?&lt;/h2&gt;


&lt;p&gt;Basically it's an extension of rails to take &lt;em&gt;'convention over configuration'&lt;/em&gt; and &lt;em&gt;'don't repeat yourself'&lt;/em&gt; even further. If you're following a standard RESTful approach then make_resourceful takes care of almost all of the heavy lifting around interfacing with your models and loading them into instances.&lt;/p&gt;


&lt;h2&gt;What do you mean by 'standard RESTful approach'?&lt;/h2&gt;


&lt;p&gt;If your controllers are broken up into the index/show/update/create/edit/destroy methods and you are defining the route to them with &lt;em&gt;map.resources&lt;/em&gt; then you are in the right track. Chances are for you user controller you've got &lt;em&gt;index&lt;/em&gt; doing something like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;def index
  @users = User.find(:all)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and show doing something like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;def index
  @user = User.find(:id)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hampton was smart enough to realise many of us are doing exactly that on a lot of our controllers now, so why not just assume that is the case?&lt;/p&gt;


&lt;h2&gt;So what is the improvement in code?&lt;/h2&gt;


&lt;p&gt;Very quickly we can reduce the controller definition to be:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;make_resourceful do
    actions :index, :show   
  end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we've also got a method to create a new user, we can turn that on by simply:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;make_resourceful do
    actions :index, :show, :new, :create
  end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What about if we add in edit and update too? We actually want to support every action except for destroy. Well that is exactly what we specify then:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;make_resourceful do
    actions :all, :except =&gt; :destroy
  end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Can I handle nested routes?&lt;/h2&gt;


&lt;p&gt;Of course! And the wonderful thing is it's just as simple as what you've seen above:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class PostsController &amp;lt; ApplicationController
  make_resourceful do
    actions :index
    belongs_to :user
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will effectively do the following:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;@user = User.find(params[:user_id])
@posts = User.posts&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;What if I want to provide additional data to my find? Or instantiate additional objects for my views? Change the name of my instance?&lt;/h2&gt;


&lt;p&gt;There are a range of helper methods that make_resourceful sets up and uses that can be overridden on a per controller basis. The key ones to look at are listed in the &lt;a href=&quot;http://mr.hamptoncatlin.com/classes/Resourceful/Default/Accessors.html&quot; rel=&quot;nofollow&quot;&gt;RDocs for Default:Accessors&lt;/a&gt;. You also still have access to all the same before and after filters that you normally have in your controllers.&lt;/p&gt;


&lt;h2&gt;I'm sold, how do I install it?&lt;/h2&gt;


&lt;p&gt;As it's a standard rails plugin, installation is the usual way:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ruby script/plugin install http://svn.hamptoncatlin.com/make_resourceful/trunk
mv vendor/plugins/trunk vendor/plugins/make_resourceful&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure you run the last step, otherwise you'll have make resourceful exported into &lt;em&gt;vendor/plugins/trunk&lt;/em&gt; rather than &lt;em&gt;vendor/plugins/trunk&lt;/em&gt;.&lt;/p&gt;


&lt;h2&gt;Be careful! It is no silver bullet&lt;/h2&gt;


&lt;p&gt;I've quickly come to realise that make resourceful is great for getting very simple controllers out the door quickly. What it is not however is a complete replacement for ActionController. There will be times where the number of before filters and hacks you have to accommodate to get your controller working means you're better off refactoring the code back into a more traditional approach. However, even in these scenarios it's a great way to quickly define the specs and get you to a point where you can put the application through usability testing while cleaning up the mess afterwards.&lt;/p&gt;</description>
          <pubDate>Tue, 27 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/27/simplifying-rails-controllers-with-make_resourceful/</guid>
          <link>http://rubypond.com/articles/2007/11/27/simplifying-rails-controllers-with-make_resourceful/</link>
        </item>
    
        <item>
          <title>Top 5 usability and design principles in web site development</title>
          <description>Many clients I work with today have come from a wealth of experience in other media formats, be it the big screen or traditional print. They often bring with them a pre-conceived notion of how they want things to look and work on the site. Quite often it is a direct translation of their existing media strategies and they want to keep the content and format consistent for the sake of 'branding'.


The web however is a fundamentally different beast than most mediums due to both the way the user interacts with it and the immensely broad reach. So a slightly different approach is needed. Pay attention to these things, and you'll ultimately end up with a happier audience and happier clients.


&lt;h2&gt;Users want instant gratification&lt;/h2&gt;


There is nothing worse than clicking a link and waiting 10 seconds for a response. Back in the early days this was the norm, but now that content is delivered near instantly an expectation is set. Don't make them endure a long download just to show them a doorway flash page into your site, or some new animated navigation bar. Likewise with operations you now may take a while to process such as a search or uploading and processing of data. Where possible, push long running operations into a background process if the user doesn't need to immediately see the results. Where they do, provide the illusion of a partial instant response with a &lt;a href=&quot;http://ajaxload.info/&quot;&gt;progress indicator&lt;/a&gt;


&lt;h2&gt;3 it's the magic (click) number&lt;/h2&gt;


(... with apologies to &lt;a href=&quot;http://www.schoolhouserock.tv/Three.html&quot; rel=&quot;nofollow&quot;&gt;schoolhouse rock&lt;/a&gt;). An old one from back in the day that still holds up in some regards today. And even for those naysayers that believe things are different, I've not heard a valid reason as to why should strive to meet this objective so long as it doesn't conflict with any others listed here. That is, make sure that whatever the user wants to do or find is never more than 3 clicks away. Beyond that point you run the risk of the user becoming frustrated and using that little Google search box in the top of their browser to find somewhere other than your site to get what they want.


And think about it, if you're using a traditional desktop application how often do you need more than 3 clicks to do anything within it? Menu bar &gt; Option &gt; Tool panel. File &gt; Open &gt; Select File. And online? Go to Amazon &gt; Find Book &gt; 1-click order.


It won't always be possible with absolutely &lt;em&gt;every&lt;/em&gt; site, but you should try and make most adhere to it.


&lt;h2&gt;Make sure your elements Fitts&lt;/h2&gt;


&lt;a href=&quot;http://en.wikipedia.org/wiki/Fitts'_law&quot; rel=&quot;nofollow&quot;&gt;Fitts's Law&lt;/a&gt; is from the wikipedia article:  &lt;em&gt;&quot;a model of human movement which predicts the time required to rapidly move to a target area, as a function of the distance to the target and the size of the target'&lt;/em&gt;. Basically what that means is that the bigger and more obvious you can make the areas you want someone to click, the easier it will be. Seems obvious right? Take a read through &lt;a href=&quot;http://www.asktog.com/columns/022DesignedToGiveFitts.html&quot; rel=&quot;nofollow&quot;&gt;this quiz over at AskTog&lt;/a&gt; for some insight into how what otherwise seems like common-sense, isn't that sensible at all. Suffice to say, you really need to pay more attention to when you place a 'buffer zone' around your objects, and when you flush things hard against the screen.


&lt;h2&gt;Make it as simple as possible, and no simpler&lt;/h2&gt;


&lt;a href=&quot;http://www.musanim.com/miller1956/&quot; rel=&quot;nofollow&quot;&gt;Psychological studies&lt;/a&gt; have raised a theory that the human brain is usually only capable of handling around 7 pieces of stimulus at a time. If you are wanting to maximise reader engagement, or improve your click through rates, the best thing to do is reduce the number of options they have to deal with at any given point in time. That goes for navigation, filling in forms, etc. Start pushing past 10 items unless it's absolutely needed or expected and you starting walking the fine line to sensory overload.


&lt;h2&gt;Summarise your content&lt;/h2&gt;


This fits in nicely with the expectation of instant gratification. Meaningful headlines and a first paragraph that acts almost like a conclusion or executive summary, giving the outcome of the following text allows the user to quickly determine if the content is appropriate. At the end of the day, you don't want to falsely lure users into sections they won't find relevant.
</description>
          <pubDate>Fri, 23 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/23/top-5-usability-and-design-principles-in-web-site-development/</guid>
          <link>http://rubypond.com/articles/2007/11/23/top-5-usability-and-design-principles-in-web-site-development/</link>
        </item>
    
        <item>
          <title>Engine Yard Bounty Pays Off</title>
          <description>&lt;p&gt;&lt;a href=&quot;http://www.engineyard.com/&quot; rel=&quot;nofollow&quot;&gt;Engine Yard&lt;/a&gt;, the current big daddy of rails hosting, decided to put a bounty out to solve a problem all the newly converted rails/nginx users would have to some degree but have previously been ignoring. The load balancer in nginx works in a round robin fashion meaning that any long running request has the potential to cause another user to queue behind it, rather than getting served by one of the free and waiting mongrels. Well wait no more!&lt;/p&gt;


&lt;p&gt;Take a look at &lt;a href=&quot;http://www.brainspl.at/articles/2007/11/09/a-fair-proxy-balancer-for-nginx-and-mongrel&quot; rel=&quot;nofollow&quot;&gt;Ezra's blog&lt;/a&gt; for the most definitive run down on how to get it working for you, but the digest version goes a little something like this.&lt;/p&gt;


&lt;p&gt;Download the optional module tarball from &lt;a href=&quot;http://git.localdomain.pl/?p=nginx.git;a=snapshot;hb=upstream_fair-0.6&quot; rel=&quot;nofollow&quot;&gt;nginx fair proxy balancer&lt;/a&gt; and then do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd nginx.git
./configureâwith-http_ssl_module
make
sudo make install&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that you've compiled with the new module all that is left to update your upstream &lt;em&gt;nginx.conf&lt;/em&gt; to include the fair directive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;upstream mongrel {
fair;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/pre&gt;
</description>
          <pubDate>Wed, 21 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/21/engine-yard-bounty-pays-off/</guid>
          <link>http://rubypond.com/articles/2007/11/21/engine-yard-bounty-pays-off/</link>
        </item>
    
        <item>
          <title>Reject junk email addresses with email veracity</title>
          <description>&lt;p&gt;Carsten Nielsen has created an amazing plugin for rails called &lt;a href=&quot;http://rails.savvica.com/2007/11/6/email-veracity-plugin&quot; rel=&quot;nofollow&quot;&gt;email veracity&lt;/a&gt;. It takes all of the heavy lifting out of what can often be a problematic part of data validation, and takes it a step further than most.&lt;/p&gt;

&lt;p&gt;Not only does email veracity remove the need for a convoluted regexp to match against the email string, but it will also check the domain records to ensure that the MX entry is currently accepting mail, wow!&lt;/p&gt;

&lt;h2&gt;So how do I check the format of an email address?&lt;/h2&gt;

&lt;p&gt;Add this to the code on your model definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;validates_email_veracity_of :email&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;that single line does the domain check too! You can turn it off, apply a timeout, and/or a custom error message if you like too:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;validates_email_veracity_of :email, :domain_check =&gt; false, :timeout =&gt; 5, :message =&gt; &quot;is not valid&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;It's available as a plugin so use piston, or the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;script/plugin install http://svn.savvica.com/public/plugins/validates_email_veracity_of&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Tue, 20 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/20/reject-junk-email-addresses-with-email-veracity/</guid>
          <link>http://rubypond.com/articles/2007/11/20/reject-junk-email-addresses-with-email-veracity/</link>
        </item>
    
        <item>
          <title>Trap rails from sending mail via SMTP</title>
          <description>&lt;p&gt;Trap rails from sending mail via SMTP  &lt;a href=&quot;http://matt.blogs.it/entries/00002655.html&quot; rel=&quot;nofollow&quot;&gt;Matt Mower&lt;/a&gt; has released a handy little tool called &lt;a href=&quot;http://rubymatt.rubyforge.org/mailtrap/&quot; rel=&quot;nofollow&quot;&gt;Mailtrap&lt;/a&gt;. Basically what it does as act as a very simple SMTP server that accepts requests from ActionMailer, but writes them to file instead of emailing them on.&lt;/p&gt;

&lt;p&gt;Installation is very straight forward:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install -y mailtrap&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then start it up:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mailtrap start&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which will start the mailtrap app to listen on port 2525. Now all that is left to do is change the config in your rails app to connect to localhost:2525 in either &lt;em&gt;/config/environment.rb&lt;/em&gt; or &lt;em&gt;/config/environment/development.rb&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  :domain =&gt; &quot;mydomain.net&quot;,
  :address =&gt; &quot;localhost&quot;,
  :port =&gt; 2525,
}&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Fri, 16 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/16/trap-rails-from-sending-mail-via-smtp/</guid>
          <link>http://rubypond.com/articles/2007/11/16/trap-rails-from-sending-mail-via-smtp/</link>
        </item>
    
        <item>
          <title>Ebay launches rails app</title>
          <description>&lt;p&gt;Not that there haven't already been high profile players talking about ruby and rails, but Ebay have just recently launched own rails app called &lt;a href=&quot;https://www.microplace.com/&quot; rel=&quot;nofollow&quot;&gt;MicroPlace&lt;/a&gt;. It's a micro-donation site like Kiva where you can invest directly into those in the 3rd world and help them escape the poverty cycle.&lt;/p&gt;</description>
          <pubDate>Mon, 12 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/12/ebay-launches-rails-app/</guid>
          <link>http://rubypond.com/articles/2007/11/12/ebay-launches-rails-app/</link>
        </item>
    
        <item>
          <title>PrototypeJS adds better OO support</title>
          <description>&lt;p&gt;The folks over at &lt;a href=&quot;http://prototypejs.org/&quot; rel=&quot;nofollow&quot;&gt;prototype&lt;/a&gt; have had their latest 1.6 release in beta for a while, and I was using it quite extensively with much joy at my last client. One of the major enhancements to the entire system has been the reworking of the Element and Object classes, and the underlying Class object.&lt;/p&gt;


&lt;p&gt;Previously there was all kinds of nastiness when trying to define a custom class. Here's an example taken from the docs:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;var Person = Class.create();
Person.prototype = {
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
};

var guy = new Person('Miro');
guy.say('hi');
// -&gt; &quot;Miro: hi&quot; 

var Pirate = Class.create();
// inherit from Person class:
Pirate.prototype = Object.extend(new Person(), {
  // redefine the speak method
  say: function(message) {
    return this.name + ': ' + message + ', yarr!';
  }
});

var john = new Pirate('Long John');
john.say('ahoy matey');
// -&gt; &quot;Long John: ahoy matey, yarr!&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But now with the improved Class constructor much of that heavy lifting can be put straight into the Class.create(). Then Pirate can be defined with something that looks more akin  to proper object inheritance as opposed to extending the object. The end result is cleaner and more readable code:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;// properties are directly passed to `create` method
var Person = Class.create({
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
});

// when subclassing, specify the class you want to inherit from
var Pirate = Class.create(Person, {
  // redefine the speak method
  say: function($super, message) {
    return $super(message) + ', yarr!';
  }
});

var john = new Pirate('Long John');
john.say('ahoy matey');
// -&gt; &quot;Long John: ahoy matey, yarr!&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is just one of the many improvements in the API, some of the others are equally outstanding. I can't recommend enough the 1.6 release and I've had no problems with it, so checkout &lt;a href=&quot;http://prototypejs.org/2007/11/7/prototype-1-6-0-script-aculo-us-1-8-0-and-the-bungee-book-now-available&quot; rel=&quot;nofollow&quot;&gt;the release notes&lt;/a&gt; and get cracking with it today!&lt;/p&gt;
</description>
          <pubDate>Thu, 08 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/08/prototypejs-adds-better-oo-support/</guid>
          <link>http://rubypond.com/articles/2007/11/08/prototypejs-adds-better-oo-support/</link>
        </item>
    
        <item>
          <title>google, social networking</title>
          <description>&lt;p&gt;Sorry about the lull in posts of late all. I've been busy traveling and catching up on much lost quality time with my girlfriend who has returned from Australia. Big news today though, with Google looking to taken on the Facebook Application juggernaut with their own API.&lt;/p&gt;

&lt;p&gt;With what sounds like it could be a master stroke of Google can pull it off correctly, they are development a social network agnostic API for applications and then trying to get all the various sites on board to support it. So no longer would the likes of &lt;a href=&quot;http://www.slide.com/&quot; rel=&quot;nofollow&quot;&gt;Slide&lt;/a&gt; have to develop their apps for Myspace, and then again for Facebook. It'd be once for OpenSocial and the deploy anywhere.&lt;/p&gt;

&lt;p&gt;I can see the obvious parallels between this and Java with the 'write once, deploy everywhere' philosophy but I wonder how successful it will ultimately be. As appealing as it is for myself and other developer folk, it won't be us developers that are deciding where the critical mass of eyeballs decide to sign up. If Facebook maintain their own platform and it ends up a two horse race between them and another player, then it makes this kind of platform pointless as I'd still have to write the application twice.&lt;/p&gt;

&lt;p&gt;Hopefully this is one of those situations where the size and credibility of Google helps pull it altogether. &lt;a href=&quot;http://code.google.com/apis/opensocial/&quot; rel=&quot;nofollow&quot;&gt;Go take a look&lt;/a&gt; once the site goes live.&lt;/p&gt;</description>
          <pubDate>Fri, 02 Nov 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/11/02/google-social-networking/</guid>
          <link>http://rubypond.com/articles/2007/11/02/google-social-networking/</link>
        </item>
    
        <item>
          <title>Securing SSH access</title>
          <description>&lt;p&gt;So you've got a shiny new server, it's connected to the net, and you (or your hosting company) has done the right thing by turning telnet off and forcing the much more secure option of using SSH to connect. But it doesn't end there, there are quite a few little things you can do to further tighten access and keep the boogey men at bay.&lt;/p&gt;


&lt;h2&gt;Setting up the server&lt;/h2&gt;


&lt;p&gt;First things first, lets move it off the default port 22. So many scripted and brute force attacks will try and blast at the defaults, and your memory isn't &lt;strong&gt;that&lt;/strong&gt; bad that you have to stick with them. So pick a number, and edit/update the &lt;b&gt;/etc/ssh/sshd_config&lt;/b&gt; file to have the following line:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Port 1022&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, remove the legacy support for the less secure SSH1 protocol in favor of the newer more robust SSH2 protocol:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Protocol 2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You've already &lt;a href=&quot;http://rubypond.com/articles/2007/08/27/adding-yourself-to-the-sudoers-file/&quot;&gt;created a user and added yourself to sudoers&lt;/a&gt;, so there is no need for the &lt;b&gt;root&lt;/b&gt; user to log in directly. Time to disable that. While we are at it, lets stop brute force attacks by reducing the number of incorrect attempts a user gets:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PermitRootLogin no
MaxAuthTries 2&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Now onto the client&lt;/h2&gt;

&lt;p&gt;We can remove the need to enter our server password all the time by pushing our public key onto the server and using that to authenticate. If you already have a public/private key combination you can ignore this next step.&lt;/p&gt;

&lt;p&gt;Creating your public/private keys is very straight forward on linux and mac, on windows you'll need to get putty. From the command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ssh-keygen -t dsa&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will prompt you for some questions and a passphrase, the default options will be fine. The keys will be saved to &lt;em&gt;~/.ssh/&lt;/em&gt;, so now we will move the contents of the public key up to the server.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat ~/.ssh/id_dsa.pub | ssh username@server &quot;cat &gt;&gt; .ssh/authorized_keys&quot; 
ssh username@server chmod 600 .ssh/authorized_keys&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Be sure to replace &lt;em&gt;username&lt;/em&gt; and &lt;em&gt;server&lt;/em&gt; with the appropriate values for the server we are setting up. Now you should be free to SSH onto the server, without a password!&lt;/p&gt;

&lt;h2&gt;Back to the server&lt;/h2&gt;

&lt;p&gt;Now that you don't need a password to get into the server, we can prevent people from trying to use one. We can also restrict the users that are permitted to access while we are at it. So back into &lt;em&gt;/etc/ssh/sshd_config&lt;/em&gt; and update/edit the following lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PasswordAuthentication no
ChallengeResponseAuthentication no
AllowUsers username&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again being sure to change &lt;em&gt;username&lt;/em&gt; to your username. Additional users can be entered, separated with a space. All done and dusted? Restart the SSH daemon:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo /etc/init.d/sshd reload&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Tue, 04 Sep 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/09/04/securing-ssh-access/</guid>
          <link>http://rubypond.com/articles/2007/09/04/securing-ssh-access/</link>
        </item>
    
        <item>
          <title>Installing Memcached</title>
          <description>&lt;p&gt;Memcached is an alternative to database storage that is often useful for session storage and caching. It was developed by the guys at live journal to help them maintain their unwieldy sessions. Since then it's gained a lot of popularity among the PHP and Rails folk because it removes some of the burden on the typical database bottle neck, and allows things like session to be maintained across a cluster of servers.&lt;/p&gt;

&lt;p&gt;First things first, you're going to need to download and make the source for libevent, which memcached has a dependency on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://www.monkey.org/~provos/libevent-1.3d.tar.gz
tar zxf libevent-1.3d.tar.gz
cd libevent-1.3d
./configure --prefix=/usr/local
make; sudo make install; make clean;
cd ..&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once that is done, you're ready to get onto the setup and install of memcached itself:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://www.danga.com/memcached/dist/memcached-1.2.2.tar.gz
tar zxf memcached-1.2.2.tar.gz
cd memcached-1.2.2
./configure --with-libevent=/usr/local/lib --prefix=/usr/local
make; sudo make install; make clean;
sudo /sbin/ldconfig /usr/local/lib
cd ..&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then finally, the ruby client interface:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install memcache-client -y&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once that is installed, moving over your session store to use memcached is a breeze, simply change the setting in your environment.rb file to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.action_controller.session_store = :mem_cache_store&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Mon, 03 Sep 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/09/03/installing-memcached/</guid>
          <link>http://rubypond.com/articles/2007/09/03/installing-memcached/</link>
        </item>
    
        <item>
          <title>Installing Subversion and MySQL</title>
          <description>&lt;p&gt;I first got &lt;em&gt;forced&lt;/em&gt; into using source control management (scm) systems when I first began working as part of a team of developers and there was times we'd need to edit the same parts of the system. It wasn't too long until those good habits trickled into the stuff I worked on by myself, and for good reason. It's nice to always have an undo option for those time when you go &quot;Whoops!&quot;. Subversion (SVN to some) is the version control tool du jour for many, so lets keep it simple to begin with and start with that. I've included installing MySQL and Postgres as well, because well it's version control and databases finish off what you need to have your app deployed; and because they are all pretty straight-forward&lt;/p&gt;


&lt;h2&gt;Installing Subversion&lt;/h2&gt;


&lt;p&gt;So first subversion. We will go get the subversion source, the dependencies package (zlib compression support, support for http(s):// repositories, etc), and then configure and install:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://subversion.tigris.org/downloads/subversion-1.4.5.tar.gz
wget http://subversion.tigris.org/downloads/subversion-deps-1.4.5.tar.gz
tar zxf subversion-1.4.5.tar.gz
tax zxf subversion-deps-1.4.5.tar.gz
cd subversion-1.4.5
./autogen.sh
./configure --prefix=/usr/local --with-openssl --with-ssl=openssl
make; sudo make install; make clean;
cd ..&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installing MySQL&lt;/h2&gt;


&lt;p&gt;Now it's time for MySQL. You'll need to ensure you've got the g/c++ libraries installed for this one:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;wget http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-5.0.45.tar.gz/from/http://www.mirrorservice.org/sites/ftp.mysql.com/
tar zxf mysql-5.0.45.tar.gz
cd mysql-5.0.45
./configure --prefix=/usr/local
make; sudo make install; make clean;
./scripts/mysql_install_db
sudo cp support-files/mysql.server /etc/init.d/mysql
sudo chmod 755 /etc/init.d/mysql
sudo /sbin/chkconfig --level 345 mysql on
sudo /usr/sbin/adduser mysql -r
sudo chown -R root:mysql /usr/local/mysql
sudo chown -R mysql:mysql /usr/local/mysql/var
sudo cp support-files/my-medium.cnf /etc/my.cnf
cd ..&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;MySQL has just been installed, the standard tables populated, permissions, users, and configs have been setup and it is set to start itself on start-up/reboot. Now you'll need to issue a secure root password to the new server, so run the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/usr/local/bin/mysqladmin -u root password 'new-password'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Replacing &lt;em&gt;new-password&lt;/em&gt; with whatever you'd like your secure password to be. Once that is all done, start up the service manually as the mysql user:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;sudo /usr/local/mysql/bin/safe_mysqld --user=mysql &amp;amp;&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Thu, 30 Aug 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/08/30/installing-subversion-and-mysql/</guid>
          <link>http://rubypond.com/articles/2007/08/30/installing-subversion-and-mysql/</link>
        </item>
    
        <item>
          <title>Installing Ruby, Rails, and Rubygems</title>
          <description>&lt;p&gt;Getting your first ruby on rails stack up and running can be a bit of a chore, here&amp;#8217;s a quick guide on how to do it on a linux box but the instructions should be equally good for OS X users.&lt;/p&gt;

&lt;h2&gt;Installing Ruby&lt;/h2&gt;

&lt;p&gt;Now depending on your OS, you&amp;#8217;ve got a few options on how to get ruby up and running. The easiest way is to use the built-in package management system. This will give you the latest known stable version of ruby for your environment, and hopefully reduce or remove any potential conflicts with other installed software. The downside is that quite often the packaged version are a few releases behind the currently advertised stable version just due to the time it takes for the linux distribution manages to bundle them up.&lt;/p&gt;

&lt;h3&gt;Installing Ruby from yum/apt-get&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;ve got a package manager, just enter whichever of the following commands is the most appropriate:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo yum install ruby irb rdoc ruby-devel
sudo apt-get ruby irb rdoc ruby-devel&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Installing Ruby from Source&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;ve decided to take the from source option, then you&amp;#8217;ll need to do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz
tar zxvf ruby-1.8.7-p72.tar.gz
cd ruby-1.8.7-p72
./configure
make
sudo make install&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installing ruby gems&lt;/h2&gt;

&lt;p&gt;Gem is the package system for ruby, and it&amp;#8217;s the easiest way to install most of your ruby dependencies (including rails). So grab it from sourceforge:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget http://rubyforge.org/frs/download.php/43985/rubygems-1.3.0.tgz
tar zxvf rubygems-1.3.0.tgz
cd rubygems-1.3.0
sudo ruby ./setup.rb&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Installing Ruby on Rails&lt;/h2&gt;

&lt;p&gt;Now getting rails installed is a breeze, all you need to do is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install rails&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may need to install your native database driver bindings too, if so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install mysql
sudo gem install postgres&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Tue, 28 Aug 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/08/28/installing-ruby-rails-and-rubygems/</guid>
          <link>http://rubypond.com/articles/2007/08/28/installing-ruby-rails-and-rubygems/</link>
        </item>
    
        <item>
          <title>Adding yourself to the sudoers file</title>
          <description>&lt;p&gt;If you&amp;#8217;ve gone at least some way to trying to make your server secure, you wont be running as root so you wont have access to many of the administration commands you&amp;#8217;ll need. It&amp;#8217;s easily resolved by adding yourself to the sudoers file, here&amp;#8217;s a quick guide on how to do it.&lt;/p&gt;

&lt;h2&gt;Giving a user access to sudo&lt;/h2&gt;

&lt;p&gt;Unless you&amp;#8217;ve already got an account with sudo access, you&amp;#8217;re going to need to log in as root one last time to set one up. So do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;su -&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And enter in the password for root when prompted. Next we&amp;#8217;ll edit the sudoers file using &lt;em&gt;visudo&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;visudo&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will open up the file in a vi session for editing. If you&amp;#8217;ve not got crazy vi chops don&amp;#8217;t worry, were don&amp;#8217;t need to do anything complicated. Just page down to the bottom of the document and enter the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;your_username_here ALL=(ALL)       ALL&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hit &lt;em&gt;esc&lt;/em&gt; then type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:wq&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and press &lt;em&gt;ENTER&lt;/em&gt;. The file will be saved, and you&amp;#8217;ve just granted yourself access to run everything as the root user. Now type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;exit&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to log out as root and back in as yourself. Now if we want to edit the sudoers file we can do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo visudo&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this time when you are prompted for a password, you only need to enter your own one. And tada, the sudoers file is open again. Now let&amp;#8217;s give some more users access, but we won&amp;#8217;t be quite so generous with what they can do.&lt;/p&gt;

&lt;h2&gt;Giving a user access to a single command&lt;/h2&gt;

&lt;p&gt;What about on a production machine where you&amp;#8217;ve got a user that is a little bit trusted, but shouldn&amp;#8217;t be given total access to the system? It quite easy to setup some walled access to the commands you need to open up. In the example below, we will grant access to &lt;em&gt;god&lt;/em&gt; for the user &lt;em&gt;deploy&lt;/em&gt; so that we can start and stop our services through capistrano.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;deploy  ALL= /usr/bin/god&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Sudo command line howto&lt;/h2&gt;

&lt;p&gt;How about running a command as another user, without changing to that user? Simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo -u otheruser /usr/bin/command&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or running a command and pushing it to the background:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo -b /usr/bin/command&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or just finding out what commands you are allowed to run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo -l&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Sudo config (more detailed sudoers file options)&lt;/h2&gt;

&lt;p&gt;The sudoers file offers quite a lot of control over exactly what someone can run, as well as who they can run it as, and from where. Let&amp;#8217;s just quickly run through a few of the other options you&amp;#8217;ve got in the sudoers file:&lt;/p&gt;

&lt;h3&gt;Restricting who a user can run commands as&lt;/h3&gt;

&lt;p&gt;The following snippet allows the user &lt;em&gt;bob&lt;/em&gt; to run all commands from anywhere, but only as alice or anne:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RunAs_Alias     HELPDESK = alice, anne
bob ALL=(HELPDESK) ALL&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Restricting where a user can run commands from&lt;/h3&gt;

&lt;p&gt;This config allows &lt;em&gt;bob&lt;/em&gt; to run any command as any user, but only from the defined subnet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host_Alias     MYNET = 10.1.2.0/255.255.255.0
bob MYNET=(ALL) ALL&lt;/code&gt;&lt;/pre&gt;</description>
          <pubDate>Mon, 27 Aug 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/08/27/adding-yourself-to-the-sudoers-file/</guid>
          <link>http://rubypond.com/articles/2007/08/27/adding-yourself-to-the-sudoers-file/</link>
        </item>
    
        <item>
          <title>Installing Apache 2.2.4</title>
          <description>&lt;p&gt;Working for various clients and deploying a full working rails stack on their hardware and environments is not always as straight-forward and easy as it should be. What distribution are they using? Which package manager? Does the package manager even currently have the right versions I need? So over the coming days I&amp;#8217;m going to write a few tutorials on getting the latest software, from source, and compiling it. So intro today, with &lt;a href=&quot;http://httpd.apache.org/&quot; rel=&quot;nofollow&quot;&gt;Apache&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The only assumption I make is that &lt;a href=&quot;http://gcc.gnu.org/&quot; rel=&quot;nofollow&quot;&gt;gcc&lt;/a&gt; is available on the system so the we can compile the source into binaries. If you don&amp;#8217;t have it, you&amp;#8217;ll need to install it for your system. So the first thing to do is download the latest unix source from a &lt;a href=&quot;http://httpd.apache.org/download.cgi&quot; rel=&quot;nofollow&quot;&gt;local mirror&lt;/a&gt; and save it somewhere convenient. To make life easier, I&amp;#8217;m going to download all the files directly to the server using wget. So it&amp;#8217;s simply a matter of:&lt;/p&gt;


&lt;pre&gt;
&lt;code class=&quot;console&quot;&gt;
mkdir rails-setup
cd rails-setup
wget http://www.apache.org/dist/httpd/httpd-2.2.4.tar.gz
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;But before we get too far ahead of ourselves, I know that I&amp;#8217;m going to want to add in the ability to compress output I&amp;#8217;m sending back to the end user, as well as support for &lt;span class=&quot;caps&quot;&gt;HTTPS&lt;/span&gt;/SSL. So I&amp;#8217;m going to need those libraries too. Lets go get them:&lt;/p&gt;


&lt;pre&gt;
&lt;code class=&quot;console&quot;&gt;
wget http://switch.dl.sourceforge.net/sourceforge/libpng/zlib-1.2.3.tar.gz
wget http://www.openssl.org/source/openssl-0.9.8e.tar.gz
&lt;/code&gt;
&lt;/pre&gt;
And tada! We&amp;#8217;ve hopefully got all we need. Time to compile.

&lt;pre&gt;
&lt;code class=&quot;console&quot;&gt;
tar zxf zlib-1.2.3.tar.gz 
cd zlib-1.2.3
./configure --prefix=/usr/local
make; sudo make install; make clean;
cd ..
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;So what have we just? We&amp;#8217;ve grabbed the &lt;a href=&quot;http://www.zlib.net/&quot; rel=&quot;nofollow&quot;&gt;zlib&lt;/a&gt; tarball and extracted and decompressed it into it&amp;#8217;s own directory. We then go in there, and run &lt;em&gt;./configure&lt;/em&gt; to ensure it is setup for our environment. Then we run make, install it once it&amp;#8217;s done, and then clean up the leftovers.&lt;/p&gt;


	&lt;p&gt;Time to do the same with &lt;a href=&quot;http://www.openssl.org/&quot; rel=&quot;nofollow&quot;&gt;OpenSSL&lt;/a&gt;.&lt;/p&gt;


&lt;pre&gt;
&lt;code class=&quot;console&quot;&gt;
tar zxf openssl-0.9.8e.tar.gz
cd openssl-0.9.8e
./config --prefix=/usr/local
make; sudo make install; make clean;
cd ..
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Okay, now we should be ready for Apache. Here&amp;#8217;s the next series of commands I typically run:&lt;/p&gt;


&lt;pre&gt;
&lt;code class=&quot;console&quot;&gt;
tar zxf httpd-2.2.4.tar.gz
cd httpd-2.2.4
./configure --enable-mods-shared=all --enable-proxy --enable-proxy-balancer --enable-proxy-http --enable-rewrite --enable-cache --enable-headers --enable-ssl --enable-deflate --with-included-apr --with-ssl=/usr/local/ssl --prefix=/usr/local/apache2
make; sudo make install; make clean;
cd ..
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;So what we&amp;#8217;ve done is run the configure script to set things up for the current environment, letting make know that we want to enable&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Mod proxy (so we can send requests through to mogrel/rails)&lt;/li&gt;
		&lt;li&gt;Mod proxy balancer (so that we can distribute to various mongrel instances)&lt;/li&gt;
		&lt;li&gt;Enabled proxy support (need it to pass requests to mod proxy)&lt;/li&gt;
		&lt;li&gt;Turn on &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; re-writing (so we can handle rails routing)&lt;/li&gt;
		&lt;li&gt;Enable dynamic file caching&lt;/li&gt;
		&lt;li&gt;Let us take control of the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; headers&lt;/li&gt;
		&lt;li&gt;Turn on support for &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;/TLS (nice and secure)&lt;/li&gt;
		&lt;li&gt;Turn on support for deflate transfer encoding (helps keep the transfer size down)&lt;/li&gt;
		&lt;li&gt;The location of the OpenSSH installation&lt;/li&gt;
		&lt;li&gt;The location where we want to install Apache&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;It will then run through, compile all the code, install it on the server, and clean up it&amp;#8217;s mess it might have left behind.&lt;/p&gt;


	&lt;p&gt;And there you have it! Apache is setup, and should be working and running on your server. Over the coming days I&amp;#8217;ll post further instruction on getting the rest of the stack running. That is going to entail MySQL and/or Postgres, ruby, rails, mongrel, mongrel_cluster, and monit for managing the services and starting/stopping everything. And of course, the various configuration that is required to make it all talk together.&lt;/p&gt;


	&lt;p&gt;You could also delete the files we downloaded and the directories we installed from because our work here is done. I personally keep them around at least until everything is working together and the system is stable, but it&amp;#8217;s up to you.&lt;/p&gt;
</description>
          <pubDate>Mon, 27 Aug 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/08/27/installing-apache-2-2-4/</guid>
          <link>http://rubypond.com/articles/2007/08/27/installing-apache-2-2-4/</link>
        </item>
    
        <item>
          <title>Welcome To The New Location</title>
          <description>&lt;p&gt;Well it has been quite a while in the making, but I&amp;#8217;ve finally decided to go it out on my own. After taking a few months off traveling and to head home and visit friends and family I&amp;#8217;ve relocated back to the UK and consolidated my various freelance and investment interests across continents into a single company, Ruby Pond. That&amp;#8217;s not to say I&amp;#8217;ve not been busy working. There are a number of projects which I&amp;#8217;ve been working on, for both external clients and personal ventures. Hopefully a steady stream of them will start coming out the virtual doors in the coming weeks, so stay tuned.&lt;/p&gt;

&lt;p&gt;Until then, expect this blog to be my geek soap box for anything related to the various facets of of my business and random learnings. For my on-going travel diaries from my newly bedouin lifestyle or to hear what my other half has to say check out the updates (when we actually get around to them) at &lt;a href=&quot;http://www.emandglenn.com/&quot; rel=&quot;nofollow&quot;&gt;Em and glenn&lt;/a&gt;&lt;/p&gt;</description>
          <pubDate>Sat, 11 Aug 2007 09:00:00 GMT</pubDate>
          <guid>http://rubypond.com/articles/2007/08/11/welcome-to-the-new-location/</guid>
          <link>http://rubypond.com/articles/2007/08/11/welcome-to-the-new-location/</link>
        </item>
    
    
  </channel>
</rss>

