<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:lindsaar.net,2007:/feed</id>
  <link rel="alternate" type="text/html" href="http://lindsaar.net"/>
  <link rel="self" type="application/atom+xml" href="http://lindsaar.net/feed.atom"/>
  <author>
    <name>Mikel Lindsaar</name>
    <email>mikel@lindsaar.net</email>
  </author>
  <title>lindsaar.net - a different view</title>
  <updated>2013-11-06T01:05:02+00:00</updated>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails-security-alert</id>
    <published>2013-01-10T06:20:28+00:00</published>
    <updated>2013-01-10T06:20:28+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails-security-alert"/>
    <title>Rails Security Alert</title>
    <content type="html">
&lt;p&gt;Rails has just had a rather nasty security alert, get your application upgraded now.  If you know what you are doing, you can follow the instructions inside of the &lt;a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ"&gt;Security Alert notes&lt;/a&gt;, if you don&amp;#8217;t, then you can get an &lt;a href="http://reinteractive.net/service/secure"&gt;fixed price upgrade service&lt;/a&gt; from reInteractive.  But whatever you do, do it soon.&lt;/p&gt;     </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/Encrypting-Another-Partition-Using-FileVault-2-on-OSX-Lion</id>
    <published>2011-08-06T12:10:00+00:00</published>
    <updated>2011-08-06T12:10:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/Encrypting-Another-Partition-Using-FileVault-2-on-OSX-Lion"/>
    <title>Encrypting Another Partition Using FileVault 2 on OSX Lion</title>
    <content type="html">
&lt;p&gt;After installing a second drive with my home folder on it in my MacBook Pro, I noticed that FileVault 2 had only encrypted my main volume.&lt;/p&gt;
&lt;p&gt;This was a problem, because most of the sensitive data is on the second volume, with my home folder.  So it had to be fixed.&lt;/p&gt;
&lt;p&gt;The solution is quite simple:&lt;/p&gt; &lt;ol&gt;
	&lt;li&gt;Log into (or create and log into) a secondary administrator account, I call mine &amp;#8220;restore&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Make sure the second account has their home folder on the main internal OS drive (not out on the secondary drive where your home folder it)&lt;/li&gt;
	&lt;li&gt;Once logged in as the restore user, find the device name of the secondary drive using df, in my case it is /dev/disk0s2:&lt;br /&gt;
  &lt;pre&gt;&lt;br /&gt;
  $ df&lt;br /&gt;
  Filesystem    512-blocks      Used Available Capacity  Mounted on&lt;br /&gt;
  /dev/disk2     466560312 169368416 296679896    37%    /&lt;br /&gt;
  devfs                392       392         0   100%    /dev&lt;br /&gt;
  /dev/disk0s2   976101344 558685488 417415856    58%    /Volumes/data&lt;br /&gt;
  map -hosts             0         0         0   100%    /net&lt;br /&gt;
  map auto_home          0         0         0   100%    /home&lt;br /&gt;
  &lt;/pre&gt;&lt;/li&gt;
	&lt;li&gt;Once logged in, run the following command from the shell:&lt;br /&gt;
  &lt;pre&gt;&lt;br /&gt;
sudo diskutil coreStorage convert /dev/disk0s2 -passphrase &amp;#8216;password&amp;#8217;&lt;/pre&gt;&lt;br /&gt;
  make sure you change &amp;#8216;password&amp;#8217; to something you will never forget :)&lt;/li&gt;
	&lt;li&gt;The system will start encrypting your drive.  Hopefully you have no open files on the secondary drive so that the system can dismount and mount your drive again and start encrypting.&lt;/li&gt;
	&lt;li&gt;Complete the steps below.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This works, however, there is a problem. With your home folder now on the second drive, it has to be unlocked &lt;span class="caps"&gt;BEFORE&lt;/span&gt; you can log in.  As you need to log in to get access to your keychain, this presents a chicken and egg problem.&lt;/p&gt;
&lt;p&gt;The solution is a great script created by Mr Ridgewell called &lt;a href="https://github.com/jridgewell/unlock"&gt;unlock&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Before you logout of the restore user (assuming you didn&amp;#8217;t need to reboot to start the encryption process due to open files), run the following from the terminal:&lt;br /&gt;
  &lt;pre&gt;&lt;br /&gt;
$ bash &amp;lt;(curl -s https://raw.github.com/jridgewell/Unlock/master/install.sh)&lt;/pre&gt;&lt;br /&gt;
  This will prompt you with &amp;#8220;Do you want to automatically unlock this drive at boot?&amp;#8221; for each encrypted volume it detects other than the boot partition.  If you say yes, you&amp;#8217;ll need to enter the password for that drive.&lt;/li&gt;
	&lt;li&gt;Once this process is complete, restart your mac and boot up and log into your normal user account, you should be all good.  Further, if you go into disk utility, you will see that the File System type has changed to &amp;#8220;Mac OS Extended (Journaled, Encrypted)&amp;#8221; for both your main internal and secondary volumes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Obviously, this is only safe if your main boot partition is also protected via FileVault otherwise your unlock key for the secondary drive would be in plain text on the boot partition. However, I am assuming you have FileVault 2 turned on for the main boot partition.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/Installing-Home-Folder-on-Second-Drive-on-OSX-Lion</id>
    <published>2011-08-06T12:04:00+00:00</published>
    <updated>2011-08-06T12:04:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/Installing-Home-Folder-on-Second-Drive-on-OSX-Lion"/>
    <title>Installing Home Folder on Second Drive on OSX Lion</title>
    <content type="html">
&lt;p&gt;I have a 15&amp;quot; Macbook Pro, early 2010 model.  It had a 500Gb Seagate 7200 &lt;span class="caps"&gt;RPM&lt;/span&gt; Momentus&lt;br /&gt;
drive in it, and had been serving me well over the past year but I wanted to give it&lt;br /&gt;
a speed boost, so I purchased a 240Gb &lt;span class="caps"&gt;SSD&lt;/span&gt; for the OS drive and new 500Gb Seagate Hybrid&lt;br /&gt;
drive with an &lt;span class="caps"&gt;OWC&lt;/span&gt; optical bay mounting kit for the data drive.&lt;/p&gt; &lt;p&gt;Installation was a bit of a pain as my user data was close to 250Gb alone, so it was&lt;br /&gt;
impossible to restore this completely to the OS drive.&lt;/p&gt;
&lt;p&gt;To handle this I did the following:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Make sure you have a complete backup before you do this!  I hope my instructions are correct, but this post has the standard &lt;span class="caps"&gt;MIT&lt;/span&gt; licence :)&lt;/li&gt;
	&lt;li&gt;Create a &amp;#8220;restore&amp;#8221; user with admin rights&lt;/li&gt;
	&lt;li&gt;Replace out the optical drive with the 500Gb Hybrid&lt;/li&gt;
	&lt;li&gt;Log in as the &amp;#8220;restore&amp;#8221; user&lt;/li&gt;
	&lt;li&gt;Format the new 500Gb drive as a single big partition calling it &amp;#8220;data&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Make a /Users folder on the data drive&lt;/li&gt;
	&lt;li&gt;While logged in as the &amp;#8220;restore&amp;#8221; user, copy (just using Finder is fine) my home directory in the /Users folder from the internal drive and dump it into the data drive &amp;#8211; this can take some time :)&lt;/li&gt;
	&lt;li&gt;Once the copy is complete open up System Preferences, accounts and right click on my user account and select &amp;#8220;Advanced Options&amp;#8221;, in there change the path to the home folder to the new folder on the data volume&lt;/li&gt;
	&lt;li&gt;Log out of the &amp;#8220;restore&amp;#8221; user and log in as your own user again, you should now have the home folder in the new location (the folder will have the home icon in finder)&lt;/li&gt;
	&lt;li&gt;Note, when logging back in as yourself, some applications might complain that they can&amp;#8217;t find the old folder, Dropbox is one of these culprits as they use an absolute path, not a relative one.  Just relink as needed.&lt;/li&gt;
	&lt;li&gt;Delete the old home folder in &amp;#8220;/Users/yourloginname&amp;#8221; (or move it to external storage for safe keeping if you are still in disbelief that everything worked)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now we are ready to replace the internal OS drive.  One thing I found though was that even after I deleted my home folder, the free space didn&amp;#8217;t drop!  It stayed stuck where it was.  This made me think it was some sort of trash or recycle bin, but what I found is that there is a directory called /.MobileBackups on your drive that is like a mini portable time machine.  So if you have time machine on, but you are not connected to it when it is time to backup, Lion will take a snapshot of your drive of changes.  Neat, but in this case annoying.&lt;/p&gt;
&lt;p&gt;So I had to do the following to replace the Internal drive:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Replace the internal OS drive with the new shiny &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;Put the old internal drive into a &lt;span class="caps"&gt;USB&lt;/span&gt; enclosure&lt;/li&gt;
	&lt;li&gt;Connect &lt;span class="caps"&gt;USB&lt;/span&gt; enclosure to mac and restart into the recovery mode (Hold down Command-R until you see the apple logo)&lt;/li&gt;
	&lt;li&gt;Once in recovery mode, go into Disk Utility and note the name of your old Internal drive that is now connected via &lt;span class="caps"&gt;USB&lt;/span&gt;, it will be called something like &amp;#8220;Macintosh HD&amp;#8221; or some custom name if you have changed it.&lt;/li&gt;
	&lt;li&gt;Quit disk utility and go into the to terminal app.&lt;/li&gt;
	&lt;li&gt;Change to the folder where your &lt;span class="caps"&gt;USB&lt;/span&gt; drive is mounted, if your drive is called Macintosh HD then do: &amp;#8220;cd /Volumes/Macintosh\ HD&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Check to see if the MobileBackups folder exists with &amp;#8220;ls -al&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Forcibly delete the MobileBackups folder if it exists with &amp;#8220;rm -rf .MobileBackups&amp;#8221; &amp;#8211; this can also take some time, in my case this folder had over 300gb in it&lt;/li&gt;
	&lt;li&gt;Once delete see how much space is left with &amp;#8220;df -hi&amp;#8221;  It will show how many Gb have been used and what is available, make sure your old internal drive now has less used than is available on your new &lt;span class="caps"&gt;SSD&lt;/span&gt; drive.&lt;/li&gt;
	&lt;li&gt;Quit terminal and fire up Disk Utility&lt;/li&gt;
	&lt;li&gt;Click on your old internal drive connected via &lt;span class="caps"&gt;USB&lt;/span&gt;, and click the &amp;#8220;Restore&amp;#8221; tab.  Then drag the new &lt;span class="caps"&gt;SSD&lt;/span&gt; drive from the sidebar into the Destination box.  This will copy the contents of the old Internal drive onto your &lt;span class="caps"&gt;SSD&lt;/span&gt; drive.&lt;/li&gt;
	&lt;li&gt;Get this started (the confirmation box here is actually quite good and tells you what is going to happen clearly).&lt;/li&gt;
	&lt;li&gt;Come back in an hour or two.&lt;/li&gt;
	&lt;li&gt;Now that the &lt;span class="caps"&gt;SSD&lt;/span&gt; drive has everything your old internal drive had, the moment of truth has come, the reboot.  Quit time machine, and then restart choosing your new &lt;span class="caps"&gt;SSD&lt;/span&gt; drive as the boot source, for added assurance, I disconnected my &lt;span class="caps"&gt;USB&lt;/span&gt; drive at this point.&lt;/li&gt;
	&lt;li&gt;Your mac should now restart on your new internal &lt;span class="caps"&gt;SSD&lt;/span&gt; drive a lot faster than before.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that&amp;#8217;s it!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/undefined-local-variable-or-method-version_requirements</id>
    <published>2011-06-30T11:01:00+00:00</published>
    <updated>2011-06-30T11:01:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/undefined-local-variable-or-method-version_requirements"/>
    <title>undefined local variable or method `version_requirements'</title>
    <content type="html">
&lt;p&gt;If you have a Rails 2.x app and hitting this, there is a simple fix while you wait to upgrade to Rails 3.&lt;/p&gt; &lt;p&gt;Edit your environment.rb file and inbetween the &lt;tt&gt;require &amp;#8216;boot&amp;#8217;&lt;/tt&gt; line and the &lt;tt&gt;Rails::Initializer&lt;/tt&gt; line, insert the following &lt;tt&gt;Gem::&lt;span class="caps"&gt;VERSION&lt;/span&gt;&lt;/tt&gt; if statement:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')

if Gem::VERSION &amp;gt;= "1.3.6"
  module Rails
    class GemDependency
      def requirement
        (super == Gem::Requirement.default) ? nil : super
      end
    end
  end
end

Rails::Initializer.run do |config|
# ....
&lt;/pre&gt;
&lt;p&gt;It&amp;#8217;s a hack, it might break with later and later releases of RubyGems.  But it allowed me to get a 2.3.x Rails app running on a fairly current rubygems.&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/a-new-world-of-resources</id>
    <published>2011-05-23T22:04:00+00:00</published>
    <updated>2011-05-23T22:04:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/a-new-world-of-resources"/>
    <title>A New World of Resources</title>
    <content type="html">
&lt;p&gt;Last year I attacked a long lost black sheep of the Rails family, ActionMailer.  This was because I had a project that needed to use email and I found the current implementation, shall we say, somewhat lacking.  This year, I&amp;#8217;m turning my attention to really the only remaining black sheep left, ActiveResource.&lt;/p&gt; &lt;p&gt;ActiveResource needs to be upgraded to be a real citizen in the Rails 3 family, in fact, in the last few years there have only been very minor fixes to ActiveResource while the rest of the world moved forward.&lt;/p&gt;
&lt;p&gt;So what do we have? Happily, working code.&lt;/p&gt;
&lt;p&gt;ActiveResource, as it stands now, works for the simplest of cases. If you have a controller exposing a Rails &lt;span class="caps"&gt;REST&lt;/span&gt; based resource, and you point ActiveResource at it, you will be able to perform the basic &lt;span class="caps"&gt;CRUD&lt;/span&gt; operations you have come to know and love.&lt;/p&gt;
&lt;p&gt;But if you want to go any further, you are on your own.&lt;/p&gt;
&lt;p&gt;Associations with ActiveRecord objects don&amp;#8217;t work, validations need attention, bulk updates and transactional support are missing entirely.  The code is really as it was when it was first released.&lt;/p&gt;
&lt;p&gt;With the world moving towards using rich clients that hit a back end &lt;span class="caps"&gt;API&lt;/span&gt; that abstracts the data layer, these things need to change.  Having your front end client go to delete 100 records requiring 100 requests to complete is no fun, and a waste of time.&lt;/p&gt;
&lt;p&gt;Sure you as a developer can dive in and create all these things. But that is the problem. With each developer rolling their own we end up with a mass of Rails apps that are all different, which increases the work load for all of us.  ActiveResource must provide the same level of opinionated functionality as the rest of Rails. There needs to be a reasonable opinion on how to provide an &lt;span class="caps"&gt;API&lt;/span&gt;, a template that you can reasonably expect all Rails applications to follow.&lt;/p&gt;
&lt;p&gt;The way I see it, there are two broad use cases for ActiveResource and the code that is exposed in the controllers.  Firstly we have the &amp;#8220;bolt on &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8221;, this is the &lt;span class="caps"&gt;API&lt;/span&gt; that is simply added to existing controller code typically using &lt;tt&gt;respond_to&lt;/tt&gt; and returning &lt;span class="caps"&gt;JSON&lt;/span&gt; or &lt;span class="caps"&gt;XML&lt;/span&gt; representations of objects.&lt;/p&gt;
&lt;p&gt;The second type though is the pure &lt;span class="caps"&gt;API&lt;/span&gt;, these are the APIs that are built from the ground up only to talk to other systems, the &lt;span class="caps"&gt;API&lt;/span&gt; at rubygems.org is a good example of this.  It is not a patch on existing functionality, but instead a core member of the entire application.&lt;/p&gt;
&lt;p&gt;With the above in mind, I want to implement the following into ActiveResource:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Opinionated way to produce a &amp;#8220;pure &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8221; with Rails (think &amp;#8220;rails generate api&amp;#8221; for Rails applications that need to expose a separate, formal &lt;span class="caps"&gt;API&lt;/span&gt; for rich clients)&lt;/li&gt;
	&lt;li&gt;Support for bulk updates of objects to existing controllers (show_many, change_many, update_many and destroy_many) &amp;#8211; see idea in &lt;a href="https://gist.github.com/981520"&gt;David&amp;#8217;s Gist&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Transactional support for bulk operations&lt;/li&gt;
	&lt;li&gt;Support for multi type operations (for example, updating the post and the author at the same time) outlined in the Rails Conf talk by Yehuda Katz&lt;/li&gt;
	&lt;li&gt;Association support &amp;#8211; providing connections through to local ORMs&lt;/li&gt;
	&lt;li&gt;Better validation handling and reliable ways to communicate error messages to client apps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above is not an exhaustive list and I am interested in your comments.  If you are interested in helping, send me an email or tweet to (&lt;a href="http://twitter.com/raasdnil"&gt;@raasdnil&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be posting updates here and on my twitter feed as we move forward.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails-static-pages</id>
    <published>2011-04-18T13:00:00+00:00</published>
    <updated>2011-04-18T13:00:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails-static-pages"/>
    <title>Rails Static Pages</title>
    <content type="html">
&lt;p&gt;Static pages are one of those things that you have to get around to doing for every website.  This is how we implemented them on &lt;a href="http://stillalive.com/"&gt;StillAlive&lt;/a&gt; to make them maintainable and also cacheable.&lt;/p&gt; &lt;p&gt;On pretty much every website, you will have a bunch of pages that are just plain old static content.  Good examples of these are Privacy Policies, Terms of Use, Contact Pages and the like.  These generally contain content that rarely changes.&lt;/p&gt;
&lt;p&gt;To make these simple static pages, we first add a catch all route at the bottom of &lt;tt&gt;config/routes.rb&lt;/tt&gt; which looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
  match ':page_name' =&amp;gt; 'site/pages#show'
&lt;/pre&gt;
&lt;p&gt;As this is a catchall route, you need to put this right at the bottom of your routes file.  Basically it just catches anything that is not defined in the above routes and send it off to &lt;tt&gt;PagesController#show&lt;/tt&gt; with the &lt;tt&gt;params[:page_name]&lt;/tt&gt; set to the requested path.&lt;/p&gt;
&lt;p&gt;So if the user navigates to &lt;a href="http://stillalive.com/plans_and_pricing"&gt;http://stillalive.com/plans_and_pricing&lt;/a&gt; then the &lt;tt&gt;PagesController&lt;/tt&gt; will have the &lt;tt&gt;show&lt;/tt&gt; method called with &lt;tt&gt;plans_and_pricing&lt;/tt&gt; set as the &lt;tt&gt;params[:page_name]&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;With the routing set, we then make a Pages controller that looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class PagesController &amp;lt; ApplicationController

  layout 'site'

  def show
    @page_name = params[:page_name].to_s.gsub(/\W/,'')
  end

end
&lt;/pre&gt;
&lt;p&gt;Some key points here, firstly, we set the &lt;tt&gt;@page_name&lt;/tt&gt; variable to be the value of the &lt;tt&gt;params[:page_name]&lt;/tt&gt;, call &lt;tt&gt;#to_s&lt;/tt&gt; on this (which handles the case of &lt;tt&gt;params[:page_name]&lt;/tt&gt; being &lt;tt&gt;nil&lt;/tt&gt;) and then call &lt;tt&gt;#gsub&lt;/tt&gt; on the string stripping out anything that is not a word character.&lt;/p&gt;
&lt;p&gt;With that done, we then drop through to rendering &lt;tt&gt;pages/show.html.erb&lt;/tt&gt; which looks like this:&lt;/p&gt;
&lt;pre class="html"&gt;
&amp;lt;%= cache "site-page-#{@page_name}-#{App.git_revision}" do %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; @page_name %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;So this just renders the partial with the page name requested.&lt;/p&gt;
&lt;p&gt;So in the example above, we have a partial called &lt;tt&gt;pages/_plans_and_pricing.html.erb&lt;/tt&gt; that gets rendered.&lt;/p&gt;
&lt;p&gt;We also wrap it in a cache block.  The cache block includes the page name, and also our git revision.  We set the git revision so that every time we push new code to our server, all the prior cached pages get expired.  This provides a no brainer way to make sure the latest code is showing on the site.&lt;/p&gt;
&lt;p&gt;The &lt;tt&gt;App.git_revision&lt;/tt&gt; call is using the &lt;a href="http://rubygems.org/gems/app"&gt;App Config gem&lt;/a&gt; and is set by modifying &lt;tt&gt;config/app.rb&lt;/tt&gt; to look like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class App &amp;lt; Configurable # :nodoc:
  # Settings in config/app/* take precedence over those specified here.
  config.name = Rails.application.class.parent.name

  config.git_revision = `git rev-parse HEAD 2&amp;gt;/dev/null`.to_s.strip
end
&lt;/pre&gt;
&lt;p&gt;This sets the value git_revision on boot.  Simple.&lt;/p&gt;
&lt;p&gt;Now the above code is good, but what happens when someone requests a page that does not exist on our site, we&amp;#8217;ll, we can&amp;#8217;t handle this the simple way, as the MissingTemplate exception gets raised outside of our controller, inside the show view.&lt;/p&gt;
&lt;p&gt;One solution would be to wrap the &lt;tt&gt;render :partial&lt;/tt&gt; call in the &lt;tt&gt;show.html.erb&lt;/tt&gt; template in a rescue block, rescue the &lt;tt&gt;ActionController::MissingTemplate&lt;/tt&gt; exception and render a missing template instead, however, the problem with this is that the response code will still be 200 OK, where we really want it to return a 404 page not found status.&lt;/p&gt;
&lt;p&gt;So we need a way to check to see if the partial is valid or not, before we render the show action.  There is no simple way to do this, so the way we handle it is by creating a &lt;tt&gt;partial_exists?&lt;/tt&gt; method in the controller which checks, like so:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class PagesController &amp;lt; ApplicationController

  layout 'site'

  def show
    @page_name = params[:page_name].to_s.gsub(/\W/,'')
    unless partial_exists?(@page_name)
      render 'missing', :status =&amp;gt; 404
    end
  end

  private

  def partial_exists?(partial)
    ValidPartials.include?(partial)
  end

  def self.find_partials
    Dir.glob(Rails.root.join('app', 'views', 'site', 'pages', '_*.erb')).map do |file|
      file = Pathname.new(file).basename.to_s
      # Strip leading _ and then everything from the first . to the end of the name
      file.sub(/^_/, '').sub(/\..+$/, '')
    end
  end

  # Do this once on boot
  ValidPartials = Site::PagesController.find_partials

end
&lt;/pre&gt;
&lt;p&gt;By using a constant at the bottom, we only run the &lt;tt&gt;Dir.glob&lt;/tt&gt; once at boot time to reduce the overhead (instead of running it on every request). The &lt;tt&gt;find_partials&lt;/tt&gt; method returns a list of partials that look like:&lt;/p&gt;
&lt;pre class="ruby"&gt;
['about', 'plans_and_pricing', 'privacy_policy'...]
&lt;/pre&gt;
&lt;p&gt;This way, every time we restart our server, we get a new list of partials in production mode, and every time we refresh in development mode, this list gets updated in any case.&lt;/p&gt;
&lt;p&gt;Hope this helps :)&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/twitter-replacing-rails-so</id>
    <published>2011-04-09T21:25:00+00:00</published>
    <updated>2011-04-09T21:25:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/twitter-replacing-rails-so"/>
    <title>Twitter Replacing Rails?  So?</title>
    <content type="html">
&lt;p&gt;Twitter are reportedly moving away from Ruby on Rails. It&amp;#8217;s on a lot of people&amp;#8217;s tweets and on our Rails Oceania Mailing list. But the real question that should be asked is &amp;#8220;So?&amp;#8221;&lt;/p&gt; &lt;p&gt;Ruby on Rails is a tool for a job. I run a Ruby and Ruby on Rails consulting firm and we use Ruby and Rails to do one thing extremely well, that is rapid, highly customised, web application development.  We can produce applications that fit very complex business models at break neck speed.&lt;/p&gt;
&lt;p&gt;These same applications can then go on, with little or no modification mind, to serve more requests than ninety nine point lots of nines websites will &lt;em&gt;ever&lt;/em&gt; need.&lt;/p&gt;
&lt;p&gt;But one thing that Ruby is not suited to is highly concurrent, speed optimised computing.  It&amp;#8217;s not designed to.  Ruby&amp;#8217;s stated design goal by Matz (paraphrasing) is programmer happiness and help change the way us programmers think by providing a language that allows us to express our ideas and thoughts rapidly, elegantly and simply.&lt;/p&gt;
&lt;p&gt;If you want something insanely fast, highly concurrent and optimised to the gills for speed, use something that is not Ruby, maybe Erlang, Scala, C, whatever.&lt;/p&gt;
&lt;p&gt;If you need a web site developed that is on budget, has a really great development curve and delivers highly productive and successful web applications in the shortest possible times, use Rails.&lt;/p&gt;
&lt;p&gt;I think the real surprise should not be &amp;#8220;&lt;span class="caps"&gt;OMG&lt;/span&gt;, Twitter is moving their search feature away from Rails!&amp;#8221;  I think the point is &amp;#8220;&lt;span class="caps"&gt;OMG&lt;/span&gt;, Rails has managed to run &lt;em&gt;twitter&amp;#8217;s&lt;/em&gt; search feature successfully for &lt;span class="caps"&gt;THIS&lt;/span&gt; &lt;span class="caps"&gt;LONG&lt;/span&gt;?!&amp;#8221;&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/engine-yard-cloud-backups-generating-zero-length-backups</id>
    <published>2011-02-11T08:55:08+00:00</published>
    <updated>2011-02-11T08:55:08+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/engine-yard-cloud-backups-generating-zero-length-backups"/>
    <title>Engine Yard Cloud Backups Generating Zero Length Backups</title>
    <content type="html">
&lt;p&gt;If your backups on EngineYard cloud are zero length, maybe it is a permissions problem.&lt;/p&gt; &lt;p&gt;We have a client that uses EngineYard cloud and has more than one application hitting the same database.&lt;/p&gt;
&lt;p&gt;As part of this, he needs access, and it turns out that some of the views and tables were not owned by the deploy user.&lt;/p&gt;
&lt;p&gt;This causes the eybackup to backup a file that is zero length and push it to the S3 backup but still return &lt;em&gt;successfully&lt;/em&gt;.  This is a problem because a cursory examination shows the backups are working all fine.&lt;/p&gt;
&lt;p&gt;While EngineYard go about fixing this, the solution is simple, just make sure the owner of all the tables in the system belong to the deploy user, or alternatively make sure the deploy user can read all the tables in the database.&lt;/p&gt;
&lt;p&gt;If you are using postgres you can do this with a simple &lt;span class="caps"&gt;SQL&lt;/span&gt; command:&lt;/p&gt;
&lt;pre class="sql"&gt;
psql&amp;gt; ALTER TABLE &amp;lt;table name&amp;gt; OWNER TO deploy;
&lt;/pre&gt;
&lt;p&gt;MySQL has a similar simple command to handle this issue.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/our-rails-rumble-entry-stillalive.com</id>
    <published>2010-10-19T18:18:00+00:00</published>
    <updated>2010-10-19T18:18:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/our-rails-rumble-entry-stillalive.com"/>
    <title>Our Rails Rumble Entry - StillAlive.com</title>
    <content type="html">
&lt;p&gt;&lt;a href="http://stillalive.com/"&gt;StillAlive.com&lt;/a&gt; is our RailsRumble entry, and I am quite happy with it!&lt;/p&gt; &lt;p&gt;StillAlive does app monitoring with a twist.  Instead of just pinging your server, or checking for a string on a page, you can write cucumber like stories that interrogate your app and test that it is actually working.&lt;/p&gt;
&lt;p&gt;For example, for &lt;a href="http://tellthemwhen.com/"&gt;TellThemWhen&lt;/a&gt; I have the following story:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;When I go to http://tellthemwhen.com/&lt;/li&gt;
	&lt;li&gt;And I follow &amp;#8220;Make a Time!&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Then I should see &amp;#8220;Create Notification&amp;#8221;&lt;/li&gt;
	&lt;li&gt;When I fill in &amp;#8220;Time&amp;#8221; with &amp;#8220;Tomorrow&amp;#8221;&lt;/li&gt;
	&lt;li&gt;And I fill in &amp;#8220;Title&amp;#8221; with &amp;#8220;Test Notification&amp;#8221;&lt;/li&gt;
	&lt;li&gt;And I fill in &amp;#8220;Message&amp;#8221; with &amp;#8220;This is the message in the notification&amp;#8221;&lt;/li&gt;
	&lt;li&gt;And I press &amp;#8220;Create Notification&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Then I should see &amp;#8220;Test Notification&amp;#8221;&lt;/li&gt;
	&lt;li&gt;And I should see &amp;#8220;This is the message in the notification&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StillAlive will then run that script every hour and email and &lt;span class="caps"&gt;SMS&lt;/span&gt; me if it fails&amp;#8230;.&lt;/p&gt;
&lt;p&gt;And the awesome thing is, we did this in 48 hours&amp;#8230; 4 guys&amp;#8230; and we even slept some!&lt;/p&gt;
&lt;p&gt;Ruby on Rails truly is an awesome development environment.&lt;/p&gt;
&lt;p&gt;Please try it out and let me know what you think.&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/renaming_a_controller_and_redirection_in_rails_3</id>
    <published>2010-09-30T18:27:00+00:00</published>
    <updated>2010-09-30T18:27:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/renaming_a_controller_and_redirection_in_rails_3"/>
    <title>Renaming a controller and redirection in Rails 3</title>
    <content type="html">
&lt;p&gt;I had the situation where I wanted to rename a basic part of the &lt;a href="http://tellthemwhen.com/"&gt;TellThemWhen&lt;/a&gt; website, that is, changing the name of &amp;#8220;instants&amp;#8221; to &amp;#8220;notifications&amp;#8221;.  As this was a major part of the whole website, I had to make sure existing URLs still resolved correctly, luckily in Rails 3, this couldn&amp;#8217;t be simpler!&lt;/p&gt; &lt;p&gt;This was a fairly big issue, &amp;#8220;Instants&amp;#8221; were the name of the basic product of the site, that is, you could make an &amp;#8220;instant&amp;#8221; to share with other people.  After a lot of varied feedback however, we decided that &amp;#8220;notification&amp;#8221; was a better name.&lt;/p&gt;
&lt;p&gt;But all the URLs our clients have been distributing look like http://tellthemwhen.com/instants/a3s2&amp;#8230; and people have been landing on our &lt;a href="http://tellthemwhen.com/instants/new"&gt;new instant page&lt;/a&gt; directly per our analytics data.&lt;/p&gt;
&lt;p&gt;So I needed a solution which basically remapped &lt;tt&gt;/instants/&lt;span class="caps"&gt;ANYTHING&lt;/span&gt;&lt;/tt&gt; to &lt;tt&gt;/notifications/&lt;span class="caps"&gt;ANYTHING&lt;/span&gt;&lt;/tt&gt;.  Happily, the Rails 3 router solves this.&lt;/p&gt;
&lt;p&gt;First step is to make a redirector.  This is a really simple rack app, I made mine like so and just put it at the top of my &lt;tt&gt;config/routes.rb&lt;/tt&gt; file, it looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
module TellThemWhen
  class InstantRedirector
    def self.call(env)
      destination  = "#{env['PATH_INFO']}".sub('instant', 'notification')
      destination &amp;lt;&amp;lt; "?#{env['QUERY_STRING']}" unless env['QUERY_STRING'].empty?
      [301, {'Location' =&amp;gt; destination}, ['Instants are now called notifications']] 
    end
  end
end

TellThemWhen::Application.routes.draw do
  # ...
end
&lt;/pre&gt;
&lt;p&gt;This is a simple Rack application. It has a class method called &amp;#8220;call&amp;#8221; that the current environment as an attribute, then pulls the path data substituting the first occurrence of &amp;#8220;instant&amp;#8221; with &amp;#8220;notification&amp;#8221;, then adds all of the params data on the end, and sends back a 301 redirect to the client with this new &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then in the &lt;tt&gt;routes.rb&lt;/tt&gt; I have:&lt;/p&gt;
&lt;pre class="ruby"&gt;
TellThemWhen::Application.routes.draw do
  # ...
  # Catch old instant style URL and redirect to Notifications
  match '(/my)/instant(s)(/:id)' =&amp;gt; TellThemWhen::InstantRedirector
end
&lt;/pre&gt;
&lt;p&gt;Here I need to match both &amp;#8220;/my/instant&amp;#8221; and &amp;#8220;/instant&amp;#8221; as well as the plural form of instants, I also want to be sure I am only matching the URLs that have instant directly off the root, just in case in the future I have a &lt;span class="caps"&gt;URL&lt;/span&gt; that looks like &amp;#8220;/notification/instant&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Using the parentheses around &lt;tt&gt;(/my)&lt;/tt&gt; and &lt;tt&gt;(s)&lt;/tt&gt; and &lt;tt&gt;(/:id)&lt;/tt&gt; make these optional to the match process.&lt;/p&gt;
&lt;p&gt;This match statement simply calls the rack app, InstantRedirector which then runs the &lt;tt&gt;call&lt;/tt&gt; class method, returning the redirection array sending the user back to the correct notifications path with a 301 permanent redirect.&lt;/p&gt;
&lt;p&gt;Sweet.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/updating_railsplugins_org_to_rails_3_part_1</id>
    <published>2010-09-24T00:11:00+00:00</published>
    <updated>2010-09-24T00:11:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/updating_railsplugins_org_to_rails_3_part_1"/>
    <title>Updating RailsPlugins.org to Rails 3 - Part 1</title>
    <content type="html">
&lt;p&gt;&lt;a href="http://rubyx.com"&gt;RubyX&lt;/a&gt; are the maintainers for the &lt;a href="http://railsplugins.org"&gt;RailsPlugins.org&lt;/a&gt; website with hosting kindly donated by &lt;a href="http://engineyard.com"&gt;EngineYard&lt;/a&gt;.  As the site is all about compatibility with Rails 3, the irony was not lost on us that the site is running on Rails 2.3.5.  I will do a series of posts which cover how we updated the site to Rails 3.&lt;/p&gt; &lt;p&gt;First off, RailsPlugins.org is a non trivial web application.  It has OpenID authentication, &lt;span class="caps"&gt;API&lt;/span&gt; integration with RubyGems.org as well as a complex versioning, voting and commenting system that includes emails out to gem owners to encourage them to get their gems up to date with Rails 3.&lt;/p&gt;
&lt;p&gt;The site currently hosts information for over 500 plugins and gems, tracking 1,500 versions with over 6,500 opinions from users and owners alike.&lt;/p&gt;
&lt;p&gt;First off, it is good to work out a broad process on how you plan to upgrade a Rails 2.x app to Rails 3.  At RubyX, this is one of our specialties, and so we have a documented path on how we go about it.&lt;/p&gt;
&lt;h3&gt;RubyX Rails 3 Upgrade Process from Rails 2.3.x&lt;/h3&gt;
&lt;p&gt;As I mentioned, RubyX have a codified path on how we update Rails 2.3 apps to Rails 3.  If you are running a version of rails that is earlier than Rails 2.3, you really need to update to 2.3.x first before trying to go to Rails 3.  It will save you a lot of pain.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Confirm all specs, tests and features are passing&lt;/li&gt;
	&lt;li&gt;Migrate the 2.3.x app over to using Bundler and a Gemfile&lt;/li&gt;
	&lt;li&gt;Remove all vendor&amp;#8217;d gems and plugins that can be specified in the Gemfile&lt;/li&gt;
	&lt;li&gt;Audit any remaining vendor&amp;#8217;d gems and plugins that have application specific modifications, and fork these changes into our own repositories and install them from here using the Gemfile&lt;/li&gt;
	&lt;li&gt;Review all gems and plugins in use by the app and ensure that Rails 3 versions are available.&lt;/li&gt;
	&lt;li&gt;For any remaining vendor&amp;#8217;d gems and plugins that can not be Gemfile&amp;#8217;d now but do have a Rails 3 version, leave them vendor&amp;#8217;d for now and migrate to the gem version once we have updated t Rails 3.&lt;/li&gt;
	&lt;li&gt;For any gems that do not have a Rails 3 version, decide what to do.  Contribute a Rails 3 version or replace.&lt;/li&gt;
	&lt;li&gt;Deploy this code to staging environment, for a sanity check.&lt;/li&gt;
	&lt;li&gt;Migrate the Rails app release by release up to Rails 2.3.9&lt;/li&gt;
	&lt;li&gt;Handle all deprecation warnings at each release&lt;/li&gt;
	&lt;li&gt;Migrate Gemfile and app to Rails 3&lt;/li&gt;
	&lt;li&gt;Update gem dependencies to ensure working with Rails 3&lt;/li&gt;
	&lt;li&gt;Do minimal modifications required to get all tests and specs passing&lt;/li&gt;
	&lt;li&gt;Review application code and take advantage of new Rails 3 idioms&lt;/li&gt;
	&lt;li&gt;Deploy to cloned production environment and test fully&lt;/li&gt;
	&lt;li&gt;Deploy to production environment with roll back plan&lt;/li&gt;
	&lt;li&gt;Test&lt;/li&gt;
	&lt;li&gt;Test&lt;/li&gt;
	&lt;li&gt;Test&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Obviously the above gets run in a separate branch, it also gets done as rapidly as possible to avoid divergence with the production branch.  There are several opportunities to merge back into production, at each update of Rails before 3.0 for example.  However, this is not required.&lt;/p&gt;
&lt;p&gt;A key point is step 6, making sure you have Rails 3 compatible versions of all gems you use in the app.  This can obviously be done earlier, however, upgrading to Rails 2.3.9 is a good thing to do in any case and can be the first goal of your migration process.&lt;/p&gt;
&lt;p&gt;You can use RailsPlugins.org to look up your gems and plugins to see what other users have found and authors have commented on in relation to Rails 3 compatibility.&lt;/p&gt;
&lt;p&gt;So with the process codified.  Lets get onto our first step, making sure the app has test coverage.&lt;/p&gt;
&lt;h3&gt;Confirm all specs, tests and features are passing&lt;/h3&gt;
&lt;p&gt;In doing this sort of upgrade you really can&amp;#8217;t stress a good test suite enough.  RailsPlugins has &lt;span class="caps"&gt;XXXX&lt;/span&gt; specs and &lt;span class="caps"&gt;XXXX&lt;/span&gt; features that exercise every part of the application, very thoroughly.  So before we start changing code or files, lets run that suite:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ rake spec
  .................... (...)
  Finished in 20.469918 seconds
  234 examples, 0 failures
$ rake cucumber
  .................... (...)
  126 scenarios (126 passed)
  1873 steps (1873 passed)
  1m7.546s
&lt;/pre&gt;
&lt;p&gt;OK, it could be a lot faster, but we have the green light on all our specs and features.  Time to migrate the app to use Bundler and a Gemfile.&lt;/p&gt;
&lt;h3&gt;Migrate the 2.3.x app to use Bundler and a Gemfile&lt;/h3&gt;
&lt;p&gt;Now that we have spec coverage for our changes, the next thing we need to do on a Rails 2.3 app is to create a &lt;tt&gt;config/preinitializer.rb&lt;/tt&gt; file as well as update your &lt;tt&gt;config/boot.rb&lt;/tt&gt; to boot using Bundler.  This is well explained on the &lt;a href="http://gembundler.com"&gt;Bundler&lt;/a&gt; website.  Just follow along there.&lt;/p&gt;
&lt;p&gt;In the case of RailsPlugins.org, we were already used a Gemfile, of sorts.  It was running a 0.9 release of bundler, and the Gemfile looked like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
source :gemcutter

gem 'rails', '2.3.5'

gem 'mysql',                '2.8.1'
gem 'url_field',            '0.0.2'
gem 'ruby-openid'
gem 'hoptoad_notifier'
gem 'capistrano'
gem 'engineyard',           '1.1.3'
gem 'delayed_job',          '2.0.2'

group :plugins do
  gem 'authlogic-oid',       :require =&amp;gt; 'authlogic_openid'
  gem 'authlogic',           '2.1.3'
  gem 'behavior',            '0.2.0'
  gem 'will_paginate',       '2.3.11'
  gem 'inherited_resources', '1.0.4'
end

group :test do
  gem 'highline',            '~&amp;gt; 1.5.2'
  gem 'machinist',           '&amp;gt;=1.0.3'
  gem 'cucumber',            '&amp;gt;=0.3.103'
  gem 'cucumber-rails',      '&amp;gt;=0.2.4'
  gem 'database_cleaner',    '&amp;gt;=0.4.3'
  gem 'webrat',              '&amp;gt;=0.6.0'
  gem 'rspec',               '&amp;gt;=1.3.0'
  gem 'rspec-rails',         '&amp;gt;=1.3.2'
  gem 'rspec',               '&amp;gt;=1.2.9'
  gem 'faker',               '~&amp;gt;0.3.1'
  gem 'nokogiri'
  gem 'ruby-debug'
  gem 'ZenTest'
end
&lt;/pre&gt;
&lt;p&gt;The above Gemfile is not &lt;span class="caps"&gt;TOO&lt;/span&gt; bad, but there are some three glaring mistakes.&lt;/p&gt;
&lt;p&gt;Firstly is the use of &amp;#8220;&amp;gt;=&amp;#8221; While this is limited to the test group, it is also just plain not a good idea as it means any equal to or higher version of the version specified.  Using &amp;#8220;~&amp;gt;&amp;#8221; is much safer as it limits updates to point releases.&lt;/p&gt;
&lt;p&gt;Secondly, is the use of the &amp;#8220;:plugins&amp;#8221; group.  This group is there to make sure that Bundler will check the dependency requirements for this group when you bundle install, as all of these gems are in the plugins directory and without any mention in the Gemfile, Bundler would not be able to check for dependency conflicts.&lt;/p&gt;
&lt;p&gt;Thirdly, several production gems requirements have no version attached.  This is dangerous.&lt;/p&gt;
&lt;p&gt;So, first thing to do is get version numbers on all of those gems.  And the best way to do that is to log into the production environment and do a &lt;tt&gt;gem list&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Doing this found the following versions for the production gems we had no versions for:&lt;/p&gt;
&lt;pre class="ruby"&gt;
  hoptoad_notifier (2.2.0)
  ruby-openid (2.1.2)
&lt;/pre&gt;
&lt;p&gt;Additionally, we no longer use capistrano for deployment, instead relying on the nice &lt;a href="http://www.engineyard.com/blog/2010/engine-yard-cli-now-open-source/"&gt;EngineYard command line gem&lt;/a&gt; to handle this.&lt;/p&gt;
&lt;p&gt;So we insert those version numbers, and delete capistrano and we get (without including the test group for now):&lt;/p&gt;
&lt;pre class="ruby"&gt;
source :gemcutter

gem 'rails', '2.3.5'

gem 'mysql',                '2.8.1'
gem 'url_field',            '0.0.2'
gem 'ruby-openid',          '2.1.2'
gem 'hoptoad_notifier',     '~&amp;gt; 2.2.0'
gem 'engineyard',           '1.1.3'
gem 'delayed_job',          '2.0.2'

group :plugins do
  gem 'authlogic-oid',       :require =&amp;gt; 'authlogic_openid'
  gem 'authlogic',           '2.1.3'
  gem 'behavior',            '0.2.0'
  gem 'will_paginate',       '2.3.11'
  gem 'inherited_resources', '1.0.4'
end
&lt;/pre&gt;
&lt;p&gt;With this in place, we do a &lt;tt&gt;bundle install&lt;/tt&gt; followed by running our test suite, to make sure that our changes don&amp;#8217;t break anything.&lt;/p&gt;
&lt;p&gt;With the specs and cukes green, we can commit the above work as the first step complete.&lt;/p&gt;
&lt;h3&gt;Remove all vendor&amp;#8217;d gems and plugins that can be specified in the Gemfile&lt;/h3&gt;
&lt;p&gt;Next step is to get rid of that plugins group, and instead use gems or github sources directly.&lt;/p&gt;
&lt;p&gt;Looking in the vendor/plugins directory of RailsPlugins.org, we see:&lt;/p&gt;
&lt;pre class="shell"&gt;
mikel@mikel.local ~/Code/railsplugins
 $ ls vendor/plugins/
   delayed_job
   formatted-dates
   high_voltage
   hubahuba
   open_id_authentication
   project_search
   timeline_fu
   url_field
&lt;/pre&gt;
&lt;p&gt;Sharp eyes will note that we have some duplication between here and the Gemfile.  Lets remove that.&lt;/p&gt;
&lt;p&gt;Now doing this is time consuming.  The steps are as follows:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Inspect the &lt;tt&gt;vendor/plugins/plugin&lt;/tt&gt; directory and see if it has a gemspec.&lt;/li&gt;
	&lt;li&gt;If there is a gemspec, get the version and create an appropriate line in the Gemfile locked to that version&lt;/li&gt;
	&lt;li&gt;If no gemspec, search RailsPlugins.org, RubyGems.org or the appropriate plugin home page for the right gem version to use for a Rails 2.3 app and then put this in the Gemfile&lt;/li&gt;
	&lt;li&gt;If no gemspec and no gem released, skip and go to the next one.&lt;/li&gt;
	&lt;li&gt;Once the gemfile has the right version, remove the vendor/plugins directory entirely&lt;/li&gt;
	&lt;li&gt;Check the various environment.rb files (main, production, development, testing etc) and remove any &lt;tt&gt;config.gem&lt;/tt&gt; line that relates to this gem.  Use any information gleaned here to update the Gemfile line&lt;/li&gt;
	&lt;li&gt;Do a new bundle install&lt;/li&gt;
	&lt;li&gt;Run all specs or tests and cukes again and make sure you are still green&lt;/li&gt;
	&lt;li&gt;Handle any requirement errors or coding errors (if doing this has forced you onto a different incompatible gem version)&lt;/li&gt;
	&lt;li&gt;Once all specs and cukes are green, repeat with the next directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The above can take time.&lt;/p&gt;
&lt;p&gt;In our case, we had a few situations.&lt;/p&gt;
&lt;p&gt;a) We had a pluginized version of hubahuba, but in the entire app, this plugin was used &lt;span class="caps"&gt;ONCE&lt;/span&gt;.  So instead, I removed the code we were using and made a &lt;tt&gt;lib/file&lt;/tt&gt; that implemented the code we needed and just nuked the directory.  Less code is good.&lt;/p&gt;
&lt;p&gt;b) We were not using project_search any more.  So this got the boot.&lt;/p&gt;
&lt;p&gt;c) high_voltage is a gem, but that Gem only works on Rails 3.  As I know that the Rails 3 version is available we will leave it vendor&amp;#8217;d for now as there is no point doing anything else with it.&lt;/p&gt;
&lt;p&gt;With all that done, our Gemfile looked like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
source :rubygems

gem 'rails',                '2.3.5'

gem 'mysql',                '~&amp;gt; 2.8.1'
gem 'url_field',            '~&amp;gt; 0.0.2'
gem 'ruby-openid',          '~&amp;gt; 2.1.7'
gem 'rack-openid',          '~&amp;gt; 1.0.3'
gem 'hoptoad_notifier',     '~&amp;gt; 2.2.5'
gem 'engineyard'
gem 'will_paginate',        '~&amp;gt; 2.3.11'
gem 'delayed_job',          '~&amp;gt; 2.0.0'
gem 'authlogic',            '2.1.3'
gem 'behavior',             '~&amp;gt; 0.2.0'
gem 'inherited_resources',  '~&amp;gt; 1.0.4'
gem 'formatted-dates',      '~&amp;gt; 0.0.1'
gem 'timeline_fu',          '~&amp;gt; 0.3.0'

group :test do
  gem 'ZenTest'
  gem 'highline',           '~&amp;gt; 1.5.2'
  gem 'machinist',          '&amp;gt;=1.0.3'
  gem 'cucumber',           '&amp;gt;=0.3.103'
  gem 'cucumber-rails',     '&amp;gt;=0.2.4'
  gem 'database_cleaner',   '&amp;gt;=0.4.3'
  gem 'webrat',             '&amp;gt;=0.6.0'
  gem 'rspec',              '&amp;gt;=1.3.0'
  gem 'rspec-rails',        '&amp;gt;=1.3.2'
  gem 'faker',              '~&amp;gt;0.3.1'
  gem 'nokogiri'
  gem 'ruby-debug'
end
&lt;/pre&gt;
&lt;p&gt;With only high_voltage left in &lt;tt&gt;vendor/plugins&lt;/tt&gt; from the original bunch.&lt;/p&gt;
&lt;p&gt;However, I needed to add in &lt;tt&gt;open_id_authentication&lt;/tt&gt; and a fork of &lt;tt&gt;authlogic_openid&lt;/tt&gt; to get OpenID working again.  Looking through the various codes, it looks like authlogic has some issues with OpenID at the moment, so part of the Rails 3 update may be converting to Devise.&lt;/p&gt;
&lt;p&gt;Note also how I changed the requirements to be &amp;#8220;~&amp;gt;&amp;#8221; instead of locked at a version.  If you do this, run &lt;tt&gt;bundle update&lt;/tt&gt; once and run all your specs again to make sure everything passes.  Then commit your Gemfile.lock to your source control so the same version gets deployed on your production environment.&lt;/p&gt;
&lt;h3&gt;Deploy this code to staging environment, for a sanity check.&lt;/h3&gt;
&lt;p&gt;Next step is to deploy our new Gemfile based Rails app to a staging environment.  On EngineYard this is painfully easy to do, simply snapshot your production environment, and then clone it to a new name (staging).  Once done, boot up your app and do an &lt;tt&gt;ey deploy -e staging&lt;/tt&gt;.  For other hosts, I am sure you will know how to do this as well.&lt;/p&gt;
&lt;p&gt;We ran into a problem in doing this.  Our production RubyGems.org was still running on 1.8.6 and there was a gem requiring Ruby 1.8.7 as a minimum.  So we updated our Ruby version to 1.8.7 and tried again.  Due to this we now know that we will have to update our production environment to 1.8.7, so I scheduled a time to do this on the website, which gave me a good opportunity to use the new sites feature from &lt;a href="http://tellthemwhen.com"&gt;tellthemwhen.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is what our command line deploy looks like:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ ey deploy -e staging
Beginning deploy for 'railsplugins' in 'staging' on server...
Successfully installed engineyard-serverside-1.3.3
1 gem installed
~&amp;gt; Deploying revision e94f047... Removing project_search, don't need that
~&amp;gt; Pushing code to all servers
~&amp;gt; Starting full deploy
~&amp;gt; Copying to /data/railsplugins/releases/20100923133736
~&amp;gt; Ensuring proper ownership
~&amp;gt; Gemfile detected, bundling gems
~&amp;gt; Symlinking configs
~&amp;gt; Migrating: cd /data/railsplugins/releases/20100923133736 &amp;amp;&amp;amp; PATH=/data/railsplugins/releases/20100923133736/ey_bundler_binstubs:$PATH RAILS_ENV=production RACK_ENV=production MERB_ENV=production rake db:migrate --trace
~&amp;gt; Symlinking code
~&amp;gt; Restarting app servers
~&amp;gt; Cleaning up old releases
Deploy complete
&lt;/pre&gt;
&lt;p&gt;Now the staging environment deployed and tested OK, it&amp;#8217;s time to update the production site during the scheduled maintenance window and then move onto the next step, Migrate the Rails app release by release up to Rails 2.3.9.&lt;/p&gt;
&lt;p&gt;For that, I will leave until the next post.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel Lindsaar&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/a_new_protocol_for_social_interaction</id>
    <published>2010-09-19T01:31:00+00:00</published>
    <updated>2010-09-19T01:31:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/a_new_protocol_for_social_interaction"/>
    <title>A new protocol for social interaction </title>
    <content type="html">
&lt;p&gt;&lt;a href="http://lindsaar.net/2010/9/17/what_is_a_distributed_social_network"&gt;In my last post&lt;/a&gt; I discussed the bubbling up horrors of having our online identity controlled by faceless mega-corporations.  But it didn&amp;#8217;t really provide any useful direction.  This is my attempt to fill that gap.  Specifically, how should we go about sharing our thoughts and emotions online, without having to give up the ownership of our data to a centralised body?  These are my thoughts.&lt;/p&gt; &lt;p&gt;I think there are four central tenants which any information sharing protocol should subscribe to.&lt;/p&gt;
&lt;p&gt;These are;&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Ownership of data should belong to those the data is of.&lt;/li&gt;
	&lt;li&gt;Authenticity of data should be ascribed by the owners of data.&lt;/li&gt;
	&lt;li&gt;Durability of data should be as long as the owners please.&lt;/li&gt;
	&lt;li&gt;Sharing of data should not circumvent the first three principles.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When a protocol for information sharing be developed that guarantees the above four rules, then we will have social networks without an ever present demon of profitability and balance sheets hovering over us.&lt;/p&gt;
&lt;p&gt;But let me take a moment to explain what the above four rules would mean.&lt;/p&gt;
&lt;h3&gt;1. Ownership of Data&lt;/h3&gt;
&lt;p&gt;Your information is yours.  This is where Diaspora are generally on target, despite any other failings.  You should be able to post information to some location, somewhere in the world, and have complete control over that data.  At no time should it be possible for someone (or something) else to claim rights to your data.&lt;/p&gt;
&lt;p&gt;This flies in the face of the &lt;a href="http://www.facebook.com/policy.php"&gt;Facebook privacy agreement&lt;/a&gt;.  Go read it if you haven&amp;#8217;t yet.  At least skim through it.  The only place where they mention ownership of your data is the last paragraph of section 6, specifically that they reserve the right to sell your data to whom ever buys them.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.google.com/privacypolicy.html"&gt;Google&amp;#8217;s privacy policy&lt;/a&gt; also has very little to say about ownership.  In fact, it has nothing to say about how much of your data you own.  Which means you have nothing to say about it using your data in whatever way it pleases.&lt;/p&gt;
&lt;p&gt;The Apple&amp;#8217;s &lt;a href="http://www.apple.com/legal/itunes/us/terms.html"&gt;iTunes privacy policy&lt;/a&gt;, that&amp;#8217;s right, the one you click through every time there is an update to iTunes, also has a glaring, sun-flare type lack of information ownership.&lt;/p&gt;
&lt;p&gt;The crazy thing is, we all don&amp;#8217;t care.  Or at least we have been conditioned to not care.&lt;/p&gt;
&lt;p&gt;With the seemingly endless stream of platitudes coming from the mega-corporations murmuring that they will look after us, our information is safe, they will only use it to help us; it is no wonder that all of us don&amp;#8217;t care.  But go back and have a look at all of those &amp;#8220;privacy policies&amp;#8221;.  None of them say they will look after your data.  In fact &lt;span class="caps"&gt;ALL&lt;/span&gt; of them explicitly state that if they screw up and release all your data, that you waive them of any liability.&lt;/p&gt;
&lt;p&gt;So Ownership of data is king.  And the only way to ensure ownership is, well, have possession of it!  There is a great old legal saying, harking back to the early 1700s that states &amp;#8220;Possession is nine points of the law&amp;#8221;.  Over the centuries since this has become &amp;#8220;Ownership is nine tenths of the law&amp;#8221; and it is true!&lt;/p&gt;
&lt;p&gt;So for you and me, the key would be for us is ownership data.  Have control of our own micro information nodes that store, backup but most importantly, own our data.&lt;/p&gt;
&lt;p&gt;Achieving this would be relatively simple, at least in the scale of the other three items in my proposal.  We would all own a micro server which had our information crown jewels locked up some how.  Each one of these little islands of personal information would then hand out tidbits of information to those that came, offering as much or as little as we wanted, while at the same time stamping each byte of data with it&amp;#8217;s stamp of authenticity.&lt;/p&gt;
&lt;h3&gt;2. Authenticity of Data&lt;/h3&gt;
&lt;p&gt;The next key point would be the owner&amp;#8217;s ability to say &amp;#8220;Yes, this data about me is correct&amp;#8221;.  Maybe the second most important thing would be preventing any one else from saying &amp;#8220;This bit of data about that person is authentic&amp;#8221; without the owner agreeing.&lt;/p&gt;
&lt;p&gt;Being able to authenticate that data belongs to you, grants you the ability to revoke that authentication, but why is this important?&lt;/p&gt;
&lt;p&gt;I touched on it in my last post, the ability (and natural right) of a human to reinvent themselves, to start over, to become more than they ever were.  Without the ability to say &amp;#8220;That is what I did before, sure, but that is not me now.  Now I am this.&amp;#8221; then I am not quite sure what you or I are bothering to live for?  As human beings we all have the intrinsic ability to start a new life, turn over a new leaf and spin up any number of clich&#233;s that allow us to change our demeanour.&lt;/p&gt;
&lt;p&gt;But the current social networks don&amp;#8217;t allow that.  &lt;span class="caps"&gt;USA&lt;/span&gt; President Obama stated to a group of kids that they should &lt;a href="http://www.huffingtonpost.com/2009/09/08/obama-on-facebook-be-care_n_279482.html"&gt;be careful what you post on Facebook&lt;/a&gt;.  And he couldn&amp;#8217;t be more correct.  Because once you post that, then Facebook are the ones who are stating that information is true about you.  Not you.&lt;/p&gt;
&lt;p&gt;Is it really fair to say that taking a video of someone being stupid at age 17, and then posting this on Youtube, should then define that person for the rest of their lives?  No.  Of course not.  But you and I can see it.  It is there.  In video.  So it &lt;span class="caps"&gt;MUST&lt;/span&gt; be &lt;span class="caps"&gt;TRUE&lt;/span&gt;!&lt;/p&gt;
&lt;p&gt;Says who?&lt;/p&gt;
&lt;p&gt;Have you seen a hollywood movie lately?  Avatar anyone?  Can you seriously tell me that if I took a clip from Avatar and decreased the resolution to Internet standards, that you would be able to prove to me that it was not live footage of an actual planet?  No.  Of course you couldn&amp;#8217;t.  And that is the point.&lt;/p&gt;
&lt;p&gt;If we are to live in a sane and free world, then you and I should be able to stamp information about ourselves as true.  And other information not.  Then the viewer of that information could then (at their discretion) validate that data with your server, getting a confirmation.&lt;/p&gt;
&lt;p&gt;Now before you go off at me about the possible legal consequences of people covering up their crimes by &amp;#8220;deauthenticating data&amp;#8221;.  Remember people, we are talking about social networks.  If the police want to collect a file about your actions and prove that it was you who robbed the bank, then fine, they can do that and the whole beyond reasonable doubt thing.&lt;/p&gt;
&lt;p&gt;But remember in the old days, if you really screwed up your life, you could get up and move town and &lt;span class="caps"&gt;START&lt;/span&gt; &lt;span class="caps"&gt;AGAIN&lt;/span&gt;.  This is the whole point.  You should be able to revoke information and start over.  Information about yourself should only exist for as long as you allow it to.&lt;/p&gt;
&lt;h3&gt;3. Durability of Data.&lt;/h3&gt;
&lt;p&gt;Go do a google search of your name.  Don&amp;#8217;t do it as an ego trip, just do it to be shocked (like I was).  You will find information about you posting to mailing lists that have stopped sending mail almost a decade ago.  You will find all sorts of information that you never thought would be there.  And maybe you find something that you don&amp;#8217;t want to be there.&lt;/p&gt;
&lt;p&gt;This data exists as long as Google feels like persisting it.  Not a minute more.  And more importantly, not a minute less.&lt;/p&gt;
&lt;p&gt;Sure, you &lt;span class="caps"&gt;MIGHT&lt;/span&gt; be able to get hold of them and delete information from caches and data stores.  But they have no legal obligation to do as you ask.  And even if they wanted to, what profit is there in doing so?  None.  Without keeping information about you and your actions, they have nothing to offer any customer, period.  Their whole business model is defined by who did what when and allowing you to find out about it.&lt;/p&gt;
&lt;p&gt;Now, don&amp;#8217;t get me wrong.  Google has a place.  It provides an incredible research tool for our generation.  When I was at school you actually had to go to the library and lookup encyclopaedia if you wanted to see information about a famous discovery.  Now you can just google it.  It is incredible and provides us with unparalleled expansion of knowledge.&lt;/p&gt;
&lt;p&gt;However, research data, and what you had for lunch, are two very opposite ends of the information super highway.  An information sharing protocol should allow the owner of data to decide when data is no long deemed necessary to be kept, and so allow it to be destroyed.  Not made &amp;#8220;anonymous&amp;#8221;.  Not &amp;#8220;archived&amp;#8221;.  Simply nuked.&lt;/p&gt;
&lt;p&gt;If you want to keep some information around for the future generations, print it out and store it in a air tight safe.  If you want to start a new life, format your information node, and start a new one.&lt;/p&gt;
&lt;p&gt;Or, if you are happy with your life and what you are doing, keep it online, and share it with your friends.&lt;/p&gt;
&lt;h3&gt;4. Sharing of Data.&lt;/h3&gt;
&lt;p&gt;The last point is probably the hardest to get right.  Ownership can be handled by having your own private server.  Authenticity could be resolved with todays public/private key authentication.  Durability can be handled with a combination of ownership and invalidating the authenticity of data.  But sharing, now that is tough.&lt;/p&gt;
&lt;p&gt;Because the problem presents itself, whom do you share data with?  And why?&lt;/p&gt;
&lt;p&gt;Does Facebook really need to know how old you are?  I mean, sure, they need to know you are of legal age to prostitute your personal life to the Facebook gods, but do they need to know that in March I will be celebrating yet another year of being on the far wrong side of 30?  No.  Don&amp;#8217;t think so.&lt;/p&gt;
&lt;p&gt;What about iTunes?  Asking your date of birth &amp;#8220;For security reasons&amp;#8221;&amp;#8230; O.o&lt;/p&gt;
&lt;p&gt;Right.&lt;/p&gt;
&lt;p&gt;Being able to share your data would take concepts like OAuth to their logical conclusion.  Instead of allowing Google et al to be our authentication &amp;#8220;proxy&amp;#8221;, we would delegate this to our information nodes, each allowing anyone to say &amp;#8220;Hey Joe, this character is claiming to be you, is he?&amp;#8221; and get a definitive &amp;#8220;yes&amp;#8221; or &amp;#8220;no&amp;#8221;.&lt;/p&gt;
&lt;p&gt;The same information node could provide things like &amp;#8220;Yes, my owner is over 18&amp;#8221; or &amp;#8220;You want his postal address?  One sec, I&amp;#8217;ll check.&amp;#8221;&lt;/p&gt;
&lt;p&gt;There is little to no need for Facebook, iTunes or many other companies to know where I personally live.  They already have my credit card data, what more do they need?  They might need my postal address to send me an invoice, sure.  But anything else?  Nope.&lt;/p&gt;
&lt;p&gt;Providing a smart way to share data would provide us with the opportunity to be so granular with our information sharing that the existing corporate efforts would just be a proverbial bull in a china shop.&lt;/p&gt;
&lt;p&gt;And it would scare the life out of them.&lt;/p&gt;
&lt;p&gt;Imagine if you will, Facebook trying to drum up more business when it could not sell targeted ads, down to a suburb, for goods and services?  Imagine google only being able to shoot gun advertise?  Imagine the empowerment we would gain as a human collective, together, breaking free of the psycho targeted marketing campaigns that assault us daily?&lt;/p&gt;
&lt;p&gt;Nice thoughts aren&amp;#8217;t they?&lt;/p&gt;
&lt;p&gt;So being able to share data in a controlled and defined manner is just as important as the other three combined.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;So these are my thoughts and my views of a future social information sharing protocol.  What do you think?&lt;/p&gt;
&lt;p&gt;I hope I have delineated them sufficiently.&lt;/p&gt;
&lt;p&gt;If you feel strongly about it, please spread the word.  This sort of discussion needs more voices than mine.  I intend to work on such a protocol, I have no idea how or where such work will take me, but I really think that personal information needs to be under the above four tenets; Ownership, Authentication, Durability and Sharing.&lt;/p&gt;
&lt;p&gt;Simple really.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel Lindsaar&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/what_is_a_distributed_social_network</id>
    <published>2010-09-17T02:16:52+00:00</published>
    <updated>2010-09-17T02:16:52+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/what_is_a_distributed_social_network"/>
    <title>What is a distributed social network? </title>
    <content type="html">
&lt;p&gt;I&amp;#8217;ve been reflecting on the future of the &amp;#8220;social networks&amp;#8221; and contemplating on how modern solutions have gotten it wrong. These are my musings.&lt;/p&gt; &lt;p&gt;Corporatization of our social interactions will become the swan song of our current society.  It&amp;#8217;s not a matter of &lt;em&gt;if&lt;/em&gt; some big centralised body is going to screw you over with regards to the information you hold with them, but just a matter of when.&lt;/p&gt;
&lt;p&gt;The problem is that we live in an age where the balance sheet is king.  I&amp;#8217;m by no means the first person to illuminate this well known fact, many have come before me.  But it is true that unless we as a society act, and fast, then there will be no privacy, no where to run and definitely no where to hide.&lt;/p&gt;
&lt;p&gt;Harking back just a short 6 years ago, before Facebook decided to open its online doors to the world, you and I could still share photos with each other, we could send an email asking one another out to dinner, and, we could even stoop as low as calling someone on the phone, or, heavens forbid, drop in unannounced on a friend &amp;#8220;just to say hi&amp;#8221;.&lt;/p&gt;
&lt;p&gt;But now the world has changed.  I talk to friends who tell me that not being active on Facebook is social suicide, that not tweeting your innermost thoughts relegates you to the digital backwater and that refusing to post your most intimate family pics on Flickr means you must be a pervert.  But really, where is our world going?&lt;/p&gt;
&lt;p&gt;In the last year I have seen Google buzz fizz and while it is too early to call, Ping is probably just another bad smell floating around.  While Facebook continues to grow and generate profits and revenue at the expense of your privacy.  Why is that?&lt;/p&gt;
&lt;p&gt;Why is it that we spend our lives trying to amass &amp;#8220;friends&amp;#8221; in our social network, yet, look around our room, alone, and wonder where they all are?&lt;/p&gt;
&lt;p&gt;Daily we are bombarded with tweets and photos of all the &amp;#8220;cool kids&amp;#8221; doing this, or commenting on that, and wonder why we can&amp;#8217;t be like them.  We yearn for someone to retweet a post or follow our thoughts.  We are conditioned to gaze in wonder at someone&amp;#8217;s friend or follower count and wonder how it is.&lt;/p&gt;
&lt;p&gt;And then we wonder where is the social interaction in all this?&lt;/p&gt;
&lt;p&gt;Who own&amp;#8217;s your information on Facebook?&lt;/p&gt;
&lt;p&gt;Who own&amp;#8217;s the information you post on Twitter?&lt;/p&gt;
&lt;p&gt;Who own&amp;#8217;s the comment you may be compelled to leave at the bottom of this post?&lt;/p&gt;
&lt;p&gt;And in the end, who cares?&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s an interesting question.  Who does care?  Or more importantly, should you?&lt;/p&gt;
&lt;p&gt;It can be argued that you willingly put information online, therefore you are willing for other people to use that information. To a degree, this is true.  I post on this blog, you can learn an awful lot about me from this blog.  But there is a difference.  I can decide that this blog no longer represents who I am, or who I want to be, and thus change or remove it all together.&lt;/p&gt;
&lt;p&gt;Sure, there would be ghosts of the content hanging around the internet in caches and my tweets online, but after a few months or a year or so, the Google juice would run out and in the end, become irrelevant.  Why?  Because this blog is controlled by no one other than myself.&lt;/p&gt;
&lt;p&gt;Not by Mark.  Not by Larry or Sergey.  Not by Biz or Evan.  Not even by Steve or Bill.  This blog is mine and I&amp;#8217;ll do what I like with it thank you very much.&lt;/p&gt;
&lt;p&gt;And that is a key point.  Unlike other social mediums out there, I can choose to exercise my right as an individual human being and redefine whom I am.&lt;/p&gt;
&lt;p&gt;Start afresh and step out into the world yelling &amp;#8220;G&amp;#8217;Day!&amp;#8221;&lt;/p&gt;
&lt;p&gt;However, your digital finger print is actually doing to you what many corporate bodies and government institutions have been trying to do to you throughout the ages, categorise and segregate you into an powerless individual defined by your past actions and held back from the future.&lt;/p&gt;
&lt;p&gt;It could be said that an individuals sanity can be measured by how far into the future they can base their decisions on.  An insane person would be someone who could only think about the past and what has happened to them, a relatively sane person could look around in the present and make some rational decisions about their actions and how they would impact on the now.  A very sane person can look into the future and see how their actions will impact all of society.&lt;/p&gt;
&lt;p&gt;Our current online social systems are turning us into past living neurotics.  We are worried about what is online about what we did.  We want to make sure the historical record of who we are accurately depicts what we are.  In short, we are getting trapped by the very social framework that was meant to free us.&lt;/p&gt;
&lt;p&gt;Fine.&lt;/p&gt;
&lt;p&gt;But what is the solution?&lt;/p&gt;
&lt;p&gt;Not sure.&lt;/p&gt;
&lt;p&gt;I have taken a look at Diaspora.  Diaspora was born through four self proclaimed geeks who thought &amp;#8220;information should be distributed and private&amp;#8221;.  Nobel goals (pun intended).  But in looking at the &amp;#8220;open source&amp;#8221; code released, there was a really major flaw.  There was a licensing model, and even a contributors agreement that one had to digitally sign in order to be part of the movement.&lt;/p&gt;
&lt;p&gt;Excuse me?&lt;/p&gt;
&lt;p&gt;Not only that, but looking through the posts, there is one major Achilles heel. One, gigantic, insurmountable flaw in their structure.  The business model.&lt;/p&gt;
&lt;p&gt;You see, that&amp;#8217;s the point.&lt;/p&gt;
&lt;p&gt;We can&amp;#8217;t have our social networks dictated by a business model.&lt;/p&gt;
&lt;p&gt;As soon as you dictate a business model, then any humanity is lost to the balance sheet.  Any right to privacy is balanced against the profitability of maintaining that privacy.  And in that battle, we all know what wins.&lt;/p&gt;
&lt;p&gt;It is not a matter of Mark and the gang being &amp;#8220;good&amp;#8221; or &amp;#8220;evil&amp;#8221;.  It is not a matter of them developing a bullet proof privacy policy or 101 ways to click your way to not sharing anything.  It is the matter of, we are a race of individuals who gain their strength and meaning from our social interactions, and unless we are willing to stand up for those interactions, someone, somewhere is going to put a dollar figure on those interactions and suddenly they become as hollow as the &amp;#8220;cha-ching&amp;#8221; of a cash register.&lt;/p&gt;
&lt;p&gt;It matters that you have friends.&lt;/p&gt;
&lt;p&gt;It matters that you have someone to talk to.&lt;/p&gt;
&lt;p&gt;And, damn it, it matters that the mega companies of the world don&amp;#8217;t profit off the fact that I call you my friend.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/bundler_and_public_git_sources</id>
    <published>2010-09-16T17:58:00+00:00</published>
    <updated>2010-09-16T17:58:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/bundler_and_public_git_sources"/>
    <title>Bundler and Public Git Sources </title>
    <content type="html">
&lt;p&gt;If you have a public git source in your production Gemfile, then you are doing it wrong.&lt;/p&gt; &lt;p&gt;Bundler rocks.  It lets us point our Gemfile source at almost anything, a path, a git source and of course RubyGems.org.&lt;/p&gt;
&lt;p&gt;But if you are using production code, and you have something like this in it:&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem "mail", :git =&amp;gt; 'git://github.com/mikel/mail.git'
&lt;/pre&gt;
&lt;p&gt;Then you are most likely doing it wrong.&lt;/p&gt;
&lt;p&gt;Why?  Well, you have no guarantee that I will keep that repository around.  I (or any github user) could just deleted it tomorrow.  And then your deploy is broken.&lt;/p&gt;
&lt;p&gt;Not only that, the reason you are pointing to a git source is because there is some production critical feature that you need from the git source.  Otherwise, you would just be specifying the gem version in your Gemfile.&lt;/p&gt;
&lt;p&gt;So this is a recipe for disaster.&lt;/p&gt;
&lt;p&gt;I recently took over a project (Rails 2.2.2) that had over 13 gems specified in the environment.rb file using the Rails 2.x style &lt;tt&gt;config.gem&lt;/tt&gt; commands that were pointing to explicit gems inside of Github.  My first action was to go in and Fork those gems into the client&amp;#8217;s public git repository and depend on &lt;span class="caps"&gt;THOSE&lt;/span&gt; versions, ones that are under our control.&lt;/p&gt;
&lt;p&gt;Of course, the next step is to go through and remove any git dependency from the Gemfile, one by one and just revert to normal gems from somewhere like RubyGems. But this has to be done incrementally and will happen over the coming weeks.&lt;/p&gt;
&lt;p&gt;So, go through your production code, and if you are pointing at someone else&amp;#8217;s github tree, just go in and fork it and point at your own.  It is cheap insurance.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/getting-heroku-memcached-and-rails3-working</id>
    <published>2010-09-13T02:41:29+00:00</published>
    <updated>2010-09-13T02:41:29+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/getting-heroku-memcached-and-rails3-working"/>
    <title>Getting Heroku, memcached and Rails 3 working</title>
    <content type="html">
&lt;p&gt;The docs for Heroku and memecached do not cover Rails 3.  So here is the short version:&lt;/p&gt; &lt;p&gt;In your Gemfile:&lt;/p&gt;
&lt;pre class="ruby"&gt;
group :production do
  gem "memcache-client"
  gem 'memcached-northscale', :require =&amp;gt; 'memcached'
end
&lt;/pre&gt;
&lt;p&gt;In your environment.rb:&lt;/p&gt;
&lt;pre class="ruby"&gt;
config.cache_store = :mem_cache_store, Memcached::Rails.new
&lt;/pre&gt;
&lt;p&gt;Told you it was short.&lt;/p&gt;
&lt;p&gt;Oh, and remember to install the memcached add on to your app:&lt;/p&gt;
&lt;pre class="shell"&gt;
heroku addons:add memcache:5mb
&lt;/pre&gt;
&lt;p&gt;Told you it was short.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/why_bundler</id>
    <published>2010-09-10T03:22:37+00:00</published>
    <updated>2010-09-10T03:22:37+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/why_bundler"/>
    <title>Why Bundler?</title>
    <content type="html">
&lt;p&gt;I have moved all of my Rails applications, and every client application I am consulting for over to Bundler and using Gemfiles, and you should too.&lt;/p&gt; &lt;p&gt;All of my Rails 3 &lt;span class="caps"&gt;AND&lt;/span&gt; Rails 2.x applications are now running on Bundler.  Even a Rails 2.1 app that we are in the process of upgrading is running on Bundler, or at least using bundler for dependency management and configuration.&lt;/p&gt;
&lt;p&gt;Bundler is &lt;span class="caps"&gt;NOT&lt;/span&gt; some &amp;#8220;Rails 3 thing&amp;#8221; and if you have this misconception, it is time you wrapped that up into a &lt;a href="http://www.youtube.com/watch?v=OdAzdBeqPmY"&gt;small scruntchy ball and tossed it&lt;/a&gt; into the circular file.&lt;/p&gt;
&lt;p&gt;But some people try to install Bundler and report back to me &amp;#8220;It&amp;#8217;s too hard&amp;#8221; or &amp;#8220;It doesn&amp;#8217;t work&amp;#8221; and &amp;#8220;It broke my app&amp;#8221;.  Of course, in many cases, you have to configure your code correctly, but the &lt;a href="http://gembundler.com/"&gt;GemBundler site&lt;/a&gt; is full of information to do that.&lt;/p&gt;
&lt;p&gt;But once your application or ruby code is configured to use Bundler, the crazy thing is that about 9 times out of 10, any further problems is because Bundler has found a problem with your gem dependencies that you didn&amp;#8217;t even know you had.&lt;/p&gt;
&lt;p&gt;I have had many many people talk to me about Bundler, in good and bad ways, and usually, any negative comments come from a lack of understanding on why bundler, and why it is needed.&lt;/p&gt;
&lt;p&gt;Luckily, Yehuda was recently at EuRuKo in Karkow, and did this talk on &lt;a href="http://vimeo.com/12614072"&gt;Why Bundler?&lt;/a&gt;  If you haven&amp;#8217;t watched it yet, it is very well worth your time to sit through.  Many things will become clear.&lt;/p&gt;
&lt;p&gt;Oh, and a parting tip, if you are trying to get Rails 2.1 running with bundler, just configure bundler as if it was not a Rails Framework app.  Treat it like the Sinatra app examples on the Gembundler website.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails_commit_access</id>
    <published>2010-09-10T02:58:41+00:00</published>
    <updated>2010-09-10T02:58:41+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails_commit_access"/>
    <title>Rails Commit Access</title>
    <content type="html">
&lt;p&gt;Hi all, I&amp;#8217;m really happy to announce that I am the first Australian to have been invited into the commit team for Ruby on Rails!&lt;/p&gt; &lt;p&gt;About 48 hours ago, I was pleasantly surprised to read in the Rails Core campfire chat that David, Jeremy and Yehuda all decided that I should be put into the Rails commit team.&lt;/p&gt;
&lt;p&gt;While this does not mean I am part of the &amp;#8220;Core Team&amp;#8221; yet, it does mean I can help move Rails forward at a rapid rate, and also means Australia now has a local who has commit access to the &lt;a href="http://github.com/rails"&gt;Rails Organisation repositories&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mostly, this was due to my work with the &lt;a href="http://contributors.rubyonrails.org/contributors/mikel-lindsaar/commits"&gt;Action Mailer 3&lt;/a&gt; updates with Mail, but I plan to extend this to other areas like Active Resource.&lt;/p&gt;
&lt;p&gt;I am honoured to be given this access and hope to carry the torch for all Rubyists, especially those in Australia, for a long time!&lt;/p&gt;
&lt;p&gt;So you will be seeing me a lot more in the commit logs from me and I&amp;#8217;ll definitely be helping out on Rails in between my consulting work as the founder of &lt;a href="http://rubyx.com/"&gt;RubyX&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel Lindsaar&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/Introducing_TellThemWhen</id>
    <published>2010-09-09T15:44:00+00:00</published>
    <updated>2010-09-09T15:44:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/Introducing_TellThemWhen"/>
    <title>Introducing TellThemWhen</title>
    <content type="html">
&lt;p&gt;I have had a scratch I have wanted to itch for a long time, and that is about how to share times online.  &lt;a href="http://TellThemWhen.com"&gt;TellThemWhen&lt;/a&gt; is my solution to this problem.&lt;/p&gt; &lt;p&gt;The problem TellThemWhen is trying to solve is one of &amp;#8220;How do I tell Bob over in another time zone, what time I want them to do something&amp;#8221;.  Now, in many cases, Bob might be a person you deal with all the time, and you know he is 9 hours behind you, tomorrow, so all you have to do is the mental arithmetic once.  Simple (yeah, right).&lt;/p&gt;
&lt;p&gt;But what about when you have a Maintenance window coming up?  What do you tell all your customers?  Probably, like many sites out there, you go: &amp;#8220;Hi there, we will be doing maintenance at 1am &lt;span class="caps"&gt;EST&lt;/span&gt; for 15 minutes&amp;#8221;, but what is &lt;span class="caps"&gt;EST&lt;/span&gt;?  If you are in Australia, it means time on the East Coast, if you are in the &lt;span class="caps"&gt;USA&lt;/span&gt;, it means something totally different.&lt;/p&gt;
&lt;p&gt;Some sites solve this by linking to the world clock.  Which is all well and good, but, honestly, a bit rude.  Why are you making me hunt around a massive page of time zones to find the one I am closest to?&lt;/p&gt;
&lt;p&gt;So what was needed was a simple way for anyone to make an instant in time, and then share that with the world.  TellThemWhen does this.&lt;/p&gt;
&lt;p&gt;The above maintenance window could include a &lt;a href="http://tellthemwhen.com/instants/03ea28e0198e4a3011a3607f932221f1b56997d6"&gt;link to TellThemWhen&lt;/a&gt; for the downtime, and now your users, in whatever time zone they are in, will get the time, for them, in their timezone.&lt;/p&gt;
&lt;p&gt;Neat.&lt;/p&gt;
&lt;p&gt;Over the weeks I&amp;#8217;ll be blogging about some of the technology behind TellThemWhen.  Handling multiple timezones is sometimes a challenge and TellThemWhen handles it in some interesting ways.  Checking on up to three different sources for the timezone data, and then also verifying with your local computer that what we guessed is correct.&lt;/p&gt;
&lt;p&gt;So anyway, check it out.  It was fun making it with my designer, David Cruikshank (&lt;a href="http://twitter.com/thedav3"&gt;@thedav3&lt;/a&gt; on twitter) and stay tuned for more features to come!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rake_RSpec_and_Cucumber_uninitialized_constant_Rails_Boot_Bundler</id>
    <published>2010-08-29T23:27:06+00:00</published>
    <updated>2010-08-29T23:27:06+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rake_RSpec_and_Cucumber_uninitialized_constant_Rails_Boot_Bundler"/>
    <title>rake RSpec &amp; Cucumber uninitialized constant Rails::Boot::Bundler</title>
    <content type="html">
&lt;p&gt;You might run into this problem if you are bringing a Rails 2.3 app onto Bundler, specifically, when you try and run &amp;#8220;rake cucumber&amp;#8221; or just &amp;#8220;rake&amp;#8221; for RSpec you get an error about &lt;tt&gt;uninitialized constant Rails::Boot::Bundler&lt;/tt&gt;.&lt;/p&gt; &lt;p&gt;The situation is most likely that (like me) you put the preinitializer.rb file into the &lt;tt&gt;config/initializers&lt;/tt&gt; directory instead of just in the &lt;tt&gt;config/&lt;/tt&gt; directory.&lt;/p&gt;
&lt;p&gt;So double check the location as per the &lt;a href="http://gembundler.com/rails23.html"&gt;bundler guide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/this-relationship-is-worth-nothing</id>
    <published>2010-06-13T10:50:10+00:00</published>
    <updated>2010-06-13T10:50:10+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/this-relationship-is-worth-nothing"/>
    <title>This Relationship is Worth Nothing </title>
    <content type="html">
&lt;p&gt;Today was the last day I had booked in my hotel room.  I had won this room through an Internet bidding service at a heavy discount of $85 per night.  However, I needed to extend my stay in the hotel another two days and that is where this relationship went to hell.&lt;/p&gt; &lt;p&gt;I called the front desk of this hotel and asked &amp;#8220;I&amp;#8217;d like to extend my stay another couple of nights, how much would that be?&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Well, we can not give you the same rate you are on now, so it will be $200 a night to extend&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&amp;#8220;K, thanks, bye&amp;#8221;.&lt;/p&gt;
&lt;p&gt;So, what did I do?  Tried Priceline again, and what should happen?  We win another bid for two nights for $85 AT &lt;span class="caps"&gt;THE&lt;/span&gt; &lt;span class="caps"&gt;SAME&lt;/span&gt; &lt;span class="caps"&gt;HOTEL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Calling the front desk resulted in &amp;#8220;Oh, ok, come down to reception and change your key then, all good&amp;#8221;&amp;#8230;&lt;/p&gt;
&lt;p&gt;O.o&lt;/p&gt;
&lt;p&gt;So what is the difference between me calling up to extend, and me calling up with a winning bid?&lt;/p&gt;
&lt;p&gt;Nothing, except one teeny tiny thing&amp;#8230; I am an existing customer.  I have already chosen this hotel (sure based on price, but I am here none the less) and so, they have an opportunity to create a strong relationship.&lt;/p&gt;
&lt;p&gt;Which they shot in the foot.&lt;/p&gt;
&lt;p&gt;This attitude just pushes the idea that my custom, is worth nothing, zero, squat and that my relationship with the hotel is worth nothing.&lt;/p&gt;
&lt;p&gt;What did it gain the hotel?  Well, the only thing it gained them is that now I know that I can &amp;#8220;cheat&amp;#8221; their &amp;#8220;system&amp;#8221; which just means contempt.&lt;/p&gt;
&lt;p&gt;If the hotel was booked out, extending my stay at a low rate would not be good business sense.  Sure.  But it wasn&amp;#8217;t.  The hotel is half empty, and they are still offering the same price I paid through the internet.&lt;/p&gt;
&lt;p&gt;Your existing customers are your most valuable resource. That is not to say you can&amp;#8217;t entice new customers with &amp;#8220;special offers&amp;#8221;, that is fine, but remember that it is your existing customers who are paying your bills and feeding your cat.&lt;/p&gt;
&lt;p&gt;This hotel in San Francisco would have won my stay for several more nights, but now I know that I can get a similar or cheaper price on the internet, which means my custom at this hotel is purely up to the gods.&lt;/p&gt;
&lt;p&gt;And that is not good business sense.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/thank-YOU</id>
    <published>2010-06-11T14:50:46+00:00</published>
    <updated>2010-06-11T14:50:46+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/thank-YOU"/>
    <title>Thank YOU... </title>
    <content type="html">
&lt;p&gt;In his recent keynote to RailsConf 2010, &lt;a href="https://twitter.com/garyvee"&gt;Gary Vaynerchuk&lt;/a&gt; gave a wonderful talk about the power of &amp;#8220;thank you&amp;#8221;. Something we all intrinsically understand, yet not enough of us practice.&lt;/p&gt; &lt;p&gt;&amp;#8220;Say Thank You&amp;#8221; was drummed into me from a very early age, my parents always encouraged me to respect those around me, from the lowest socialite I met to the highest janitor I had the pleasure of talking shop with, I always learnt that the opportunity to create a relationship with those around me was something to be cherished and grasped tightly.&lt;/p&gt;
&lt;p&gt;After Gary&amp;#8217;s Keynote, he asked for questions, I posed the question of what his experience was with big corporates trying to &amp;#8220;manage&amp;#8221; customer complaints instead of treating them as the true gift of solid gold that they are.  Gary mentioned that he has not seen much change, and this makes me sad, but reaffirmed what I already knew from my own experiences.&lt;/p&gt;
&lt;p&gt;But some might be wondering what I am referring to.  Surely customer complaints are something that should be managed; less complaints equates to better customer service &amp;#8211; surely?!&lt;/p&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;p&gt;If you are running a business of more than one or two people, and you are not receiving any complaints, I would argue that you are doing something terribly, terribly wrong.&lt;/p&gt;
&lt;p&gt;But you might need to broaden your idea of what a complaint is.&lt;/p&gt;
&lt;p&gt;A complaint does not have to generate from bad service.  A complaint per the dictionary is &amp;#8220;a statement that a situation is unsatisfactory or unacceptable&amp;#8221;.  But there lies the rub.  A complaint is a statement, and a statement by definition is something voiced.  Your client has to gather the courage to contact you, go to the effort to find an avenue, and say or type &amp;#8220;hey, what you just did wasn&amp;#8217;t what I was expecting, and that&amp;#8217;s not cool&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&amp;#8220;What?&amp;#8221; you say.  &amp;#8220;Courage? Effort? I told my web design team to make sure there is a &amp;#8216;contact us&amp;#8217; menu item in the footer of every web page on our site&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Yeah, awesome.  You mean that 10pt link right next to the &amp;#8220;Terms of Service&amp;#8221; which unsimply says &amp;#8220;We legally don&amp;#8217;t give a shit?&amp;#8221;, that rocks, awesome positioning.&lt;/p&gt;
&lt;p&gt;How many times have you called a company to complain and been turned away?  How many times have you sent an email and been told &amp;#8220;The system says&amp;#8230; and I can&amp;#8217;t change it&amp;#8221;?  How many times have you picked up the phone to complain, stopped mid dial and just hung up again in the knowing frustration that your voice is going to be cheerily greeted by some autonomous string of 1&amp;#8217;s and 0&amp;#8217;s for 10 minutes before you get told that the customer service desk is closed and that you can&amp;#8217;t leave a message, doofus.&lt;/p&gt;
&lt;p&gt;Well, your client is the same.  If you don&amp;#8217;t make it insanely simple for them to contact you, if you don&amp;#8217;t encourage that call; 9 times out of 10, they just won&amp;#8217;t do it.  Then you my friend have lost an awesome opportunity.  Because that single call could make or break your organisation.&lt;/p&gt;
&lt;p&gt;Let me give you a personal example.  I purchased a service from a domain name hosting company.  This company claimed that their system would provide a &amp;#8220;comprehensive&amp;#8221; tool to edit and update domain names.  It cost $12 for the year.  I decided to purchase it as an option for one of my domain names.  On getting this service, I found that it did nothing like what I expected, it was a simple interface with minimal functionality.  After 5 minutes of purchasing the service, I decided that it wasn&amp;#8217;t what I needed and immediately sent a very polite email off to their support staff asking to please cancel and refund the $12.&lt;/p&gt;
&lt;p&gt;Simple request.  I mentioned politely that the advertising had promised an advanced service, and pointed out the features it did not support.  I felt very justified in my complaint and believed that shortly there after I would receive an email saying &amp;#8220;very sorry sir, we have refunded your card, thank you very much for your custom and we trust we can assist you in the future.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Instead I received a blunt email saying asking for a refund was outside the terms of service, that the money had already been charged and that if I wanted, I could receive a $12 credit towards other services they offered.&lt;/p&gt;
&lt;p&gt;Not only that, but the reply to email address on the support email was a &amp;#8220;do-not-reply@company&amp;#8221;!&lt;/p&gt;
&lt;p&gt;Long story short, I found the support email address, also mentioned their reply address was broken, asserted my right to the refund and spent another 8 emails back and forth trying to get my point across.&lt;/p&gt;
&lt;p&gt;All for $12!&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t give a toss about the $12. But this was just wrong.&lt;/p&gt;
&lt;p&gt;Finally contacting the head of accounting (O.o), I got my refund of $12 and a somewhat guarded apology.  The very next thing I did was move 15 domain names off that company to another, went and spoke to three friends of mine that used them and they are all migrating as well.&lt;/p&gt;
&lt;p&gt;All in all, customer service fail.&lt;/p&gt;
&lt;p&gt;In an alternate universe the same scenario might have gone a little like this:&lt;/p&gt;
&lt;p&gt;&amp;#8220;Hi, it seems the service I just bought doesn&amp;#8217;t do feature X which your marketing pages say it should do, I would like a refund please&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&amp;#8220;Thank you very much Mr Lindsaar for contacting us about this problem.  I have alerted marketing to get this issue resolved and have already passed your details to our accounting department to credit your card, your refund should appear within 3-4 working days.  As you took the time to alert us to this problem, I am also pleased to pass on a $10 credit for any other service we can provide you and have already applied this to your account.  Thank you for using our company.&amp;#8221;&lt;/p&gt;
&lt;p&gt;I tell you, if they did that, they would have won me as a customer for life.  And being a web application developer, that would be a not insignificant amount of business.&lt;/p&gt;
&lt;p&gt;And how much would have that token of gratitude cost them?&lt;/p&gt;
&lt;p&gt;Zero.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s right.  Nada.&lt;/p&gt;
&lt;p&gt;In fact, it would have cost them &lt;span class="caps"&gt;LESS&lt;/span&gt; than it cost to go the other way.  Remember, they had to pay that &amp;#8220;support&amp;#8221; person to sit there writing me those invalidative emails, they had to pay his senior to review each email, they had to pay (I assume) the head of accounting to take the time to read and refund my card.&lt;/p&gt;
&lt;p&gt;And they also lost all my future business.&lt;/p&gt;
&lt;p&gt;Stupid. Stupid. Stupid.&lt;/p&gt;
&lt;p&gt;So what do we have to do to bring about this alternate universe?  One where relationships take precedence over the bottom line.  Remember, the relationships will generate for you more bottom line than any discount or &amp;#8220;loyalty program&amp;#8221; will.&lt;/p&gt;
&lt;p&gt;Get into communication with your clients.&lt;/p&gt;
&lt;p&gt;Call them.  Send them an email.  Do a random survey.  Make sure that every time a customer interacts with your organisation your staff are drilled on finding out if the client has had an unsatisfactory experience with your work.  Get to know your clients, establish those relationships.&lt;/p&gt;
&lt;p&gt;Because if you establish those relationships, then the client (just like your best friend) won&amp;#8217;t be afraid to tell you that your fly is unzipped before you walk out in front of a packed audience and make a total fool of yourself.&lt;/p&gt;
&lt;p&gt;And thank &lt;span class="caps"&gt;YOU&lt;/span&gt; for taking the time to read this.  I appreciate it.&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/inline-attachments-for-actionmailer</id>
    <published>2010-06-07T23:40:00+00:00</published>
    <updated>2010-06-07T23:40:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/inline-attachments-for-actionmailer"/>
    <title>Inline Attachments for ActionMailer</title>
    <content type="html">
&lt;p&gt;ActionMailer&amp;#8217;s support for inline attachments sucks. Totally.  Until now.&lt;/p&gt; &lt;p&gt;If you have ever tried to get an inline attachment working in Rails 2.x or even Rails 3 more recently, you were faced with an uphill battle that really did not deserve to be there.&lt;/p&gt;
&lt;p&gt;For those not in the know, an Inline attachment in an email is simply an attachment that has a Content-Disposition of &amp;#8220;inline&amp;#8221; and allows you to reference it by using an &lt;span class="caps"&gt;HTML&lt;/span&gt; image tag with its source attribute pointing to &lt;tt&gt;cid:conent-id-of-image-part&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This allows you to put logos in your emails, header images etc.  All embedded within the email itself.&lt;/p&gt;
&lt;p&gt;So enough talk, this is how you do it, say you have a welcome message in your Action Mailer class, and in this welcome message you want to embed your company logo, which is conveniently located in your Rails root &amp;#8220;public/images&amp;#8221; directory.&lt;/p&gt;
&lt;p&gt;First in your mailer, you would do:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Notifier &amp;lt; ActionMailer::Base

  def welcome
    data = File.read(Rails.root.join('public/images/logo.png'))
    attachments.inline['logo.png'] = data
    mail
  end
  
end
&lt;/pre&gt;
&lt;p&gt;Notice the &lt;ins&gt;inline&lt;/ins&gt; call to attachments?  What this does is tells Mail to mark this file with a content disposition of &amp;#8220;inline&amp;#8221; instead of the usual &amp;#8220;attachment&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Then in your view you would do:&lt;/p&gt;
&lt;pre class="html"&gt;
&amp;lt;h1&amp;gt;Thank you for choosing ErnCorp!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;%= image_tag attachments['logo.png'].url -%&amp;gt;&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Here, we are just interrogating the &lt;tt&gt;mail.attachments&lt;/tt&gt; hash for the attachment with the filename &amp;#8220;logo.png&amp;#8221; and then calling &lt;ins&gt;url&lt;/ins&gt; on the attachment we fine. This generates a standard email content ID resource locator (cid tag) that looks something like: &lt;tt&gt;cid:4c0da20e13de6@mikel.local.mail&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;And that is it!&lt;/p&gt;
&lt;p&gt;Now the cool thing about this is that when you send this email, ActionMailer looks through your attachments list finding any inline attachments, if it finds some, then it changes your email to a &lt;tt&gt;multipart/related&lt;/tt&gt; content type and then makes these attachments available to the view through the attachments helper.&lt;/p&gt;
&lt;p&gt;Anyway, this is now &lt;a href="http://github.com/rails/rails/commit/311d99eef01c268cedc6e9b3bdb9abc2ba5c6bfa"&gt;pushed&lt;/a&gt;.  Enjoy and have fun!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/Upgrading_RailsPlugins_org_to_Rails_3_Part_1</id>
    <published>2010-05-18T04:34:07+00:00</published>
    <updated>2010-05-18T04:34:07+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/Upgrading_RailsPlugins_org_to_Rails_3_Part_1"/>
    <title>Upgrading RailsPlugins.org to Rails 3 - Part 1</title>
    <content type="html">
&lt;p&gt;Note, this post has been recreated now that Rails 3 has been released.  Please see: &lt;a href="http://lindsaar.net/2010/9/24/updating_railsplugins_org_to_rails_3_part_1"&gt;Updating Railsplugins.org to Rails 3&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;New version available&lt;/h3&gt;
&lt;p&gt;Please see the above new version, the below is old content and not really usable any more&lt;/p&gt;
&lt;h3&gt;Old content:&lt;/h3&gt;
&lt;p&gt;I am going to do a series of blog posts covering the upgrade of RailsPlugins.org to Rails 3.  You can follow along as we go and comments or suggestions are welcome!&lt;/p&gt;
&lt;p&gt;This upgrade was done using at least Rails 3 beta3.  If try it on anything earlier, it will most likely go boom.&lt;/p&gt;
&lt;h3&gt;Process&lt;/h3&gt;
&lt;p&gt;Going about upgrading a non trivial site like RailsPlugins.org requires a process to make sure it works:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Confirm the gems and plugins you are using either work with Rails 3, there are alternatives you can use, or you are interested in helping upgrade them &amp;#8211; this is the most important step in terms of scope and time required to get the job done.&lt;/li&gt;
	&lt;li&gt;Run all specs and features or tests and make sure they pass &amp;#8211; if you don&amp;#8217;t have any, then now would be a good time to install Cucumber and write at &lt;em&gt;least&lt;/em&gt; features covering all the main user stories of your site.&lt;/li&gt;
	&lt;li&gt;Run the rails_upgrade plugin to highlight areas of concern&lt;/li&gt;
	&lt;li&gt;Upgrade the application to Rails 3&lt;/li&gt;
	&lt;li&gt;Fix all concerns within your application itself, ignoring plugins for now&lt;/li&gt;
	&lt;li&gt;Go through each plugin and gem, either installing newer versions that are Rails 3 compatible, or replacing / fixing them&lt;/li&gt;
	&lt;li&gt;Run all specs and features and tests and make sure they pass&lt;/li&gt;
	&lt;li&gt;Boot up and play around in your development environment&lt;/li&gt;
	&lt;li&gt;Deploy on a staging environment to confirm your upgrade&lt;/li&gt;
	&lt;li&gt;Deploy live and watch like a hawk.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I am going to document all these steps as part of upgrading the RailsPlugins.org site.&lt;/p&gt;
&lt;h3&gt;Confirm the gems and plugins you are using&lt;/h3&gt;
&lt;p&gt;Going through all the plugins and gems we use on the RailsPlugins.org site, showed up that most of them have Rails 3 versions available or listed as &amp;#8220;Maybe&amp;#8221;.  I guess I&amp;#8217;ll be helping people get it done! :)&lt;/p&gt;
&lt;h3&gt;Run all specs and features&lt;/h3&gt;
&lt;p&gt;I have good coverage on RailsPlugins.org and it is all green&amp;#8230; so onward and upwards.&lt;/p&gt;
&lt;h3&gt;Run the upgrade plugin&lt;/h3&gt;
&lt;p&gt;The rails_upgrade plugin is hosted on github and up to date with all the latest bells and whistles of Rails 3, so we&amp;#8217;ll use that:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ script/plugin install git://github.com/rails/rails_upgrade.git
&lt;/pre&gt;
&lt;p&gt;And then once installed, we do:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ rake rails:upgrade:check
&lt;/pre&gt;
&lt;p&gt;Which gives us &lt;em&gt;pages&lt;/em&gt; of output, simplified down to:&lt;/p&gt;
&lt;pre class="shell"&gt;
Deprecated constant(s)
Constants like RAILS_ENV, RAILS_ROOT, and RAILS_DEFAULT_LOGGER are now deprecated.
More information: http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/
...

Deprecated session secret setting
Previously, session secret was set directly on ActionController::Base; it's now config.secret_token.
More information: http://weblog.rubyonrails.org/
...

Old session store setting
Previously, session store was set directly on ActionController::Base; it's now config.session_store :whatever.
More information: http://weblog.rubyonrails.org/
...

Deprecated ActionMailer API
You're using the old ActionMailer API to send e-mails in a controller, model, or observer.
More information: http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3
...

Old ActionMailer class API
You're using the old API in a mailer class.
More information: http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3
...

Soon-to-be-deprecated ActiveRecord calls
Methods such as find(:all), find(:first), finds with conditions, and the :joins option will soon be deprecated.
More information: http://m.onkey.org/2010/1/22/active-record-query-interface
...

named_scope is now just scope
The named_scope method has been renamed to just scope.
More information: http://github.com/rails/rails/commit/d60bb0a9e4be2ac0a9de9a69041a4ddc2e0cc914
...

Old Rails generator API
A plugin in the app is using the old generator API (a new one may be available at http://github.com/trydionel/rails3-generators).
More information: http://blog.plataformatec.com.br/2010/01/discovering-rails-3-generators/
...

Old router API
The router API has totally changed.
More information: http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/
...

Deprecated ERb helper calls
Block helpers that use concat (e.g., form_for) should use &amp;lt;%= instead of &amp;lt;%. The current form will continue to work for now, but you will get deprecation warnings since this form will go away in the future.
More information: http://weblog.rubyonrails.org/
...

New file needed: config/application.rb
You need to add a config/application.rb.
More information: http://omgbloglol.com/post/353978923/the-path-to-rails-3-approaching-the-upgrade
...
&lt;/pre&gt;
&lt;p&gt;OK, so this might be too long for a single blog post, let&amp;#8217;s take it in sections then.&lt;/p&gt;
&lt;h3&gt;Deprecated constant(s)&lt;/h3&gt;
&lt;p&gt;This section produced the following output:&lt;/p&gt;
&lt;pre class="shell"&gt;
Deprecated constant(s)
Constants like RAILS_ENV, RAILS_ROOT, and RAILS_DEFAULT_LOGGER are now deprecated.
More information: http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/

The culprits: 
  - /Users/mikel/Code/railsplugins/lib/tasks/environments.rake
  - /Users/mikel/Code/railsplugins/lib/tasks/cucumber.rake
  - /Users/mikel/Code/railsplugins/lib/tasks/hoptoad_notifier_tasks.rake
  - /Users/mikel/Code/railsplugins/lib/tasks/rspec.rake
&lt;/pre&gt;
&lt;p&gt;Which doesn&amp;#8217;t seem too bad.  I only really have one file in my application that is to blame, environments.rake, the other three are part of plugins that RailsPlugins.org uses, and I trust that the Rails 3 versions of these which we will update to later, should handle themselves.&lt;/p&gt;
&lt;p&gt;Opening up environments.rake we see:&lt;/p&gt;
&lt;pre class="shell"&gt;
# Sets environments as needed for rake tasks
%w[development production staging].each do |env|
  desc "Runs the following task in the #{env} environment" 
  task env do
    RAILS_ENV = ENV['RAILS_ENV'] = env
  end
end

task :testing do
  Rake::Task["test"].invoke
end

task :dev do
  Rake::Task["development"].invoke
end

task :prod do
  Rake::Task["production"].invoke
end
&lt;/pre&gt;
&lt;p&gt;This is a custom rake file we use to easily set environments for rake tasks.  However, setting &lt;tt&gt;RAILS_ENV&lt;/tt&gt; is deprecated in Rails 3.  In Rails 3, you can set &lt;tt&gt;Rails.env&lt;/tt&gt; directly with an assignment.  So changing this rake task to be Rails 3 compatible would be:&lt;/p&gt;
&lt;pre class="shell"&gt;
# Sets environments as needed for rake tasks
%w[development production staging].each do |env|
  desc "Runs the following task in the #{env} environment" 
  task env do
    Rails.env = env
  end
end

task :testing do
  Rake::Task["test"].invoke
end

task :dev do
  Rake::Task["development"].invoke
end

task :prod do
  Rake::Task["production"].invoke
end
&lt;/pre&gt;
&lt;p&gt;OK good.  As I mentioned above, we are going to eave the cucumber, rspec and hoptoad files to be updated by their respective gems as we move along.&lt;/p&gt;
&lt;h3&gt;Deprecated session secret setting&lt;/h3&gt;
&lt;p&gt;The rails_upgrade plugin has pointed out the following:&lt;/p&gt;
&lt;pre class="shell"&gt;
Deprecated session secret setting
Previously, session secret was set directly on ActionController::Base; it's now config.secret_token.
More information: http://weblog.rubyonrails.org/

The culprits: 
	- /Users/mikel/Code/railsplugins/config/initializers/session_store.rb

Old session store setting
Previously, session store was set directly on ActionController::Base; it's now config.session_store :whatever.
More information: http://weblog.rubyonrails.org/

The culprits: 
  - /Users/mikel/Code/railsplugins/config/initializers/session_store.rb
&lt;/pre&gt;
&lt;p&gt;Which looks like this:&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;config/initializers/session_store.rb&lt;/tt&gt;&lt;br /&gt;
&lt;pre class="ruby"&gt;&lt;br /&gt;
ActionController::Base.session = {&lt;br /&gt;
  :key         =&amp;gt; &amp;#8216;_plugins_session&amp;#8217;,&lt;br /&gt;
  :secret      =&amp;gt; &amp;#8216;somereallylongrandomkey&amp;#8217;&lt;br /&gt;
}&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In Rails 3, this process was changed quite significantly, with this commit, the upgrade though is very straight forward.  First, you reduce &lt;tt&gt;session_store.rb&lt;/tt&gt; to the following:&lt;/p&gt;
&lt;pre class="ruby"&gt;
Rails.application.config.session_store :cookie_store, :key =&amp;gt; "_my_app_name_session"
&lt;/pre&gt;
&lt;p&gt;And then, because we now need somewhere to store the secret, you create a new file called &lt;tt&gt;config/initializers/cookie_verification_secret.rb&lt;/tt&gt; and put inside of it:&lt;/p&gt;
&lt;pre class="ruby"&gt;
Rails.application.config.cookie_secret = 'somereallylongrandomkey'
&lt;/pre&gt;
&lt;p&gt;If instead of using cookies, you were using active record as the store, then you obviously wouldn&amp;#8217;t need the &lt;tt&gt;cookie_verification_secret.rb&lt;/tt&gt; file and instead would insert any other config you needed into its own file inside of initializers.&lt;/p&gt;
&lt;p&gt;This gives us the added bonus of being able to exclude cookie secrets from source control systems.&lt;/p&gt;
&lt;p&gt;In the next instalment, we&amp;#8217;ll cover getting the RailsPlugins.org site actually up and running on Rails 3.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/stripping-dollar-signs-and-commas-from-a-string</id>
    <published>2010-05-14T02:07:33+00:00</published>
    <updated>2010-05-14T02:07:33+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/stripping-dollar-signs-and-commas-from-a-string"/>
    <title>Stripping dollar signs and commas from a string</title>
    <content type="html">
&lt;p&gt;It is moments like these that you realise why it is you love Ruby so much&amp;#8230;&lt;/p&gt; &lt;p&gt;Today was one of those moments with the String class&amp;#8217;s &lt;tt&gt;:delete&lt;/tt&gt; method.&lt;/p&gt;
&lt;p&gt;I have used this method many, many times in the past.. and this is nothing new for me&amp;#8230; but it was one of those moments where I just went &amp;#8220;Gee, I love coding in Ruby&amp;#8230;&amp;#8221; and I wanted to share :)&lt;/p&gt;
&lt;p&gt;If you ever need to convert, say &lt;tt&gt;$12,345.12&lt;/tt&gt; into a single float number like &lt;tt&gt;12345.12&lt;/tt&gt; a Ruby newbie, might do something like this:&lt;/p&gt;
&lt;pre class="ruby" lang="ruby" data-caption="how not to do it"&gt;
"$12,345.12".gsub("$",'').gsub(",",'') #=&amp;gt; "12345.12"
&lt;/pre&gt;
&lt;p&gt;But hark! Look into the &lt;a href="http://ruby-doc.org/core/classes/String.html"&gt;string class&lt;/a&gt; and you shall find the &lt;tt&gt;:delete&lt;/tt&gt; method, which lets you do this:&lt;/p&gt;
&lt;pre class="ruby" lang="ruby" data-caption="how not to do it"&gt;
"$12,345.12".delete("$,") #=&amp;gt; "12345.12"
&lt;/pre&gt;
&lt;p&gt;Ahhh&amp;#8230; pure Ruby bliss.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/Getting-Rails-3-Edge-with-jQuery-RSpec-and-Cucumber-using-RVM</id>
    <published>2010-05-09T22:08:27+00:00</published>
    <updated>2010-05-09T22:08:27+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/Getting-Rails-3-Edge-with-jQuery-RSpec-and-Cucumber-using-RVM"/>
    <title>Getting Rails 3 Edge with jQuery, RSpec and Cucumber using RVM </title>
    <content type="html">
&lt;p&gt;Here are the simple (?) steps to get Rails 3 running with the above technologies.&lt;/p&gt; &lt;h3&gt;Install Rails&lt;/h3&gt;
&lt;p&gt;You know, this is pretty obvious, but before you get into any other hoo ha you are going to have to get a version of Rails installed into your system gems so that you will have access to the &lt;tt&gt;rails&lt;/tt&gt; command.&lt;/p&gt;
&lt;p&gt;So:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="installing Rails 3"&gt;
$ gem install rails --version "3.0.0.beta3"
Successfully installed i18n-0.3.7
Successfully installed tzinfo-0.3.20
Successfully installed builder-2.1.2
Successfully installed memcache-client-1.8.3
Successfully installed activesupport-3.0.0.beta3
Successfully installed activemodel-3.0.0.beta3
....
&lt;/pre&gt;
&lt;p&gt;Should do the trick.&lt;/p&gt;
&lt;h3&gt;Setup the Rails app&lt;/h3&gt;
&lt;p&gt;Now we have Rails install our app using the standard &lt;tt&gt;rails g&lt;/tt&gt; command.&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="creating an app"&gt;
$ rails my_app -JT
     create  
     create  README
     create  .gitignore
     create  Rakefile
     create  config.ru
     create  Gemfile
     ....
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;-J&lt;/tt&gt; parameter, tells Rails not to install the Prototype Javascript libraries.  The &lt;tt&gt;-T&lt;/tt&gt; tells it to skip generating the &lt;tt&gt;Test::Unit&lt;/tt&gt; files, together they order &lt;a href="http://www.youtube.com/watch?v=SLtwFugudZE"&gt;Cheese Royals&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Setting up &lt;span class="caps"&gt;RVM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Now change into the my_app directory and add the line &lt;tt&gt;rvm ruby-1.8.7@my_app&lt;/tt&gt; to the &lt;tt&gt;.rvmrc file&lt;/tt&gt;&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="making an RVMRC file"&gt;
$ echo "rvm ruby-1.8.7@my_app" &amp;gt; .rvmrc
&lt;/pre&gt;
&lt;p&gt;This will make a clean gemset for our Rails app to play in.&lt;/p&gt;
&lt;p&gt;But we need to create the gemset first:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="making the gemset"&gt;
$ rvm gemset create 'my_app'
Gemset 'my_app' created.
&lt;/pre&gt;
&lt;p&gt;Nice.&lt;/p&gt;
&lt;p&gt;Now whenever we &lt;tt&gt;cd&lt;/tt&gt; into the &lt;tt&gt;my_app&lt;/tt&gt; directory, &lt;span class="caps"&gt;RVM&lt;/span&gt; will auto detect the &lt;tt&gt;.rvmrc&lt;/tt&gt; file and switch our gemset to the &lt;tt&gt;my_app&lt;/tt&gt; Gemset.&lt;/p&gt;
&lt;p&gt;Or we can do it manually:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="changing gemsets manually"&gt;
$ rvm ruby-1.8.7@my_app
$ gem list

*** LOCAL GEMS ***

rake (0.8.7)
&lt;/pre&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;h3&gt;House Keeping&lt;/h3&gt;
&lt;pre lang="shell" class="shell" data-caption="cleaning up the app"&gt;
$ cd my_app/
$ rm public/index.html
$ rm public/images/rails.png 
&lt;/pre&gt;
&lt;p&gt;Notice I deleted the &lt;tt&gt;index.html&lt;/tt&gt; and &lt;tt&gt;rails.png&lt;/tt&gt; above.  You don&amp;#8217;t &lt;em&gt;have&lt;/em&gt; to do this right now, if you want to see the nice happy message telling you that daisies are going to bloom and butterflies are fluttering about because your Rails App is now working, please don&amp;#8217;t remove it yet, wait and fire up your rails app with &lt;tt&gt;rails s&lt;/tt&gt; and browse to &lt;tt&gt;http://127.0.0.1:3000&lt;/tt&gt; and bask in your RailsFuNess&amp;#8230;&lt;/p&gt;
&lt;p&gt;But for the rest of us, nuke it.&lt;/p&gt;
&lt;h3&gt;Getting jQuery installed&lt;/h3&gt;
&lt;p&gt;Next, we need to install jQuery.  Just go to the website and download it and place it into your javascripts directory.  For cut and fiends out there, this curl command should handle it as well:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="downloading jQuery"&gt;
$ mkdir public/javascripts/jquery
$ curl http://code.jquery.com/jquery-1.4.2.min.js &amp;gt; public/javascripts/jquery/jquery-1.4.2.min.js
&lt;/pre&gt;
&lt;p&gt;Note I have put this into a jQuery folder.  I have done this so that the &lt;tt&gt;javascript_include_tag :all&lt;/tt&gt; command I will use further down does not pickup the jQuery source files.&lt;/p&gt;
&lt;h3&gt;Getting the Rails jQuery Driver&lt;/h3&gt;
&lt;p&gt;Now that we have destroyed prototype, we need to replace it with jQuery, two steps to this.&lt;/p&gt;
&lt;p&gt;First, download the jQuery driver and over write your &lt;tt&gt;rails.js&lt;/tt&gt; file that lives in &lt;tt&gt;public/javascripts/&lt;/tt&gt;, I usually do this by going to the &lt;a href="http://github.com/rails/jquery-ujs/blob/master/src/rails.js"&gt;Rails jQuery-&lt;span class="caps"&gt;UJS&lt;/span&gt;&lt;/a&gt; page and clicking raw and cut and pasting it into the &lt;tt&gt;public/javascripts/rails.js&lt;/tt&gt; file.  Feel free to use a submodule if you wish, or&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="installing the jQuery driver"&gt;
$ curl http://github.com/rails/jquery-ujs/raw/59dd91d945570391f905b1e40444e5921dbc2b8f/src/rails.js &amp;gt; public/javascripts/rails.js
&lt;/pre&gt;
&lt;p&gt;Will do it as well&amp;#8230; note, this will most likely &lt;em&gt;not&lt;/em&gt; be the most recent version in the future.  To get the latest, go to the &lt;a href="http://github.com/rails/jquery-ujs/blob/master/src/rails.js"&gt;Rails jQuery-&lt;span class="caps"&gt;UJS&lt;/span&gt;&lt;/a&gt; page and click on the &lt;span class="caps"&gt;RAW&lt;/span&gt; link to the right of the source code div.&lt;/p&gt;
&lt;h3&gt;Wiring up jQuery and the Rails driver&lt;/h3&gt;
&lt;p&gt;Now that we have jQuery and the Rails jQuery &lt;span class="caps"&gt;UJS&lt;/span&gt; drivers installed, we need to wire them up to the app, so open up &lt;tt&gt;app/views/layouts/application.html.erb&lt;/tt&gt; make it look like the following:&lt;/p&gt;
&lt;pre lang="erb" class="ruby" data-caption="adding jQuery and rails.js"&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;MyApp&amp;lt;/title&amp;gt;
  &amp;lt;%= stylesheet_link_tag :all %&amp;gt;
  &amp;lt;%= csrf_meta_tag %&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;%= yield %&amp;gt;

&amp;lt;%= javascript_include_tag 'jquery/jquery-1.4.2.min' %&amp;gt;
&amp;lt;%= javascript_include_tag :all, :cache =&amp;gt; true %&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;p&gt;OK, couple of things here.  Firstly, we remove the &lt;tt&gt;javascript_include_tag :all&lt;/tt&gt; from the header.  Then we put the two tags at the bottom of the document.&lt;/p&gt;
&lt;p&gt;Why do we separate out the &lt;tt&gt;jquery/jquery-1.4.2.min&lt;/tt&gt; from the &lt;tt&gt;javascript_include_tag :all&lt;/tt&gt; line?  This is because the &lt;tt&gt;:all&lt;/tt&gt; directive will just grab all the javascript files in the order it finds them and bundle them all together, which means that your javascript files, may be trying to init javascript classes from your jQuery library that do not exist yet.&lt;/p&gt;
&lt;p&gt;So we get around this by loading jQuery first.&lt;/p&gt;
&lt;p&gt;OK. So that is jQuery sorted, now onto the specifications side.&lt;/p&gt;
&lt;h3&gt;Installing RSpec &amp;amp; Friends&lt;/h3&gt;
&lt;p&gt;Best way to go about this, is to modify your &lt;tt&gt;Gemfile&lt;/tt&gt; and make it look something like this:&lt;/p&gt;
&lt;pre lang="ruby" class="ruby" data-caption="Gemfile"&gt;
source 'http://rubygems.org'

## Bundle edge rails:
gem "rails",  :git =&amp;gt; "git://github.com/rails/rails.git"
gem "sqlite3-ruby"

group :test do
  gem "rspec"
  gem "rspec-rails",      "&amp;gt;= 2.0.0.beta"
  gem "machinist",        :git =&amp;gt; "git://github.com/notahat/machinist.git"
  gem "faker"
  gem "ZenTest"
  gem "autotest"
  gem "autotest-rails"
  gem "cucumber",         :git =&amp;gt; "git://github.com/aslakhellesoy/cucumber.git"
  gem "database_cleaner", :git =&amp;gt; 'git://github.com/bmabey/database_cleaner.git'
  gem "cucumber-rails",   :git =&amp;gt; "git://github.com/aslakhellesoy/cucumber-rails.git"
  gem "capybara"
  gem "capybara-envjs"
  gem "launchy"
  gem "ruby-debug"
end
&lt;/pre&gt;
&lt;p&gt;This is going to install everything you need to get RSpec, Cucumber, Machinist, autotest and even throwing in the Ruby Debugger at the bottom.&lt;/p&gt;
&lt;p&gt;Save this, and then we need to install it.  But remember, we are on a clean gemset, so we need to install bundler first:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="installing bundler"&gt;
 $ gem install bundler
Successfully installed bundler-0.9.25
1 gem installed
Installing ri documentation for bundler-0.9.25...
Installing RDoc documentation for bundler-0.9.25...

mikel@baci.lindsaar.net ~/Code/my_app
 $ gem list

*** LOCAL GEMS ***

bundler (0.9.25)
rake (0.8.7)
&lt;/pre&gt;
&lt;p&gt;Good to go, so now we are just a &lt;tt&gt;bundle install&lt;/tt&gt; away from launching:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="bundle installing"&gt;
 $ bundle install
Fetching source index from http://rubygems.org/
Using rake (0.8.7) from system gems 
Installing abstract (1.0.0) from .gem files at /Users/mikel/.rvm/gems/ruby-1.8.7-p249@my_app/cache 
...
&lt;/pre&gt;
&lt;p&gt;And we are away!&lt;/p&gt;
&lt;h3&gt;Initializing RSpec and Cucumber&lt;/h3&gt;
&lt;p&gt;Now that we have all our dependencies done, we need to tell RSpec and Cucumber to get a move on:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="initialising RSpec"&gt;
$ rails g rspec:install
      exist  lib
     create  lib/tasks/rspec.rake
      exist  config/initializers
     create  config/initializers/rspec_generator.rb
     create  spec
     create  spec/spec_helper.rb
     create  autotest
     create  autotest/discover.rb
&lt;/pre&gt;
&lt;p&gt;And then for cucumber, we will use capybara (because we installed it in the Gemfile above) and pass &lt;tt&gt;&amp;#8212;rspec&lt;/tt&gt; because I like being complete!&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="initialising Cucumber"&gt;
$ rails g cucumber:skeleton --capybara --rspec
     create  config/cucumber.yml
     create  script/cucumber
      chmod  script/cucumber
     create  features/step_definitions
     create  features/step_definitions/web_steps.rb
     create  features/support
     create  features/support/paths.rb
     create  features/support/env.rb
      exist  lib/tasks
     create  lib/tasks/cucumber.rake
       gsub  config/database.yml
       gsub  config/database.yml
      force  config/database.yml
&lt;/pre&gt;
&lt;p&gt;OK good.. so that is our skeleton app.&lt;/p&gt;
&lt;p&gt;One last thing, we are using Rails with sqlite, so it will expect our databases to exist before it will run any tests, so let&amp;#8217;s make them:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="making databases"&gt;
$ rake db:create
&lt;/pre&gt;
&lt;h3&gt;Getting our first feature to run&lt;/h3&gt;
&lt;p&gt;Now that we have our app installed and everything wired up, we should be able to get an initial feature working, so go ahead and make a &lt;tt&gt;features/the_home_page.feature&lt;/tt&gt; file, and whack something like this in it:&lt;/p&gt;
&lt;pre lang="fixed" class="fixed" data-caption="features/the_home_page.feature"&gt;
Feature: Manage app_should_boots
  In order to see what my app is about
  a user
  wants to be able to land on a home page
  
  Scenario: Visiting the site for the first time
    Given I am on the home page
    Then I should see "Welcome" within "h1"
&lt;/pre&gt;
&lt;p&gt;This should fail:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption=""&gt;
Using the default profile...
.F

(::) failed steps (::)

scope '//h1' not found on page (Capybara::ElementNotFound)
./features/step_definitions/web_steps.rb:14:in `with_scope'
./features/step_definitions/web_steps.rb:108:in `/^(?:|I )should see "([^\"]*)"(?: within "([^\"]*)")?$/'
features/the_home_page.feature:8:in `Then I should see "Welcome" within "h1"'

Failing Scenarios:
cucumber features/the_home_page.feature:6 # Scenario: Visiting the site for the first time
&lt;/pre&gt;
&lt;p&gt;Which is saying that the default rails &amp;#8220;Not Found&amp;#8221; page does not have &amp;#8220;Welcome&amp;#8221; within a &amp;#8220;h1&amp;#8221; tag&amp;#8230; which I guess is true!&lt;/p&gt;
&lt;p&gt;Lets fix this:&lt;/p&gt;
&lt;p&gt;First we&amp;#8217;ll generate the welcome controller:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="generate welcome controller"&gt;
$ rails g controller welcome
     create  app/controllers/welcome_controller.rb
     invoke  erb
     create    app/views/welcome
     invoke  rspec
     create    spec/controllers/welcome_controller_spec.rb
     create    spec/views/welcome
     invoke  helper
     create    app/helpers/welcome_helper.rb
     invoke    rspec
&lt;/pre&gt;
&lt;p&gt;Then we&amp;#8217;ll edit the &lt;tt&gt;config/routes.rb&lt;/tt&gt; file to wire up the root url to the welcome controllers index action:&lt;/p&gt;
&lt;pre lang="ruby" class="ruby" data-caption="config/routes.rb"&gt;
MyApp::Application.routes.draw do |map|
  root :to =&amp;gt; "welcome#index"
end
&lt;/pre&gt;
&lt;p&gt;Note, if you haven&amp;#8217;t already deleted the &lt;tt&gt;public/index.html&lt;/tt&gt; file, now is a good time to do it!&lt;/p&gt;
&lt;p&gt;Now we make an &lt;tt&gt;app/views/welcome/index.html.erb&lt;/tt&gt; file and put in it our welcome message:&lt;/p&gt;
&lt;pre lang="erb" class="ruby" data-caption="app/views/welcome/index.html.erb"&gt;
&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And now we will re-run our cucumber feature and all should be good:&lt;/p&gt;
&lt;pre lang="shell" class="shell" data-caption="cucumber feature output"&gt;
 $ rake cucumber
Using the default profile...
..

1 scenario (1 passed)
2 steps (2 passed)
0m0.214s
&lt;/pre&gt;
&lt;p&gt;Cool!  We are now on the Rails with Cucumber and everything else that is good in the world.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/actionmailer_go_proc_thyself</id>
    <published>2010-05-03T10:11:00+00:00</published>
    <updated>2010-05-03T10:11:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/actionmailer_go_proc_thyself"/>
    <title>Action Mailer, go Proc thyself</title>
    <content type="html">
&lt;p&gt;On my recent &lt;a href="http://www.railsdispatch.com/posts/actionmailer"&gt;Rails Dispatch&lt;/a&gt; screen cast, I had a seemingly innocent example of a default header, using &lt;tt&gt;Time.now&lt;/tt&gt; to insert a time stamp.&lt;/p&gt; &lt;p&gt;It was an innocent thing, and truthfully, I had it there more as an example than something I would do in production.&lt;/p&gt;
&lt;p&gt;Nevertheless, good Ruby aficionados will recognise the mistake from a thousand miles away, the default hash inside of Action Mailer gets read, parsed and evaluated at compile time, not on a per message basis&amp;#8230; which makes it basically useless as a Time stamp.&lt;/p&gt;
&lt;p&gt;Rick DeNatale pointed this out in a question to me at &lt;a href="http://www.railsdispatch.com/community/questions/"&gt;RailsDispatch&lt;/a&gt;, he also asked if Action Mailer supports Proc objects inside of the default hash.&lt;/p&gt;
&lt;p&gt;Sadly, the answer was no.&lt;/p&gt;
&lt;p&gt;But then a &lt;a href="http://github.com/rails/rails/commit/ceaa100e59c7953ce5c0e978ddd6d5bc046c9fd9"&gt;few hours later&lt;/a&gt; it was yes!&lt;/p&gt;
&lt;p&gt;So now you can pass in &lt;tt&gt;Proc&lt;/tt&gt; objects to your Action Mailer class default method, like so:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Notifier &amp;lt; ActionMailer::Base
  default :to =&amp;gt; 'system@test.lindsaar.net',
          :subject =&amp;gt; Proc.new { give_a_greeting }

  def welcome
    mail
  end
  
  private
  
  def give_a_greeting
    "This is a greeting at #{Time.now}"
  end
end
&lt;/pre&gt;
&lt;p&gt;Which would then call the &lt;tt&gt;give_a_greeting&lt;/tt&gt; method on your Mailer instance to create a value to assign to the subject field.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/the-real-news-donation-drive</id>
    <published>2010-04-30T10:33:35+00:00</published>
    <updated>2010-04-30T10:33:35+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/the-real-news-donation-drive"/>
    <title>The Real News Donation Drive</title>
    <content type="html">
&lt;p&gt;If you haven&amp;#8217;t checked out the &lt;a href="https://therealnews.com/"&gt;The Real News Network&lt;/a&gt;, now is the time.&lt;/p&gt; &lt;p&gt;The Real News are not supported by corporate or government funding, they don&amp;#8217;t have to report to anyone except you and me, people who fund them for the only real independent news agency in the world.&lt;/p&gt;
&lt;p&gt;They are on a fundraising drive right now to raise $500,000 in 24 hours to fund the next six months worth or programming.  It is worth your money to go and make your donation.&lt;/p&gt;
&lt;p&gt;I just pledged my monthly donation to this worthy cause.  No where else can you get unbiased views.  If you want an independent news feed that is not bought by the corporate masses, go and give them a small or large donation, better yet, sign up for $10 per month like I did to help fund it on an ongoing basis!&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t know about you, but I am sick of the mass media, calm the masses, issue dodging drivel that spews from our poor excuses for news media.  It is obviously bought out by vested interests&amp;#8230; but people power can win!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/actionmailer_screencast_and_article</id>
    <published>2010-04-24T04:43:14+00:00</published>
    <updated>2010-04-24T04:43:14+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/actionmailer_screencast_and_article"/>
    <title>ActionMailer ScreenCast and Article</title>
    <content type="html">
&lt;p&gt;I was asked by the guys at EngineYard (who have created RailsDispatch) to host this week&amp;#8217;s topic, &lt;a href="http://www.railsdispatch.com/posts/actionmailer/"&gt;ActionMailer&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Of course I agreed, and the result is &lt;a href="http://www.railsdispatch.com/posts/actionmailer/"&gt;now online&lt;/a&gt;.  There is a shortish (10 minute) screen cast as well as a very detailed article.&lt;/p&gt;
&lt;p&gt;The article really goes into depth on ActionMailer, I tried to cover all the major points and walk through all the parts that I felt were important.  The screen cast shows you just how easy it is to setup email now.&lt;/p&gt;
&lt;p&gt;Please feel free to let me know what you think in the comments here!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/installing_rspec_for_rails_3</id>
    <published>2010-04-14T20:48:06+00:00</published>
    <updated>2010-04-14T20:48:06+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/installing_rspec_for_rails_3"/>
    <title>Installing RSpec for Rails 3</title>
    <content type="html">
&lt;p&gt;Installing RSpec for Rails 3 was quite simple, here is a short guide to make sure you can also do it :)&lt;/p&gt; &lt;p&gt;For a Rails 3 app, simply edit the Gemfile and put this into the test section:&lt;/p&gt;
&lt;pre class="ruby"&gt;
group :test do
  gem "rspec-rails",      "&amp;gt;= 2.0.0.beta"
  gem "autotest"
  gem "autotest-rails"
end
&lt;/pre&gt;
&lt;p&gt;Then from your Rails root do:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ bundle install
&lt;/pre&gt;
&lt;p&gt;Once installed, you will need to tell RSpec to install itself:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ script/rails g rspec:install
       exist  lib
      create  lib/tasks/rspec.rake
       exist  config/initializers
      create  config/initializers/rspec_generator.rb
       exist  spec
      create  spec/spec_helper.rb
      create  autotest
      create  autotest/discover.rb
&lt;/pre&gt;
&lt;p&gt;Then you should just be able to run Autotest:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ autotest
loading autotest/rails_rspec2
style: RailsRspec2
/Users/mikel/.rvm/rubies/ruby-1.8.7-p249/bin/ruby &amp;lt;snip&amp;gt;
........

Finished in 0.30205 seconds
8 examples, 0 failures
&lt;/pre&gt;
&lt;p&gt;Nice.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/i_am_speaking_at_railsconf_2010</id>
    <published>2010-04-12T05:51:17+00:00</published>
    <updated>2010-04-12T05:51:17+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/i_am_speaking_at_railsconf_2010"/>
    <title>I am speaking at RailsConf 2010</title>
    <content type="html">
&lt;p&gt;If you visit my website, you can see the badge, and it is true, this Aussie munchkin is making the trek to the US of A to talk to a bunch of people about a little section of Rails.&lt;/p&gt; &lt;p&gt;The talk is called &amp;#8220;Itch Scratching the ActionMailer &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8221; and I am going to discuss how it all happened, from starting with TMail, why I got fed up with it, why I started Mail, how I went about coding it including spec examples and my workflow, and then onto integrating Mail into ActionMailer and then onto rewriting the ActionMailer &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I hope it will be an interesting talk, I&amp;#8217;ll also be going over Mail and how to use it and some of the lesser known features that you can take advantage of in Rails.&lt;/p&gt;
&lt;p&gt;Hope to see you there!  If you have any suggestions or things you would like me to include, hit me up in the comments, or via Twitter or through my email address.&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails_3_session_secret_and_session_store</id>
    <published>2010-04-07T20:30:00+00:00</published>
    <updated>2010-04-07T20:30:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails_3_session_secret_and_session_store"/>
    <title>Rails 3 Session Secret and Session Store </title>
    <content type="html">
&lt;p&gt;In Rails 3 the location and way you declare the session secret and session store have changed.&lt;/p&gt; &lt;p&gt;Rails 3 Session Secret and Session Store&lt;/p&gt;
&lt;p&gt;In Rails 3 the location and way you declare the session secret and session store have changed.&lt;/p&gt;
&lt;p&gt;Previously (in 2.3.x) you would have one file:&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;config/initializers/session_store.rb&lt;/tt&gt;&lt;br /&gt;
&lt;pre class="ruby"&gt;&lt;br /&gt;
ActionController::Base.session = {&lt;br /&gt;
  :key         =&amp;gt; &amp;#8216;_my_app_name_session&amp;#8217;,&lt;br /&gt;
  :secret      =&amp;gt; &amp;#8216;somereallylongrandomkey&amp;#8217;&lt;br /&gt;
}&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In Rails 3, you reduce &lt;tt&gt;session_store.rb&lt;/tt&gt; to the following:&lt;/p&gt;
&lt;pre class="ruby"&gt;
Rails.application.config.session_store :cookie_store, :key =&amp;gt; "_my_app_name_session"
&lt;/pre&gt;
&lt;p&gt;And then, because we now need somewhere to store the secret, you create a new file called &lt;tt&gt;config/initializers/cookie_verification_secret.rb&lt;/tt&gt; and put inside of it:&lt;/p&gt;
&lt;pre class="ruby"&gt;
Rails.application.config.cookie_secret = 'somereallylongrandomkey'
&lt;/pre&gt;
&lt;p&gt;If instead of using cookies, you were using active record as the store, then you obviously wouldn&amp;#8217;t need the &lt;tt&gt;cookie_verification_secret.rb&lt;/tt&gt; file and instead would insert any other config you needed into its own file inside of initializers.&lt;/p&gt;
&lt;p&gt;This gives us the added bonus of being able to exclude cookie secrets from source control systems.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/if_youre_lazy_and_you_know_it_write_your_specs</id>
    <published>2010-04-04T04:43:28+00:00</published>
    <updated>2010-04-04T04:43:28+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/if_youre_lazy_and_you_know_it_write_your_specs"/>
    <title>If you're lazy and you know it write your specs!</title>
    <content type="html">
&lt;p&gt;You need to sing that title along to &lt;a href="http://www.youtube.com/watch?v=zhwHtw9b_5U"&gt;this tune&lt;/a&gt; but it struck me as a great idea for a post.&lt;/p&gt; &lt;p&gt;As you probably all know, I code the Mail library for Ruby.  When I announced my intentions to the TMail mailing list last year, I had a bunch of people say &amp;#8220;Don&amp;#8217;t bother, it&amp;#8217;s too big a job&amp;#8221; or &amp;#8220;just wrap the libmime library&amp;#8221;.  But I decided to try it out, I mean, how hard could it be?&lt;/p&gt;
&lt;p&gt;Hard.&lt;/p&gt;
&lt;p&gt;No really.  It&amp;#8217;s a real pain covering all the edge cases.  Email is probably one of the most abused specifications out there, actually.  No.  I think it is &lt;span class="caps"&gt;THE&lt;/span&gt; most abused specification out there.  Even the worst &lt;span class="caps"&gt;HTML&lt;/span&gt; pages are better put together than your average spam email.  And there are millions of spam emails.&lt;/p&gt;
&lt;p&gt;But when I started on Mail, I made a conscious decision to spec first the entire library, and as it stands today, there are over 1300 specs in Mail.&lt;/p&gt;
&lt;p&gt;The first spec I wrote was actually this one (which is still in the library):&lt;/p&gt;
&lt;pre class="ruby"&gt;
describe "mail" do
  it "should be able to be instantiated" do
    doing { Mail }.should_not raise_error
  end
end
&lt;/pre&gt;
&lt;p&gt;One of the more narly ones is:&lt;/p&gt;
&lt;pre class="ruby"&gt;
it "should handle |Pete(A wonderful ) chap) &amp;lt;pete(his account)@silly.test(his host)&amp;gt;|" do
  address = Mail::Address.new('Pete(A wonderful \) chap) &amp;lt;pete(his account)@silly.test(his host)&amp;gt;')
  address.should break_down_to({
      :name         =&amp;gt; 'Pete',
      :display_name =&amp;gt; 'Pete',
      :address      =&amp;gt; 'pete(his account)@silly.test',
      :comments     =&amp;gt; ['A wonderful \\) chap', 'his account', 'his host'],
      :domain       =&amp;gt; 'silly.test',
      :local        =&amp;gt; 'pete(his account)',
      :format       =&amp;gt; 'Pete &amp;lt;pete(his account)@silly.test&amp;gt; (A wonderful \\) chap his account his host)',
      :raw          =&amp;gt; 'Pete(A wonderful \\) chap) &amp;lt;pete(his account)@silly.test(his host)&amp;gt;'})
end
&lt;/pre&gt;
&lt;p&gt;What has this got to do with being lazy?  Easy, if you have a full spec (or test) suite and you change something, you can track the impact there is on the entire library.&lt;/p&gt;
&lt;p&gt;So when I get an email that breaks mail, I load it into the spec suite, and run it, get a failure, then go ahead and change code with aplomb, each time running the specs.&lt;/p&gt;
&lt;p&gt;There is a huge sense of security knowing you have thorough spec coverage.&lt;/p&gt;
&lt;p&gt;I have another application, consisting of over 50,000 lines of code (combined specs, features and code itself) which I wrote for a client.  I had to go back to it 7 months after I wrote it (having basically not touched it for this time) and add a new feature.&lt;/p&gt;
&lt;p&gt;The first thing I did was make sure the spec suite was running.  It was, mostly, another coder had made some changes and not updated the specs and features, so there were a few failures.  So I got to work and got it green.&lt;/p&gt;
&lt;p&gt;Then making the change was trivial, I didn&amp;#8217;t have to worry too much about unintended consequences as I know the spec and feature set was very thorough.  The client is also rewarded with a highly maintainable application that is mostly error free and has been running happily along.&lt;/p&gt;
&lt;p&gt;The point is, that if you are not thorough writing test / specs / features with your Rails app.  Then you are not doing your job in a professional manner, simple as that.&lt;/p&gt;
&lt;p&gt;But the good point is, if you like being lazy (and not having to spend &lt;em&gt;&lt;span class="caps"&gt;HOURS&lt;/span&gt;&lt;/em&gt; trying to debug the latest problem with your code), write your specs and features as you go.  You will save yourself (and your client / boss / life) countless hours of frustration.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/bundler_uninitialized_constant_ActionController</id>
    <published>2010-04-01T17:01:30+00:00</published>
    <updated>2010-04-01T17:01:30+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/bundler_uninitialized_constant_ActionController"/>
    <title>Bundler - uninitialized constant ActionController </title>
    <content type="html">
&lt;p&gt;If you are switching over a Rails 2.3 app to Bundler with a Rails App, or you are setting up a new one, you might run into this error when you try to boot rails or run a rake task, thankfully the solution is simple.&lt;/p&gt; &lt;p&gt;The problem is that in your Gemfile, you are trying to load a gem that requires the Rails stack to be in place.  If you check out the Bundler docs for &lt;a href="http://gembundler.com/rails23.html"&gt;Rails 2.3&lt;/a&gt; you will see a &lt;tt&gt;:plugins&lt;/tt&gt; group option.  This group provides a way to load up gem plugins that require the Rails stack.&lt;/p&gt;
&lt;p&gt;If you are not sure which gem is requiring the Rails stack before Rails is loaded and thus blowing out bundler, you can run &lt;tt&gt;rake -T&lt;/tt&gt; as usual, you will get something like this:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ rake -T --trace
(in /Users/mikel/Code/railsplugins)
rake aborted!
uninitialized constant ActionController
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in `load_missing_constant'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in `const_missing'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in `const_missing'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/behavior-0.2.0/lib/behavior.rb:80
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:45:in `require'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:45:in `require'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:40:in `each'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:40:in `require'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:39:in `each'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler/runtime.rb:39:in `require'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/bundler-0.9.14/lib/bundler.rb:75:in `require'
/Users/mikel/Code/railsplugins/config/../config/preinitializer.rb:20
/Users/mikel/Code/railsplugins/config/boot.rb:28:in `load'
/Users/mikel/Code/railsplugins/config/boot.rb:28:in `preinitialize'
/Users/mikel/Code/railsplugins/config/boot.rb:10:in `boot!'
/Users/mikel/Code/railsplugins/config/boot.rb:128
/Users/mikel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/Users/mikel/.rvm/rubies/ruby-1.8.7-p249/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
/Users/mikel/Code/railsplugins/Rakefile:4
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2383:in `load'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2383:in `raw_load_rakefile'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2017:in `load_rakefile'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2016:in `load_rakefile'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2000:in `run'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/lib/rake.rb:1998:in `run'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/gems/rake-0.8.7/bin/rake:31
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/bin/rake:19:in `load'
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@global/bin/rake:19
&lt;/pre&gt;
&lt;p&gt;Now, inside of that trace is a &lt;em&gt;single line&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="shell"&gt;
/Users/mikel/.rvm/gems/ruby-1.8.7-p249@railsplugins/gems/behavior-0.2.0/lib/behavior.rb:80
&lt;/pre&gt;
&lt;p&gt;And there is your clue, moving the gem requirement for behavior into the :plugins group like this:&lt;/p&gt;
&lt;pre class="shell"&gt;
# Gemfile

source :gemcutter

gem 'rails', '2.3.5'

gem 'mysql',            '2.8.1'

group :plugins do
  gem 'behavior',       '0.2.0'
end
&lt;/pre&gt;
&lt;p&gt;Save and re run the rake task, if you are like me and had two or three of these lurking, you will have to work out which ones to put into the :plugins group yourself, the type of plugin is usually pretty obvious.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/bundle_me_some_sanity</id>
    <published>2010-03-31T21:40:44+00:00</published>
    <updated>2010-03-31T21:40:44+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/bundle_me_some_sanity"/>
    <title>Bundle Me Some Sanity</title>
    <content type="html">
&lt;p&gt;You know, there are these two guys working in broad daylight on Bundler, &lt;a href="http://yehudakatz.com/"&gt;Yehuda&lt;/a&gt; and &lt;a href="http://carllerche.com/"&gt;Carl&lt;/a&gt; (he&amp;#8217;s the one in the sidecar), but I don&amp;#8217;t think people have really grasped the importance of what they are doing.&lt;/p&gt; &lt;p&gt;Bundler is just as mind blowing a development for Rails 3 as any other change in the Rails framework.  As the &lt;a href="http://twitter.com/wycats"&gt;wycats&lt;/a&gt; states; &lt;strong&gt;&amp;#8220;Bundler manages an application&amp;#8217;s dependencies through it&amp;#8217;s entire life across many machines systematically and repeatably&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To me, bundler takes the guess work out of dependency management, it simply provides you with a way to know what gems you are distributing with your application, we (as a Ruby community) have never had such a comprehensive solution to gem management before.&lt;/p&gt;
&lt;p&gt;But like any new tool, it is going to go through some growing pains.  To my surprise, (and the credit of the authors) the growing pains have been short and sharp, rapidly fixed as bundler grows to whole new levels of reliability.&lt;/p&gt;
&lt;p&gt;And also like any new tool, it is optimised for certain environments, in bundler&amp;#8217;s case, &lt;a href="http://rvm.beginrescueend.com/"&gt;&lt;span class="caps"&gt;USE&lt;/span&gt; &lt;span class="caps"&gt;RVM&lt;/span&gt;!&lt;/a&gt;  If you are not using &lt;span class="caps"&gt;RVM&lt;/span&gt; and you are running multiple rubies with Bundler, honestly, you&amp;#8217;re mad.  Do yourself a favour, download &lt;span class="caps"&gt;RVM&lt;/span&gt; and use it.  You can then specify sand boxes of gem sets for each ruby or application you have, goodbye incompatible gems conflicting with each other.&lt;/p&gt;
&lt;p&gt;To give you a taste of just how awesome the Bundle &lt;span class="caps"&gt;RVM&lt;/span&gt; marriage is, check this out:&lt;/p&gt;
&lt;p&gt;After you install &lt;span class="caps"&gt;RVM&lt;/span&gt;, go into the directory of each app you want to have their own private gem sets and create a file called &lt;span class="shell"&gt;.rvmrc&lt;/span&gt; and put in there:&lt;/p&gt;
&lt;pre class="shell"&gt;
rvm ruby-1.8.7@railsplugins
&lt;/pre&gt;
&lt;p&gt;Which is what I have on my RailsPlugins.org repository.&lt;/p&gt;
&lt;p&gt;Then change into the directory, and &lt;span class="caps"&gt;RVM&lt;/span&gt; will tell you it doesn&amp;#8217;t know about the gemset:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ cd railsplugins
Gemset 'railsplugins' does not exist, rvm gemset create 'railsplugins' first.
&lt;/pre&gt;
&lt;p&gt;OK, so go ahead and create the gemset and have a look at what gems you have installed:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ rvm gemset create 'railsplugins'
Gemset 'railsplugins' created.
$ gem list

*** LOCAL GEMS ***

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10.2.0]
&lt;/pre&gt;
&lt;p&gt;Good&amp;#8230; see? A clean ruby 1.8.7, as if you just bought the computer.&lt;/p&gt;
&lt;p&gt;Now go ahead and install bundler for this clean gemset:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ gem install --no-rdoc --no-ri bundler
Successfully installed bundler-0.9.14
1 gem installed
&lt;/pre&gt;
&lt;p&gt;Cool, now all that we have left is to give bundler the reins and tell it to do what it does best:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ bundle install
&amp;lt;lots of output&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now when you gem list for that directory you will get all the gems in your gem file, and when you move to a different directory (with a different .rvmrc) all your gems get magically switched out for the new set.&lt;/p&gt;
&lt;p&gt;Honestly, with the number of different clients I am coding for and the number of libraries I am working on, I can&amp;#8217;t imagine being any where near as productive without the &lt;span class="caps"&gt;RVM&lt;/span&gt; and bundler team.&lt;/p&gt;
&lt;p&gt;Yehuda has made a fairly comprehensive guide to bundler at the  &lt;a href="http://gembundler.com/index.html"&gt;Gem Bundler&lt;/a&gt; site which you should read through and understand, and I have only brushed the surface of &lt;span class="caps"&gt;RVM&lt;/span&gt;, you should check it out as well at the &lt;a href="http://rvm.beginrescueend.com/"&gt;&lt;span class="caps"&gt;RVM&lt;/span&gt; site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/how_to_use_mail_and_actionmailer_3_with_gmail_smtp</id>
    <published>2010-03-15T16:29:34+00:00</published>
    <updated>2010-03-15T16:29:34+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/how_to_use_mail_and_actionmailer_3_with_gmail_smtp"/>
    <title>How to use Mail / ActionMailer 3 with GMail SMTP</title>
    <content type="html">
&lt;p&gt;Getting Mail (and therefore ActionMailer 3) working with GMail &lt;span class="caps"&gt;SMTP&lt;/span&gt; is crazy simple, if you know how.&lt;/p&gt; &lt;p&gt;The secret is actually in the Mail RDoc, but to save you looking, here you are:&lt;/p&gt;
&lt;p&gt;Mail allows you to send emails using &lt;span class="caps"&gt;SMTP&lt;/span&gt;.  This is done by wrapping Net::&lt;span class="caps"&gt;SMTP&lt;/span&gt; in&lt;br /&gt;
an easy to use manner.&lt;/p&gt;
&lt;h3&gt;Sending via &lt;span class="caps"&gt;SMTP&lt;/span&gt; server on Localhost&lt;/h3&gt;
&lt;p&gt;Sending locally (to a postfix or sendmail server running on localhost) requires&lt;br /&gt;
no special setup.  Just do&lt;/p&gt;
&lt;pre class="ruby"&gt;
Mail.deliver do
       to 'mikel@test.lindsaar.net'
     from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
     body 'testing sendmail'
end

# Or:

mail = Mail.new do
       to 'mikel@test.lindsaar.net'
     from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
     body 'testing sendmail'
end

mail.deliver
&lt;/pre&gt;
&lt;p&gt;And your email will be fired off to your localhost &lt;span class="caps"&gt;SMTP&lt;/span&gt; server.&lt;/p&gt;
&lt;h3&gt;Sending via GMail&lt;/h3&gt;
&lt;p&gt;To send out via GMail, you need to configure the &lt;tt&gt;Mail::&lt;span class="caps"&gt;SMTP&lt;/span&gt;&lt;/tt&gt; class to have the correct values, so to try this out, open up &lt;span class="caps"&gt;IRB&lt;/span&gt; and type the following:&lt;/p&gt;
&lt;pre class="ruby"&gt;
require 'mail'
options = { :address              =&amp;gt; "smtp.gmail.com",
            :port                 =&amp;gt; 587,
            :domain               =&amp;gt; 'your.host.name',
            :user_name            =&amp;gt; '&amp;lt;username&amp;gt;',
            :password             =&amp;gt; '&amp;lt;password&amp;gt;',
            :authentication       =&amp;gt; 'plain',
            :enable_starttls_auto =&amp;gt; true  }
            
Mail.defaults do
  delivery_method :smtp, options
end
&lt;/pre&gt;
&lt;p&gt;The last block calls &lt;tt&gt;Mail.defaults&lt;/tt&gt; which allows us to set the global delivery method for all mail objects that get created from now on.  Power user tip, you don&amp;#8217;t have to use the global method, you can define the delivery_method directly on any individual &lt;tt&gt;Mail::Message&lt;/tt&gt; object and have different delivery agents per email, this is useful if you are building an application that has multiple users with different servers handling their email.&lt;/p&gt;
&lt;h3&gt;Delivering the email&lt;/h3&gt;
&lt;p&gt;Once you have the settings right, sending the email is done the same way as you would for a local host delivery default:&lt;/p&gt;
&lt;pre class="ruby"&gt;
Mail.deliver do
       to 'mikel@test.lindsaar.net'
     from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
     body 'testing sendmail'
end
&lt;/pre&gt;
&lt;p&gt;Or by calling deliver on a Mail message&lt;/p&gt;
&lt;pre class="ruby"&gt;
mail = Mail.new do
       to 'mikel@test.lindsaar.net'
     from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
     body 'testing sendmail'
end

mail.deliver
&lt;/pre&gt;
&lt;h3&gt;Combining this with ActionMailer 3&lt;/h3&gt;
&lt;p&gt;So as ActionMailer 3 uses Mail as it&amp;#8217;s email transport agent, all you have to do is pass the same options Hash into ActionMailer:&lt;/p&gt;
&lt;pre class="ruby"&gt;
ActionMailer::Base.smtp_settings = {
  :address              =&amp;gt; "smtp.gmail.com",
  :port                 =&amp;gt; 587,
  :domain               =&amp;gt; 'your.host.name',
  :user_name            =&amp;gt; '&amp;lt;username&amp;gt;',
  :password             =&amp;gt; '&amp;lt;password&amp;gt;',
  :authentication       =&amp;gt; 'plain',
  :enable_starttls_auto =&amp;gt; true  }
}
&lt;/pre&gt;
&lt;p&gt;Hope that helps!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/put-your-mailer-where-the-action-is</id>
    <published>2010-03-02T04:28:20+00:00</published>
    <updated>2010-03-02T04:28:20+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/put-your-mailer-where-the-action-is"/>
    <title>Put your mailer where the action is! </title>
    <content type="html">
&lt;p&gt;Recently I was pointed at an article by &lt;a href="http://www.robbyonrails.com/articles/2009/11/16/sending-email-controllers-versus-models"&gt;Robby on Rails&lt;/a&gt; which discussed where mailers belong.  Well, after reading the amazingly long discussion, I feel the solution is quite simple.&lt;/p&gt; &lt;ul&gt;
	&lt;li&gt;Put it in the controller if the primary action depends on sending email.&lt;/li&gt;
	&lt;li&gt;Put it in a callback if the email is a byproduct.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But first a little history.  ActionMailer has been rewritten, almost from the ground up.  It now inherits from AbstractController, and is the same sort of beast as one of your view controllers.  In fact, it uses the same render calls that your average controller does and as far as Rails is concerned, it is just another controller, except it renders email instead of web pages.&lt;/p&gt;
&lt;p&gt;Controllers when they are processing a request from a user, control the action. They decide what models get queries, what files or images get sent and what access the users can and can&amp;#8217;t have.  This is all decided in the controller.&lt;/p&gt;
&lt;p&gt;ActionMailer is just another controller, it is much more a controller than a model.  So if it is just a controller, we should treat it as one!&lt;/p&gt;
&lt;p&gt;But what do I mean above by &amp;#8220;a primary action&amp;#8221;?  Well, take a new user signing up and needing to click on an registration link, the controller should be responsible for getting the email sent:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class UsersController &amp;lt; ActionController::Base
  def create
    # ...
    if @user.save
      Notifier.deliver_verification_email
      flash[:notice] = "Please check your inbox..."
      redirect_to home_path
    else
    # ...
  end
end
&lt;/pre&gt;
&lt;p&gt;Here the primary action of this user is to get a new account, and part of that is the verification email, in fact, a big part of that.  So much so that if they don&amp;#8217;t get that email, then they don&amp;#8217;t get an account.&lt;/p&gt;
&lt;p&gt;What about another primary action?  Well, password reset is a perfect example:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class PasswordsController &amp;lt; ActionController::Base
  def destroy
    user = User.find_by_email(params[:email])
    Notifier.deliver_password_reset(user)
    flash[:notice] = "Please check your inbox..."
    redirect_to home_path
    # ...
  end
end
&lt;/pre&gt;
&lt;p&gt;Again, here we have a controller who is handling a request from a user who wants to receive an email.  The primary purpose here is to deliver that email.  Why make a whole complex call back?  The logic is simple, clear and easy to follow.&lt;/p&gt;
&lt;p&gt;But by-product emails are another thing.&lt;/p&gt;
&lt;p&gt;At &lt;a href="http://railsplugins.org/"&gt;RailsPlugins.org&lt;/a&gt;, we have it hooked up to RubyGems.org so that if you push a new gem version to RubyGems, and you have that same gem listed and &amp;#8216;linked&amp;#8217; in RailsPlugins, then that new version will be automatically created for you on RailsPlugins with all the previous version&amp;#8217;s compatibility matrix, oh, and by the way, the RailsPlugins app will send you an email to let you know.&lt;/p&gt;
&lt;p&gt;That is the key phrase though, to let you know.&lt;/p&gt;
&lt;p&gt;If the email doesn&amp;#8217;t get sent, it&amp;#8217;s not the end of the world.  It is not a primary action.  It will not destroy the integrity of your database.  In fact, it may not even be noticed if it was missing.  So putting this into the model, or as a call back is perfectly valid.&lt;/p&gt;
&lt;p&gt;Another by-product email would be notifications to everyone watching a comment thread.  Again, this is dependent on the model being saved, the comment being valid, and, oh, we&amp;#8217;ll send out a notification to all our users.  The email is not the primary part of the app, and would be clutter in the controller.  Another perfect example of a mailer that can go into an observer, call back or the model itself.&lt;/p&gt;
&lt;p&gt;The bottom line is, it is not a religious war, put your mailers where they make sense.&lt;/p&gt;
&lt;p&gt;But with ActionMailer now effectively just another controller, use it as one!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/why_force_a_choice</id>
    <published>2010-02-20T17:48:58+00:00</published>
    <updated>2010-02-20T17:48:58+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/why_force_a_choice"/>
    <title>Why Force a Choice? </title>
    <content type="html">
&lt;p&gt;Recently I have been reading a bit from the Python crowd, and I realised a key point on why Rails is successful, you are not forced to choose.&lt;/p&gt; &lt;p&gt;You have all heard the &amp;#8220;Convention over Configuration&amp;#8221; mantra, and, if you use Rails, you most likely subscribe to this war cry, and why not? It enables the average developer to get up of the ground &lt;em&gt;fast&lt;/em&gt; with an application that works, while simultaneously allowing your non average developer to do whatever the hell they want and extend the system in new and interesting ways.&lt;/p&gt;
&lt;p&gt;This mantra provides the Rails Community with probably the second biggest advantage over any other web development framework out there, the first advantage is of course Ruby itself.&lt;/p&gt;
&lt;p&gt;But while reading the &lt;a href="http://djangoadvent.com/1.2/deploying-django-site-using-fastcgi/"&gt;installation manual&lt;/a&gt;  from our &lt;a href="http://railsenvy.com/2007/9/10/ruby-on-rails-vs-django-commercial-7"&gt;DeeJayAngo&lt;/a&gt; friends, I kept hitting spots where the author was asking the reader to make decisions, &lt;tt&gt;mod_wsgi&lt;/tt&gt; or &lt;tt&gt;mod_python&lt;/tt&gt;, &lt;tt&gt;Apache&lt;/tt&gt; or &lt;tt&gt;Nginx&lt;/tt&gt;, &lt;tt&gt;threaded&lt;/tt&gt; or &lt;tt&gt;prefork&lt;/tt&gt;, the list goes on.&lt;/p&gt;
&lt;p&gt;Now assumedly, the audience that article was written to was a crowd of developers who do not already know how to install a Python based web server, so asking them to make decisions on the capacity, style, environment and resources of a web app is a bit premature.&lt;/p&gt;
&lt;p&gt;Of course, I am making an example of that one article, but I keep seeing this in various instruction manuals and frameworks.  If that article was entitled &amp;#8220;Django Installation Reference for the Experienced Developer&amp;#8221; then fine, but it isn&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;This reminds me of a saying from my &lt;a href="http://lindsaar.net/about_mikel"&gt;philosophy of choice&lt;/a&gt;, &amp;#8220;To decide, one must first understand&amp;#8221;, and this holds very true in all of our web development circles, not just programming and installation guides.&lt;/p&gt;
&lt;p&gt;Rails is opinionated, this is another way of saying that the developers of Rails (who do understand) makes decisions on behalf of the new user (who has relatively no clue) on how the system should behave. Then, step by step the user expands their knowledge up to a point where they understand the system themselves, and then, can make their own decisions, like change a javascript library, or write your own style scaffold, or whatever you choose.&lt;/p&gt;
&lt;p&gt;But you as a Rails developer need to also keep this nugget of philosophy in mind when you are developing your Rails app.  Your new customer has no idea how your system works, if the first thing you do is require them to make decisions, then chances are you are going to lose customers.&lt;/p&gt;
&lt;p&gt;Each step of your site should have, as much as possible, &lt;span class="caps"&gt;ONE&lt;/span&gt; action that the customer should do to proceed to the next step.&lt;/p&gt;
&lt;p&gt;Customer comes to your site for the first time, good, offer them the trial account, obviously and clearly. They don&amp;#8217;t understand your service, they don&amp;#8217;t really need to beyond &amp;#8220;Will this service solve my problem at a realistic price?&amp;#8221;.  Making them decide to buy plan A or plan B, when they don&amp;#8217;t even know what it is you do is just asking for disaster.&lt;/p&gt;
&lt;p&gt;Customer logs into their newly purchased account, good, tell them what to do as a first action.  Then, preferably, tell them what the second standard action is.  Of course, don&amp;#8217;t force them to do what you think is the best next step, but these User Interface guides can drastically improve your site&amp;#8217;s usability.&lt;/p&gt;
&lt;p&gt;The other thing that this forces you to do as a developer is simplify your site design and change the way you think.  Of course you want the user to have many options, but if you keep this idea in mind of &amp;#8220;Does the user at this point understand enough to be able to make a decision?&amp;#8221; then you will find your product will become more and more successful.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/how-to-make-an-rss-feed-or-atom-feed-in-rails</id>
    <published>2010-02-12T22:12:05+00:00</published>
    <updated>2010-02-12T22:12:05+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/how-to-make-an-rss-feed-or-atom-feed-in-rails"/>
    <title>How to make an RSS feed in Rails</title>
    <content type="html">
&lt;p&gt;Easy. Don&amp;#8217;t. Use an &lt;span class="caps"&gt;ATOM&lt;/span&gt; feed instead.  Rails is opinionated software, it has an opinion on feeds, there is an &lt;tt&gt;atom_feed&lt;/tt&gt; helper, but no &lt;tt&gt;rss_feed&lt;/tt&gt; helper?  Omission?  Nup.&lt;/p&gt; &lt;p&gt;I added the &lt;span class="caps"&gt;ATOM&lt;/span&gt; feed to &lt;a href="http://railsplugins.org"&gt;Rails Plugins&lt;/a&gt; website very simply, by using the Rails &lt;tt&gt;atom_feed&lt;/tt&gt; helper.  It was a simple case of creating a &lt;tt&gt;FeedsController&lt;/tt&gt; with just a single index action, which collected up all the time line events that needed to go onto the feed and assigned them to the view in an &lt;tt&gt;@events&lt;/tt&gt; ivar.&lt;/p&gt;
&lt;p&gt;So the controller looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class FeedsController &amp;lt; ApplicationController
  
  layout false
  
  def index
    @events = TimelineEvent.for_feed
    @title = "Rails Plugins Feed"
    @updated = @events.first.created_at unless @events.empty?
  end
end
&lt;/pre&gt;
&lt;p&gt;Then in the view file &lt;tt&gt;app/views/feeds/index.atom.builder&lt;/tt&gt; looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
atom_feed do |feed|
  feed.title(@title)

  feed.updated(@updated)

  @events.each do |event|
    feed.entry(event) do |entry|

      entry.title(h(event.title))
      entry.summary(truncate(strip_tags(event.description), :length =&amp;gt; 100))

      entry.author do |author|
        author.name(event.author_name)
      end
    end
  end
end
&lt;/pre&gt;
&lt;p&gt;And then the route to wire it up:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# config/routes.rb (Rails 2.0)
ActionController::Routing::Routes.draw do |map|
  map :resources :feeds, :only =&amp;gt; [:index]
end
&lt;/pre&gt;
&lt;p&gt;And finally the &lt;tt&gt;auto_discovery_link_tag&lt;/tt&gt; in the &lt;tt&gt;application.html.erb&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="html"&gt;
&amp;lt;%= auto_discovery_link_tag(:atom, "/feeds.atom") %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now this was all well and good, and I thought, why not add an &lt;span class="caps"&gt;RSS&lt;/span&gt; feed as well?&lt;/p&gt;
&lt;p&gt;I started down on this path and the first thing that struck me was, there was no &lt;tt&gt;rss_feed&lt;/tt&gt; helper in Rails, why?  Seemed like an ommission&amp;#8230;&lt;/p&gt;
&lt;p&gt;Then I was looking around the web and found many examples on how to do an &lt;span class="caps"&gt;RSS&lt;/span&gt; feed in Rails, but none of them mentioned this omission of the helper, why?&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t puzzle over this long, and just went ahead and added an &lt;span class="caps"&gt;RSS&lt;/span&gt; feed, it wasn&amp;#8217;t hard, you can find this out from your friend google.&lt;/p&gt;
&lt;p&gt;But then I got this IM from &lt;a href="http://intertwingly.net/"&gt;Sam Ruby&lt;/a&gt; after I let him know the &lt;span class="caps"&gt;RSS&lt;/span&gt; feed for Rails Plugins was now online:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;#8220;Ewwwww&amp;#8221;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Which was not really the answer I was expecting, so I stated:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;#8220;I never did get the &lt;span class="caps"&gt;ATOM&lt;/span&gt; v &lt;span class="caps"&gt;RSS&lt;/span&gt; debate&amp;#8221;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To which he replied:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;#8220;I started the Atom vs &lt;span class="caps"&gt;RSS&lt;/span&gt; debate.&amp;#8221;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And that started an interesting chat!  Let me tell you!&lt;/p&gt;
&lt;p&gt;Turns out that &lt;a href="http://en.wikipedia.org/wiki/Atom_%28standard%29"&gt;&lt;span class="caps"&gt;ATOM&lt;/span&gt;&lt;/a&gt; is actually defined, with &lt;a href="http://www.ietf.org/rfc/rfc4287.txt"&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt; 4287&lt;/a&gt; that covers all the basics of what you need to know.&lt;/p&gt;
&lt;p&gt;Also turns out that any modern reader will handle &lt;span class="caps"&gt;ATOM&lt;/span&gt;, just as easily as &lt;span class="caps"&gt;RSS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Also turns out that with &lt;span class="caps"&gt;ATOM&lt;/span&gt; you can define things like (gasp) language settings, Internationalization, content types and several other points which make the data a lot more consumable.&lt;/p&gt;
&lt;p&gt;So, then I added the following to the Rails Plugins website:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class FeedsController &amp;lt; ApplicationController
  def index
    # ...
    respond_to do |wants|
      wants.rss do
        redirect_to feeds_path(:format =&amp;gt; :atom),
                    :status=&amp;gt;:moved_permanently
      end
      wants.atom
    end
  end
end
&lt;/pre&gt;
&lt;p&gt;And decided to sum up my gained knowledge with: &lt;a href="http://twitter.com/raasdnil/statuses/9045548351"&gt;We are Rails, we are opinionated, ta-ta &lt;span class="caps"&gt;RSS&lt;/span&gt;  http://bit.ly/c9eyNL &amp;#8211; &lt;span class="caps"&gt;KTHXBAI&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails_3_routing_with_rack</id>
    <published>2010-02-07T05:56:12+00:00</published>
    <updated>2010-02-07T05:56:12+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails_3_routing_with_rack"/>
    <title>Rails 3 Routing with Rack </title>
    <content type="html">
&lt;p&gt;You probably all have heard that &amp;#8220;Rails lets you route to Rack applications directly&amp;#8221; and thought &amp;#8220;Oh really?&amp;#8221; well&amp;#8230; bet you didn&amp;#8217;t think it would be this simple.&lt;/p&gt; &lt;p&gt;Rails 3 really opens up a whole new world of pluggable awesomeness.  This post expects you have already installed Rails 3 &amp;#8212;prerelease, if not, follow the instructions in the &lt;a href="http://guides.rails.info/3_0_release_notes.html"&gt;Release Notes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal here is to make a &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra app&lt;/a&gt; run inside of Rails, taking routes it needs directly using the new Rails routing features.&lt;/p&gt;
&lt;p&gt;Code is better at talking than me, so first make a new app:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ rails app
&lt;/pre&gt;
&lt;p&gt;Let rails do its thing.  Then we want to make a simple Sinatra app, let&amp;#8217;s make it marginally useful and have it hit Twitter.&lt;/p&gt;
&lt;p&gt;Make a directory &lt;tt&gt;lib/twitter&lt;/tt&gt; and in there make a new file called &lt;tt&gt;twitter_app.rb&lt;/tt&gt;, inside of it put:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class TwitterApp &amp;lt; Sinatra::Base
  set :root, File.dirname(__FILE__)

  get '/twitter' do
    @user = 'raasdnil'
    t = Twitter::Search.new(@user).fetch
    @tweets = t.results
    erb :twitter
  end

end
&lt;/pre&gt;
&lt;p&gt;This is a basic Sinatra app, it first sets its root directory to be the directory of the current file (needed because using the Rails root will not work) and then responds to one url &lt;tt&gt;/twitter&lt;/tt&gt; that uses the Twitter gem to do the heavy lifting on searching for all the tweets by some weirdo (me).&lt;/p&gt;
&lt;p&gt;It then assigns all the tweets to an instance variable and renders the template &lt;tt&gt;twitter.erb&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;We have to make this template, so create another folder &lt;tt&gt;lib/twitter/views&lt;/tt&gt; and make a file in there called &lt;tt&gt;twitter.erb&lt;/tt&gt; and put in the following:&lt;/p&gt;
&lt;pre class="html"&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Tweets mentioning &amp;lt;%= @user %&amp;gt;&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;style type="text/css" media="screen"&amp;gt;
    div.tweet { border: 1px solid gray;
                height: 50px;
                width: 600px;
                padding: 5px;
                margin-bottom: 10px; }
    img.icon { float: left; padding-right: 10px; }
    div.text { font-family: verdana, sans-serif; }
    div.&amp;lt;%= @user %&amp;gt; { background: #F4F4FF; }
  &amp;lt;/style&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;% @tweets.each do |tweet| %&amp;gt;
    &amp;lt;div class="tweet  &amp;lt;%= tweet.from_user %&amp;gt;" id="&amp;lt;%= tweet.id %&amp;gt;"&amp;gt;
      &amp;lt;img class="icon" src="&amp;lt;%= tweet.profile_image_url %&amp;gt;" /&amp;gt;
      &amp;lt;div class="text" &amp;gt;
        &amp;lt;%= tweet.text %&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;p&gt;OK, our Sinatra app is ready to fire. Now hooking it up is simple.&lt;/p&gt;
&lt;p&gt;First, we need to make sure we require the needed gems, so open up your &lt;tt&gt;Gemfile&lt;/tt&gt; in Rails root and add the following:&lt;/p&gt;
&lt;pre class="ruby"&gt;
## Bundle the gems you use:
gem "sinatra", "0.9.2"
gem "twitter", "0.8.3"
&lt;/pre&gt;
&lt;p&gt;Then do a bundle check to make sure we have the gems we need:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ bundle check
The Gemfile's dependencies are satisfied
&lt;/pre&gt;
&lt;p&gt;All good (if that gave you an error, just run &lt;tt&gt;bundle install&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;Now the final step is to wire up the Rails Router.&lt;/p&gt;
&lt;p&gt;Open up &lt;tt&gt;config/routes.rb&lt;/tt&gt; and add a require for your twitter app as well as a route to match &lt;tt&gt;&amp;#8216;/twitter&amp;#8217;&lt;/tt&gt; and send to your Sinatra App, something like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
require 'twitter/twitter_app'

RackTest::Application.routes.draw do |map|

  match '/twitter', :to =&amp;gt; TwitterApp

end
&lt;/pre&gt;
&lt;p&gt;And that&amp;#8217;s it!&lt;/p&gt;
&lt;p&gt;Fire up your Rails app with &lt;tt&gt;rails s&lt;/tt&gt; as you normally would, and browse to &lt;a href="http://127.0.0.1:3000/twitter"&gt;http://127.0.0.1:3000/twitter&lt;/a&gt; and proove it to yourself&amp;#8230; this stuff works.&lt;/p&gt;
&lt;p&gt;Almost too simple.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/bundle_me_some_rails</id>
    <published>2010-02-06T00:42:17+00:00</published>
    <updated>2010-02-06T00:42:17+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/bundle_me_some_rails"/>
    <title>Bundle me some Rails</title>
    <content type="html">
&lt;p&gt;Bundler rocks, but you need to think differently about how to start and run your Rails app.&lt;/p&gt; &lt;h3&gt;The Bundler Way&lt;/h3&gt;
&lt;p&gt;You should realise that &lt;a href="http://github.com/carlhuda/bundler"&gt;Bundler&lt;/a&gt; is a library management tool.  This has to be in your mind when you are getting a Rails application running on version 3.0.&lt;/p&gt;
&lt;p&gt;For example, I had a new Rails application that I want to run with PostgreSQL, so I go in and change database.yml to look at my PostgreSQL database instead of the Sqlite3 database, fairly standard, straight forward opperation.&lt;/p&gt;
&lt;p&gt;Then starting the application console however, I got a bit of a shock:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ rails c
/Users/mikel/.gem/ruby/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract/connection_specification.rb:76:in `establish_connection':
Please install the postgresql adapter: `gem install activerecord-postgresql-adapter`
(no such file to load -- pg) (RuntimeError)
  from /Users/mikel/.gem/ruby/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract/connection_specification.rb:60:in
`establish_connection'
  from /Users/mikel/.gem/ruby/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract/connection_specification.rb:55:in 
`establish_connection'
  from /Users/mikel/.gem/ruby/1.8/gems/activerecord-3.0.0.beta/lib/active_record/railtie.rb:45
...
&lt;/pre&gt;
&lt;p&gt;This confused me for a second, I was sure that the &lt;tt&gt;pg&lt;/tt&gt; gem was installed on my system, and the following confirmed it for me:&lt;/p&gt;
&lt;pre class="shell"&gt;
mikel@baci.lindsaar.net ~
 $ gem list pg

*** LOCAL GEMS ***

pg (0.8.0)
&lt;/pre&gt;
&lt;p&gt;OK, but the rails app was complaining that it couldn&amp;#8217;t find it.  At this point, I did a bit of a double take, then a &amp;#8220;D&amp;#8217;Uh&amp;#8221; moment hit me, bundler does not equal rubygems.&lt;/p&gt;
&lt;p&gt;This is an important datum, Bundler is a library management tool, and it allows you to totally bypass the rubygems on your system.&lt;/p&gt;
&lt;p&gt;So, first things first, bundler gives you some tools:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle
Tasks:
  bundle check        # Checks if the dependencies listed in Gemfile are satisfied by currently installed gems
  bundle exec         # Run the command in context of the bundle
  bundle help [TASK]  # Describe available tasks or one specific task
  bundle init         # Generates a Gemfile into the current working directory
  bundle install      # Install the current environment to the system
  bundle lock         # Locks the bundle to the current set of dependencies, including all child dependencies.
  bundle pack         # Packs all the gems to vendor/cache
  bundle show         # Shows all gems that are part of the bundle.
  bundle unlock       # Unlock the bundle. This allows gem versions to be changed
&lt;/pre&gt;
&lt;p&gt;So &amp;#8220;bundle check&amp;#8221; should see if my dependencies are satisfied:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle check
The Gemfile's dependencies are satisfied
&lt;/pre&gt;
&lt;p&gt;OK, so that&amp;#8217;s not the problem, so what gems does bundler say I have installed then?&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle show
Gems included by the bundle:
  * abstract (1.0.0)
  * actionmailer (3.0.0.beta)
  * actionpack (3.0.0.beta)
  * activemodel (3.0.0.beta)
  * activerecord (3.0.0.beta)
  * activeresource (3.0.0.beta)
  * activesupport (3.0.0.beta)
  * arel (0.2.1)
  * builder (2.1.2)
  * bundler (0.9.2)
  * erubis (2.6.5)
  * i18n (0.3.3)
  * mail (2.1.2)
  * memcache-client (1.7.8)
  * mime-types (1.16)
  * rack (1.1.0)
  * rack-mount (0.4.5)
  * rack-test (0.5.3)
  * rails (3.0.0.beta)
  * railties (3.0.0.beta)
  * rake (0.8.7)
  * sqlite3-ruby (1.2.5)
  * text-format (1.0.0)
  * text-hyphen (1.0.0)
  * thor (0.13.0)
  * tzinfo (0.3.16)
&lt;/pre&gt;
&lt;p&gt;And there the light turns on, no &amp;#8220;pg&amp;#8221; listed, which I am using inside my Rails app.&lt;/p&gt;
&lt;p&gt;So that must mean that my &lt;tt&gt;Gemfile&lt;/tt&gt; is not listing &lt;tt&gt;pg&lt;/tt&gt; as a dependency, let&amp;#8217;s check:&lt;/p&gt;
&lt;pre class="shell"&gt;
# Edit this Gemfile to bundle your application's dependencies.
source :gemcutter

gem "rails", "3.0.0.beta"

## Bundle edge rails:
# gem "rails", :git =&amp;gt; "git://github.com/rails/rails.git"

# ActiveRecord requires a database adapter. By default,
# Rails has selected sqlite3.
gem "sqlite3-ruby"

## Bundle the gems you use:
# gem "bj"
# gem "hpricot", "0.6"
# gem "sqlite3-ruby", :require_as =&amp;gt; "sqlite3"
# gem "aws-s3", :require_as =&amp;gt; "aws/s3"

## Bundle gems used only in certain environments:
# gem "rspec", :only =&amp;gt; :test
# only :test do
#   gem "webrat"
# end
&lt;/pre&gt;
&lt;p&gt;Notice, no mention of pg?  Easy, I add &lt;tt&gt;pg&lt;/tt&gt; like so:&lt;/p&gt;
&lt;pre class="shell"&gt;
# ...
## Bundle the gems you use:
gem "pg"
# gem "hpricot", "0.6"
# gem "sqlite3-ruby", :require_as =&amp;gt; "sqlite3"
# gem "aws-s3", :require_as =&amp;gt; "aws/s3"
# ...
&lt;/pre&gt;
&lt;p&gt;And now another check:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle check
The Gemfile's dependencies are satisfied
&lt;/pre&gt;
&lt;p&gt;All good, we can also check to see if bundle is now looking for the &lt;tt&gt;pg&lt;/tt&gt; gem now:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle show
Gems included by the bundle:
  * abstract (1.0.0)
  * actionmailer (3.0.0.beta)
  * actionpack (3.0.0.beta)
  * activemodel (3.0.0.beta)
  * activerecord (3.0.0.beta)
  * activeresource (3.0.0.beta)
  * activesupport (3.0.0.beta)
  * arel (0.2.1)
  * builder (2.1.2)
  * bundler (0.9.2)
  * erubis (2.6.5)
  * i18n (0.3.3)
  * mail (2.1.2)
  * memcache-client (1.7.8)
  * mime-types (1.16)
  * pg (0.8.0)
  * rack (1.1.0)
  * rack-mount (0.4.5)
  * rack-test (0.5.3)
  * rails (3.0.0.beta)
  * railties (3.0.0.beta)
  * rake (0.8.7)
  * sqlite3-ruby (1.2.5)
  * text-format (1.0.0)
  * text-hyphen (1.0.0)
  * thor (0.13.0)
  * tzinfo (0.3.16)
&lt;/pre&gt;
&lt;p&gt;All good, there is the &lt;tt&gt;pg&lt;/tt&gt; gem listed, so now that all dependencies are met, and I have the PostgreSQL database all setup, I should now be able to start the application console:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ rails c
Loading development environment (Rails 3.0.0.beta)
&amp;gt;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And voila, we are up and running.&lt;/p&gt;
&lt;h3&gt;Packing it Up&lt;/h3&gt;
&lt;p&gt;The cool thing about bundler that sets is apart from any other library management system, is its ability to pack and lock your gem files.&lt;/p&gt;
&lt;p&gt;Say you want to now give your Rails app to some other developer, you don&amp;#8217;t know what versions of what gems they have running on their system, so instead, you just pack away all the gems that are working for you and then send them the whole Rails application directory, this will ship your app and all its dependencies to your co-developer, who then can just run the app as is without any other hoops.&lt;/p&gt;
&lt;p&gt;First step is to pack your gems:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle pack
Copying .gem files into vendor/cache
  * builder-2.1.2.gem
  * text-hyphen-1.0.0.gem
  * i18n-0.3.3.gem
  * bundler-0.9.2.gem
  * arel-0.2.1.gem
  * activemodel-3.0.0.beta.gem
  * rack-mount-0.4.5.gem
  * mime-types-1.16.gem
  * mail-2.1.2.gem
  * abstract-1.0.0.gem
  * erubis-2.6.5.gem
  * thor-0.13.0.gem
  * memcache-client-1.7.8.gem
  * rack-1.1.0.gem
  * rack-test-0.5.3.gem
  * actionpack-3.0.0.beta.gem
  * rake-0.8.7.gem
  * railties-3.0.0.beta.gem
  * sqlite3-ruby-1.2.5.gem
  * activerecord-3.0.0.beta.gem
  * text-format-1.0.0.gem
  * actionmailer-3.0.0.beta.gem
  * tzinfo-0.3.16.gem
  * activesupport-3.0.0.beta.gem
  * activeresource-3.0.0.beta.gem
  * rails-3.0.0.beta.gem
&lt;/pre&gt;
&lt;p&gt;This now has put every gem that my rails app depends on into the vendor/gems directory, you can confirm this by checking out &lt;tt&gt;vendor/cache&lt;/tt&gt; which shows all the gem files listed.&lt;/p&gt;
&lt;p&gt;You can then simply zip up the whole package and send it to your co-developer (or use Git or whatever means you love), your opposite number then unpacks the entire directory, goes to the root of it and types:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle install
Installing abstract (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing actionmailer (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing actionpack (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activemodel (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activerecord (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activeresource (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activesupport (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing arel (0.2.1) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing builder (2.1.2) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing bundler (0.9.3) from system gems 
Installing erubis (2.6.5) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing i18n (0.3.3) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing mail (2.1.2) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing memcache-client (1.7.8) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing mime-types (1.16) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rack (1.1.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rack-mount (0.4.5) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rack-test (0.5.3) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rails (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing railties (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rake (0.8.7) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing sqlite3-ruby (1.2.5) from .gem files at /Users/mikel/Code/app/vendor/cache with native extensions 
Installing text-format (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing text-hyphen (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing thor (0.13.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing tzinfo (0.3.16) from .gem files at /Users/mikel/Code/app/vendor/cache 
Your bundle is complete!
&lt;/pre&gt;
&lt;p&gt;Now your co-developer has installed every gem they need to start your Rails application on their system, all sitting right within the Rails app.&lt;/p&gt;
&lt;p&gt;Simply, this rocks.&lt;/p&gt;
&lt;h3&gt;Lock &amp;#8216;n&amp;#8217; Load&lt;/h3&gt;
&lt;p&gt;But you would have noticed that when we specified the &lt;tt&gt;pg&lt;/tt&gt; gem above, we did not specify a version, bundler helpfully grabbed the most recent one we had installed and shipped that.&lt;/p&gt;
&lt;p&gt;But when you are delopying an application to a production server, you don&amp;#8217;t want approximates on Gem versions, you want what works.  You don&amp;#8217;t want &amp;#8220;Well, gem xyz is now version 0.9, it was working on 0.8.2, so it should be ok.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Bundler handles this problem as well, by locking.&lt;/p&gt;
&lt;p&gt;Again, standing in the root of your app, just run bundle lock:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle lock
The bundle is now locked. Use `bundle show` to list the gems in the environment.
&lt;/pre&gt;
&lt;p&gt;What this command does is make a Gemfile.lock file in your application&amp;#8217;s root directory which looks like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
--- 
dependencies: 
- rails: = 3.0.0.beta
- sqlite3-ruby: "&amp;gt;= 0"
- pg: "&amp;gt;= 0"
specs: 
- text-hyphen: 
    version: 1.0.0
- builder: 
    version: 2.1.2
- i18n: 
    version: 0.3.3
- bundler: 
    version: 0.9.3
- arel: 
    version: 0.2.1
- activemodel: 
    version: 3.0.0.beta
- rack-mount: 
    version: 0.4.5
- abstract: 
    version: 1.0.0
- erubis: 
    version: 2.6.5
- mime-types: 
    version: "1.16"
- mail: 
    version: 2.1.2
- thor: 
    version: 0.13.0
- memcache-client: 
    version: 1.7.8
- rack: 
    version: 1.1.0
- rack-test: 
    version: 0.5.3
- actionpack: 
    version: 3.0.0.beta
- rake: 
    version: 0.8.7
- railties: 
    version: 3.0.0.beta
- sqlite3-ruby: 
    version: 1.2.5
- text-format: 
    version: 1.0.0
- actionmailer: 
    version: 3.0.0.beta
- activerecord: 
    version: 3.0.0.beta
- pg: 
    version: 0.8.0
- activeresource: 
    version: 3.0.0.beta
- rails: 
    version: 3.0.0.beta
- tzinfo: 
    version: 0.3.16
- activesupport: 
    version: 3.0.0.beta
hash: b75772b5511703b25aded771d7ca687836679fef
sources: 
- Rubygems: 
    uri: http://gemcutter.org
- Path: 
    glob: "{*/,}*.gemspec"
    path: /Users/mikel/rails_programs/rails
&lt;/pre&gt;
&lt;p&gt;A couple of things to notice about this, see that the &lt;tt&gt;pg&lt;/tt&gt; gem has now been locked to version 0.8.0?  This means that your application will now &lt;span class="caps"&gt;ONLY&lt;/span&gt; start if it has access to this version, of course, if the target platform does not have version 0.8.0 installed, a simple &lt;tt&gt;bundle install&lt;/tt&gt; will fix this.&lt;/p&gt;
&lt;p&gt;The &lt;tt&gt;Gemfile.lock&lt;/tt&gt; also has a hash in it, this is a &lt;span class="caps"&gt;SHA&lt;/span&gt; of your Gemfile, this is there so that if you change your Gemfile to add a new gem, say &lt;tt&gt;hpricot&lt;/tt&gt;, then bundler will complain (rightly so) as follows:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle check
You changed your Gemfile after locking. Please relock using `bundle lock`
&lt;/pre&gt;
&lt;p&gt;OK, so we run bundle lock again:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle lock
The bundle is already locked, relocking.
Could not find gem 'hpricot (= 0.6, runtime)' in any of the sources.
Run `bundle install` to install missing gems
&lt;/pre&gt;
&lt;p&gt;Well, good, I like being lead by the hand&amp;#8230;&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle install
Fetching source index from http://gemcutter.org
Resolving dependencies
Installing abstract (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing actionmailer (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing actionpack (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activemodel (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activerecord (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activeresource (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing activesupport (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing arel (0.2.1) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing builder (2.1.2) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing bundler (0.9.3) from system gems 
Installing erubis (2.6.5) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing hpricot (0.6) from rubygems repository at http://gemcutter.org with native extensions 
Installing i18n (0.3.3) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing mail (2.1.2) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing memcache-client (1.7.8) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing mime-types (1.16) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing pg (0.8.0) from system gems 
Installing rack (1.1.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rack-mount (0.4.5) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rack-test (0.5.3) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rails (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing railties (3.0.0.beta) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing rake (0.8.7) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing sqlite3-ruby (1.2.5) from .gem files at /Users/mikel/Code/app/vendor/cache with native extensions 
Installing text-format (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing text-hyphen (1.0.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing thor (0.13.0) from .gem files at /Users/mikel/Code/app/vendor/cache 
Installing tzinfo (0.3.16) from .gem files at /Users/mikel/Code/app/vendor/cache 
Your bundle is complete!
&lt;/pre&gt;
&lt;p&gt;Good, see bundler did what it was meant to and grabbed the &lt;tt&gt;hpricot&lt;/tt&gt; gem for us.  Mow that we have installed, lets bundle check again:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle check
The Gemfile's dependencies are satisfied
&lt;/pre&gt;
&lt;p&gt;All good, so now we can bundle pack (which is optional as you can just lock off the system gems installed):&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle pack
Copying .gem files into vendor/cache
  * text-hyphen-1.0.0.gem
  * hpricot-0.6.gem
  * builder-2.1.2.gem
  * i18n-0.3.3.gem
  * bundler-0.9.3.gem
  * arel-0.2.1.gem
  * activemodel-3.0.0.beta.gem
  * mime-types-1.16.gem
  * mail-2.1.2.gem
  * abstract-1.0.0.gem
  * erubis-2.6.5.gem
  * thor-0.13.0.gem
  * sqlite3-ruby-1.2.5.gem
  * rake-0.8.7.gem
  * railties-3.0.0.beta.gem
  * memcache-client-1.7.8.gem
  * rack-1.1.0.gem
  * rack-test-0.5.3.gem
  * rack-mount-0.4.5.gem
  * actionpack-3.0.0.beta.gem
  * pg-0.8.0.gem
  * activerecord-3.0.0.beta.gem
  * text-format-1.0.0.gem
  * actionmailer-3.0.0.beta.gem
  * activeresource-3.0.0.beta.gem
  * rails-3.0.0.beta.gem
  * tzinfo-0.3.16.gem
  * activesupport-3.0.0.beta.gem
&lt;/pre&gt;
&lt;p&gt;Awesome, hpricot was packed.  Now we can bundle lock:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ bundle lock
The bundle is now locked. Use `bundle show` to list the gems in the environment.
&lt;/pre&gt;
&lt;p&gt;The app is now all good and ready to deploy again.&lt;/p&gt;
&lt;p&gt;If you look at the Gemfile.lock file, you will find the hash has changed from before:&lt;/p&gt;
&lt;pre class="shell"&gt;
# Was before:
hash: b75772b5511703b25aded771d7ca687836679fef
#
# Is now:
hash: 613e95d88b2b3e09185c89572cff3291ecaa45cf
&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;One thing you should remember is that packing and locking your gems with bundler are optional.  You don&amp;#8217;t have to pack your gems to lock, and you don&amp;#8217;t have to lock to install.  The point of packing and locking is that your application becomes a self contained repository of all the gems you need to run your application.&lt;/p&gt;
&lt;p&gt;I hope the above gives you a good introduction to this awesome library manager.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/helping_out_in_haiti</id>
    <published>2010-02-05T15:03:33+00:00</published>
    <updated>2010-02-05T15:03:33+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/helping_out_in_haiti"/>
    <title>Helping out in Haiti</title>
    <content type="html">
&lt;p&gt;Lots of people are flying to Haiti to help out from all walks of life, good to see some Scientologists getting in there as well.&lt;/p&gt; &lt;p&gt;Found &lt;a href="http://today.msnbc.msn.com/id/26184891/vp/35214415#35214415"&gt;this video&lt;/a&gt; today on &lt;span class="caps"&gt;MSNBC&lt;/span&gt;, shows some of our Volunteer ministers from America down in Haiti.&lt;/p&gt;
&lt;p&gt;Another one of our members from Australia &lt;a href="http://www.scientology.net.au/news/2010/02/05/australian-volunteer-minister-flies-out-for-haiti-disaster-relief/"&gt;just flew out to Haiti&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;We have a &lt;a href="http://blog.volunteerministers.org/"&gt;volunteer minister&lt;/a&gt; program all over the world, it&amp;#8217;s actually the largest independent relief force in the world, something you don&amp;#8217;t hear a lot in the news, but we do a lot of good around the world.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/watch_your_self</id>
    <published>2010-02-05T02:36:49+00:00</published>
    <updated>2010-02-05T02:36:49+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/watch_your_self"/>
    <title>Watch your self </title>
    <content type="html">
&lt;p&gt;Blocks and closures are probably the most powerful, and least understood part of the Ruby programming language, combined &lt;tt&gt;instance_eval&lt;/tt&gt;, it can create some unintuitive bugs.&lt;/p&gt; &lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;In my Mail library for Ruby, I have made use of &lt;tt&gt;instance_eval&lt;/tt&gt; to provide a domain specific language for email, this allows me to offer the following as valid Ruby code:&lt;/p&gt;
&lt;pre class="ruby"&gt;
m = Mail.new do
       to 'mikel@test.lindsaar.net'
     from 'you@test.lindsaar.net'
  subject 'This is a valid email'
     body "When this block closes it will " +
          "return an email message."
end
&lt;/pre&gt;
&lt;p&gt;This bit of code is calling the #new method on the Mail module, which accepts a block.  This which creates a new &lt;tt&gt;Mail::Message&lt;/tt&gt;, passing the block of ruby code which in turn calls &lt;tt&gt;instance_eval&lt;/tt&gt; on itself, passing the Ruby code that is inside the block of code that we wrote between the &lt;tt&gt;do&lt;/tt&gt; and &lt;tt&gt;end&lt;/tt&gt; keywords.&lt;/p&gt;
&lt;p&gt;The newly created &lt;tt&gt;Mail::Message&lt;/tt&gt; now runs that block on itself, calling the &lt;tt&gt;to()&lt;/tt&gt;, &lt;tt&gt;from()&lt;/tt&gt;, &lt;tt&gt;subject()&lt;/tt&gt; and &lt;tt&gt;body()&lt;/tt&gt; methods in turn, passing the strings we gave it.&lt;/p&gt;
&lt;p&gt;Once done, the Mail module then calls deliver on the &lt;tt&gt;Mail::Message&lt;/tt&gt; and the email is sent on its way.&lt;/p&gt;
&lt;p&gt;The code that makes the above happen is inside the Mail library:&lt;/p&gt;
&lt;pre class="ruby"&gt;
module Mail

  class Message
    def initialize
      # ... initialization
      if block_given?
        instance_eval(&amp;amp;block)
      end
    end
  end
  
  def Mail.new(*args, &amp;amp;block)
    Mail::Message.new(args, &amp;amp;block)
  end

end
&lt;/pre&gt;
&lt;h3&gt;Gotcha&lt;/h3&gt;
&lt;p&gt;All of the above is pretty straight forward and it works pretty much as you would expect, but there is one use case that will trip you up.&lt;/p&gt;
&lt;p&gt;Suppose you don&amp;#8217;t want to pass in strings to your Mail object?  Suppose you want to pass in &lt;strong&gt;instance variables&lt;/strong&gt; instead?  Something like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
@text = "When this block closes it will " +
        "return an email message."
@to   = 'mikel@test.lindsaar.net'
@subject = "This is a valid email"

Mail.new do
       to @to
     from 'you@test.lindsaar.net'
  subject @subject
     body @text_body
end
&lt;/pre&gt;
&lt;p&gt;This ruby code will run successfully, but it will not return what you think.  This is because the instance variables you pass into the block are evaluated within the scope of the &lt;tt&gt;Mail::Message&lt;/tt&gt; and inside the &lt;tt&gt;Mail::Message&lt;/tt&gt;, &lt;tt&gt;&lt;code&gt;text&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&lt;/code&gt;to&lt;/tt&gt; and &lt;tt&gt;@subject&lt;/tt&gt; all evaluate to &lt;tt&gt;nil&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This is where you need to watch your self.  Inside of the &lt;tt&gt;Mail.new do.. end&lt;/tt&gt; block, self effectively becomes the &lt;tt&gt;Mail::Message&lt;/tt&gt;, and the mail message has not defined the instance variables you are passing in.&lt;/p&gt;
&lt;h3&gt;Solutions&lt;/h3&gt;
&lt;p&gt;To get around this, you can do a number of things.&lt;/p&gt;
&lt;p&gt;First, you can use methods instead of instance variables:&lt;/p&gt;
&lt;pre class="ruby"&gt;
def body_text
  "When this block closes it will " +
  "return an email message."
end

def to_address
  'mikel@test.lindsaar.net'
end

def default_subject
  "This is a valid email"
end

Mail.new do
       to to_address
     from 'you@test.lindsaar.net'
  subject default_subject
     body body_text
end
&lt;/pre&gt;
&lt;p&gt;This is obviously a lot more code, but in practice you usually have the to, subject and body text already being generated by methods inside your code, so it can work.&lt;/p&gt;
&lt;p&gt;The other solution is a lot more simple, don&amp;#8217;t use a block:&lt;/p&gt;
&lt;pre class="ruby"&gt;
@text = "When this block closes it will " +
        "return an email message."
@to   = 'mikel@test.lindsaar.net'
@subject = "This is a valid email"

m = Mail.new
m.to @to
m.from 'you@test.lindsaar.net'
m.subject @subject
m.body @text
&lt;/pre&gt;
&lt;p&gt;Which is arguably less pretty, but you are not going to get caught out.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/is_rails_3_a_game_changer</id>
    <published>2010-02-04T00:38:07+00:00</published>
    <updated>2010-02-04T00:38:07+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/is_rails_3_a_game_changer"/>
    <title>Is Rails 3.0 a Game Changer? </title>
    <content type="html">
&lt;p&gt;With Rails 3 on its way to release, and all it is bringing in terms of features and refactorization, some might be wondering, is it a &amp;#8220;game changer&amp;#8221;?&lt;/p&gt; &lt;p&gt;Well, the simple answer to that is, &amp;#8220;Who cares?&amp;#8221;&lt;/p&gt;
&lt;p&gt;The important question is not &amp;#8220;will Rails 3 revolutionise the web development industry?&amp;#8221; but a much more pragmatic one of &amp;#8220;what does Rails 3 offer that will help me?&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Or more importantly &amp;#8220;Will upgrading my site to Rails 3 be worth it!?&amp;#8221;&lt;/p&gt;
&lt;p&gt;And I feel the honest answer to that last question is &amp;#8211; yes.&lt;/p&gt;
&lt;p&gt;But here is the pinch, the benefit you and your site will gain from upgrading will not be realised from the improvements in the latest way to validate a model, or the new query syntax, because, let&amp;#8217;s be real here, if you are upgrading, then whatever you have right now is most likely working, so even though Rails 3 gives you another three or four ways to skin the problem, the problem will just be skinned as it was before, regardless of elegance.&lt;/p&gt;
&lt;p&gt;Sure there are gains to be had from cleaning up horrid old find methods and migrating to a chain-able relation syntax.  Or cleaner, more usable, mailers from the new ActionMailer syntax.  But all of these are marginal improvements, they help, sure, but for an existing operational site, don&amp;#8217;t give a huge amount of benefit.&lt;/p&gt;
&lt;p&gt;The real benefit I think your site will gain from Rails 3 comes down to just three killer features; &lt;span class="caps"&gt;HTML&lt;/span&gt; 5, Modularity and speed.&lt;/p&gt;
&lt;p&gt;Let me explain myself here before you all go &lt;a href="http://github.com/rails/rails/commit/2ebea1c02d10e0fea26bd98d297a8f4d41dc1aff#comments"&gt;&lt;span class="caps"&gt;OMGWTFKTHXBAI&lt;/span&gt;!?!&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; 5&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; 5 is the new black.&lt;/p&gt;
&lt;p&gt;There, I&amp;#8217;ve said it.&lt;/p&gt;
&lt;p&gt;There are lots of ideas but nothing really concrete on how &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 is going to change the web screen-scape, there is definitely movement at the station, but the word is not quite around yet and there are still a lot of people still looking at each other going &amp;#8220;hmmm&amp;#8221;.&lt;/p&gt;
&lt;p&gt;The latest release from Apple show them positioning their products to take full advantage of &lt;span class="caps"&gt;HTML&lt;/span&gt; 5, and a lot can be done with this new standard, it may well become the flash killer many people are hoping.&lt;/p&gt;
&lt;p&gt;The real exciting thing about &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 though is its capabilities in the mobile device world.  &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 and mobile devices are made for each other, literally, and this works &lt;span class="caps"&gt;NOW&lt;/span&gt;.  It&amp;#8217;s not something that might work when the browsers get around to it, it is a feature that you can leverage instantly.&lt;/p&gt;
&lt;p&gt;For us Rails developers, the cool thing is v3 has now moved in this direction.  With its &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 support now baked into Action Pack helpers and a &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 viewpoint on how to present web pages, it is gearing up for the future, whatever that may be.&lt;/p&gt;
&lt;p&gt;Getting your app updated to version 3 will not suddenly make the sky open up with the &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 Gods shining down at you and driving more traffic at your site, but it will place you in a very good position to take advantage, quickly, of whatever will happen, and leverage the mobile market like never before.&lt;/p&gt;
&lt;h3&gt;Modularity&lt;/h3&gt;
&lt;p&gt;Rails 3 provides a modular framework that is, wait for it, &lt;strong&gt;extensible&lt;/strong&gt;.  All of the internals in Rails received a massive clean out turning them into, essentially, the same type of object as any other Rails plugin.  Calling Action Mailer or Active Record &amp;#8220;plugins&amp;#8221;, isn&amp;#8217;t really fair considering how functional they are, but really, when you get down to it, that&amp;#8217;s all they are.  They are just parts of the Rails framework, that can be &lt;strong&gt;swapped out&lt;/strong&gt; with other plugins.&lt;/p&gt;
&lt;p&gt;You have already seen alternatives for Active Record (Datamapper, Sequel, Mongomapper et al) but traditionally, getting these sorts of plugins working in Rails has been a sparring match with Action Pack and this pain was the motivation behind creating Active Model, the first step on modularising the Rails framework.&lt;/p&gt;
&lt;p&gt;But think about it for a second, with a complete Plugin &lt;span class="caps"&gt;API&lt;/span&gt;, documented, showing all the hooks, features and methods your new plugin can take advantage of, and with that &lt;span class="caps"&gt;API&lt;/span&gt; having full, defined access to the entire Rails stack from boot to shutdown, your opportunities to create or take advantage of something incredible in this space have just increased several thousand fold.&lt;/p&gt;
&lt;p&gt;Want to make a killer admin interface?  Want to create a &amp;#8220;plug in&amp;#8221; blog?  Need a forum feature in your Rails app?  You now have defined tools to make that happen.&lt;/p&gt;
&lt;p&gt;And &lt;strong&gt;that&lt;/strong&gt; is reason enough to upgrade to Rails 3.  If your app is not on Rails 3, you can&amp;#8217;t take advantage of the community of functionality that is going to grow up around this platform as we move forward documenting and establishing this community.&lt;/p&gt;
&lt;p&gt;But if you are already on Rails 3, and someone releases a new gem that provides you a new and amazing way to zig when everyone else is zagging, then, you will be in a position to implement rapidly.&lt;/p&gt;
&lt;h3&gt;Speed&lt;/h3&gt;
&lt;p&gt;I am not talking about how fast a Rails app can serve up a page of &lt;span class="caps"&gt;HTML&lt;/span&gt; here, although, Rails has had a ton of improvements in that area, I am talking about how fast you and your application can react to the changes occurring on the web today.&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; 5 support and Modularity bring you agility and speed.  You will be able to react to a changing web rapidly, and being able to move fast without baggage holding you down translates into $$ in your pocket.&lt;/p&gt;
&lt;p&gt;Now that I have written the above, don&amp;#8217;t get me wrong, I am not downplaying the massive amount of work done to improve Rails as a framework, and I am developing an application on Rails 3 right now that has been an absolute dream compared with developing on Rails 2.&amp;#215;.&lt;/p&gt;
&lt;p&gt;But I do think, at the end of all this, you too should be able to answer the question of &amp;#8220;Will upgrading my site to Rails 3 be worth it!?&amp;#8221; with just one word.&lt;/p&gt;
&lt;p&gt;Yes.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/where-did-the-scripts-go</id>
    <published>2010-02-03T19:46:00+00:00</published>
    <updated>2010-02-03T19:46:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/where-did-the-scripts-go"/>
    <title>Where did the scripts go? </title>
    <content type="html">
&lt;p&gt;The recent &lt;a href="http://github.com/rails/rails/commit/d236827881d119fb9ad25c81ce8e7756f1966823"&gt;commit&lt;/a&gt; removing the contents of the &lt;tt&gt;script&lt;/tt&gt; directory streamlines rails somewhat.  But there were a lot of files in that directory, this is a quick cheat sheet on what replaces what&amp;#8230;&lt;/p&gt; &lt;p&gt;The script directory used to contain&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;strong&gt;Old Script File&lt;/strong&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;&lt;strong&gt;How to use now&lt;/strong&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;&lt;strong&gt;Shortcut Command&lt;/strong&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;about&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rake about&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;server&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails server&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails s&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;console&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails console&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails c&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;dbconsole&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails dbconsole&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails db&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;generate&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails generate&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails g&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;destroy&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails destroy&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;performance/benchmark&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails benchmark&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;performance/profiler&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails profiler&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;plugin&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails plugin&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;tt&gt;runner&lt;/tt&gt;&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;rails runner&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;As you can see from the above, the &lt;ins&gt;server&lt;/ins&gt;, &lt;ins&gt;console&lt;/ins&gt;, &lt;ins&gt;dbconsole&lt;/ins&gt; and &lt;ins&gt;generate&lt;/ins&gt; parameters also have shortcut aliases.&lt;/p&gt;
&lt;p&gt;When you run the &lt;tt&gt;rails&lt;/tt&gt; command from within a Rails application directory, the above commands work, however, if you run the &lt;tt&gt;rails&lt;/tt&gt; command from outside a Rails application directory, then the usual Rails initialization command works in the format of &lt;tt&gt;rails/railties/bin/rails APP_PATH [options]&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Note with the new 3.0 rails command, the &lt;tt&gt;APP_NAME&lt;/tt&gt; has been changed to an &lt;tt&gt;APP_PATH&lt;/tt&gt; and any options now come at the end, not before.  &lt;tt&gt;APP_PATH&lt;/tt&gt; allows you to initialise a new Rails application at some other path name and uses the last part of the path name for your application.&lt;/p&gt;
&lt;p&gt;One word of warning, if you are running the Rails 3.0 Beta using the &lt;tt&gt;&amp;#8212;dev&lt;/tt&gt; flag from a clone of the Rails source tree, then be sure to call &lt;tt&gt;script/rails &lt;command&gt;&lt;/tt&gt; otherwise the rails binary that is run will be from your system gems, and you will end up initialising a new Rails application inside your new Rails 3 app directory.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/validates_rails_3_awesome_is_true</id>
    <published>2010-01-31T12:17:00+00:00</published>
    <updated>2010-01-31T12:17:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/validates_rails_3_awesome_is_true"/>
    <title>validates :rails_3, :awesome =&gt; true</title>
    <content type="html">
&lt;p&gt;The new validation methods in Rails 3.0 have been extracted out to Active Model, but in the process have been sprinkled with &lt;span class="caps"&gt;DRY&lt;/span&gt; goodness&amp;#8230;&lt;/p&gt; &lt;p&gt;As you would know from Yehuda&amp;#8217;s post on &lt;a href="http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/"&gt;Active Model abstraction&lt;/a&gt;, in Rails 3.0, Active Record now mixes in many aspects of Active Model, including the validates modules.&lt;/p&gt;
&lt;p&gt;Before we get started though, your old friends still exist:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;tt&gt;validates_acceptance_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_associated&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_confirmation_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_each&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_exclusion_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_format_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_inclusion_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_length_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_numericality_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_presence_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_size_of&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;validates_uniqueness_of&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Are still around and not going anywhere, but Rails version 3 offers you some cool, nay, awesome alternatives:&lt;/p&gt;
&lt;h3&gt;Introducing the validates method&lt;/h3&gt;
&lt;p&gt;The Validates method accepts an attribute, followed by a hash of validation options.&lt;/p&gt;
&lt;p&gt;Which means you can type something like:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Person &amp;lt; ActiveRecord::Base
  validates :email, :presence =&amp;gt; true
end
&lt;/pre&gt;
&lt;p&gt;The options you can pass in to &lt;span class="ruby"&gt;validates&lt;/span&gt; are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;tt&gt;:acceptance =&amp;gt; Boolean&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:confirmation =&amp;gt; Boolean&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:exclusion =&amp;gt; { :in =&amp;gt; Ennumerable }&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:inclusion =&amp;gt; { :in =&amp;gt; Ennumerable }&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:format =&amp;gt; { :with =&amp;gt; Regexp }&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:length =&amp;gt; { :minimum =&amp;gt; Fixnum, maximum =&amp;gt; Fixnum, }&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:numericality =&amp;gt; Boolean&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:presence =&amp;gt; Boolean&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:uniqueness =&amp;gt; Boolean&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which gives you a huge range of easily usable, succinct options for your attributes and allows you to place your validations for each attribute in one place.&lt;/p&gt;
&lt;p&gt;So for example, if you had to validate name and email, you might do something like this:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# app/models/person.rb
class User &amp;lt; ActiveRecord::Base
  validates :name,  :presence =&amp;gt; true, 
                    :length =&amp;gt; {:minimum =&amp;gt; 1, :maximum =&amp;gt; 254}
                   
  validates :email, :presence =&amp;gt; true, 
                    :length =&amp;gt; {:minimum =&amp;gt; 3, :maximum =&amp;gt; 254},
                    :uniqueness =&amp;gt; true,
                    :format =&amp;gt; {:with =&amp;gt; /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}
  
end
&lt;/pre&gt;
&lt;p&gt;This allows us to be able to look at a model and easily see the validations in one spot for each attribute, win for code readability!&lt;/p&gt;
&lt;h3&gt;Extracting Common Use Cases&lt;/h3&gt;
&lt;p&gt;However, the &lt;span class="ruby"&gt;:format =&amp;gt; {:with =&amp;gt; EmailRegexp}&lt;/span&gt; is a bit of a drag to retype everywhere, and definitely fits the idea of a reusable validation that we might want to use in other models.&lt;/p&gt;
&lt;p&gt;And what if you wanted to use a really impressive Regular Expression that takes more than a few characters to type to show that you know how to Google?&lt;/p&gt;
&lt;p&gt;Well, validations can also except a custom validation.&lt;/p&gt;
&lt;p&gt;To use this, we first make an &lt;span class="ruby"&gt;email_validator.rb&lt;/span&gt; file in &lt;span class="ruby"&gt;Rails.root&lt;/span&gt;&amp;#8217;s lib directory:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# lib/email_validator.rb
class EmailValidator &amp;lt; ActiveModel::EachValidator

  EmailAddress = begin
    qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
    dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
    atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
      '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
    quoted_pair = '\\x5c[\\x00-\\x7f]'
    domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
    quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
    domain_ref = atom
    sub_domain = "(?:#{domain_ref}|#{domain_literal})"
    word = "(?:#{atom}|#{quoted_string})"
    domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
    local_part = "#{word}(?:\\x2e#{word})*"
    addr_spec = "#{local_part}\\x40#{domain}"
    pattern = /\A#{addr_spec}\z/
  end

  def validate_each(record, attribute, value)
    unless value =~ EmailAddress
      record.errors[attribute] &amp;lt;&amp;lt; (options[:message] || "is not valid") 
    end
  end
  
end
&lt;/pre&gt;
&lt;p&gt;As each file in the lib directory gets loaded automatically by Rails, and as our class inherits from &lt;span class="ruby"&gt;ActiveModel::EachValidator&lt;/span&gt; the class name is used to create a dynamic validator that you can then use in any object that makes use of the &lt;span class="ruby"&gt;ActiveModel::Validations&lt;/span&gt; mix in, such as Active Record objects.&lt;/p&gt;
&lt;p&gt;The name of the dynamic validation option is based on whatever is to the left of &amp;#8220;Validator&amp;#8221; down-cased and underscorized.&lt;/p&gt;
&lt;p&gt;So now in our User class we can simply change it to:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# app/models/person.rb
class User &amp;lt; ActiveRecord::Base
  validates :name,  :presence =&amp;gt; true, 
                    :length =&amp;gt; {:minimum =&amp;gt; 1, :maximum =&amp;gt; 254}
                   
  validates :email, :presence =&amp;gt; true, 
                    :length =&amp;gt; {:minimum =&amp;gt; 3, :maximum =&amp;gt; 254},
                    :uniqueness =&amp;gt; true,
                    :email =&amp;gt; true
  
end
&lt;/pre&gt;
&lt;p&gt;Notice the &lt;span class="ruby"&gt;:email =&amp;gt; true&lt;/span&gt; call?  This is much cleaner and simple, and more importantly, reusable.&lt;/p&gt;
&lt;p&gt;Now in our console, we will see something like:&lt;/p&gt;
&lt;pre class="shell"&gt;
 $ ./script/console 
Loading development environment (Rails 3.0.pre)
?&amp;gt; u = User.new(:name =&amp;gt; 'Mikel', :email =&amp;gt; 'bob')
=&amp;gt; #&amp;lt;User id: nil, name: "Mikel", email: "bob", created_at: nil, updated_at: nil&amp;gt;
&amp;gt;&amp;gt; u.valid?
=&amp;gt; false
&amp;gt;&amp;gt; u.errors
=&amp;gt; #&amp;lt;OrderedHash {:email=&amp;gt;["is not valid"]}&amp;gt;
&lt;/pre&gt;
&lt;p&gt;With our custom error message &amp;#8220;is not valid&amp;#8221; showing up in the email.&lt;/p&gt;
&lt;h3&gt;Class Wide Validations&lt;/h3&gt;
&lt;p&gt;But what if you had, say, three different models, users, visitors and customers, all of which shared some common validations, but were different enough that you had to separate them out?&lt;/p&gt;
&lt;p&gt;Well, you could use another custom validator, but pass it to your models as a &lt;span class="ruby"&gt;validates_with&lt;/span&gt; call:&lt;/p&gt;
&lt;pre class="ruby"&gt;
# app/models/person.rb
class User &amp;lt; ActiveRecord::Base
  validates_with HumanValidator
end

# app/models/person.rb
class Visitor &amp;lt; ActiveRecord::Base
  validates_with HumanValidator
end

# app/models/person.rb
class Customer &amp;lt; ActiveRecord::Base
  validates_with HumanValidator
end
&lt;/pre&gt;
&lt;p&gt;You could then make a file in your lib directory like so:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class HumanValidator &amp;lt; ActiveModel::Validator

  def validate(record)
    record.errors[:base] &amp;lt;&amp;lt; "This person is dead" unless check(human)
  end

  private

    def check(record)
      (record.age &amp;lt; 200) &amp;amp;&amp;amp; (record.age &amp;gt; 0)
    end
  
end
&lt;/pre&gt;
&lt;p&gt;Which is an obviously contrived example, but would produce this result in our console:&lt;/p&gt;
&lt;pre class="shell"&gt;
$ ./script/console 
Loading development environment (Rails 3.0.pre)
&amp;gt;&amp;gt; u = User.new
=&amp;gt; #&amp;lt;User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil&amp;gt;
&amp;gt;&amp;gt; u.valid?
=&amp;gt; false
&amp;gt;&amp;gt; u.errors
=&amp;gt; #&amp;lt;OrderedHash {:base=&amp;gt;["This person is dead"]}&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;Trigger times&lt;/h3&gt;
&lt;p&gt;As you would expect, any validates method can have the following sub options added to them:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;tt&gt;:on&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:if&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:unless&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:allow_blank&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;:allow_nil&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these can take a call to a method on the record itself.  So we could have:&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Person &amp;lt; ActiveRecord::Base
  
  validates :post_code, :presence =&amp;gt; true, :unless =&amp;gt; :no_postcodes?

  def no_postcodes?
    ['TW'].include?(country_iso)
  end
  
end
&lt;/pre&gt;
&lt;p&gt;I think you can see this gives you a huge amount of flexibility.&lt;/p&gt;
&lt;h3&gt;Credits&lt;/h3&gt;
&lt;p&gt;Kudos to &lt;a href="http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/"&gt;Jamie Hill&lt;/a&gt;, &lt;a href="http://blog.plataformatec.com.br/"&gt;Jos&#233; Valim&lt;/a&gt; and &lt;a href="http://joshpeek.com/"&gt;Joshua Peek&lt;/a&gt; for getting &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/3058-patch-sexy-validations"&gt;the patch&lt;/a&gt; in.&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/new-rails-version-3-guides-online</id>
    <published>2010-01-29T16:53:00+00:00</published>
    <updated>2010-01-29T16:53:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/new-rails-version-3-guides-online"/>
    <title>New Rails Version 3.0 Guides Online</title>
    <content type="html">
&lt;p&gt;I am going through and updating a lot of the guides for Rails.  As I do each one, I will update this post.&lt;/p&gt; &lt;p&gt;Rails 3 has a &lt;em&gt;lot&lt;/em&gt; of changes.  Don&amp;#8217;t be fooled, the core team has been hard at work for the last year ever since the &lt;a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/"&gt;Merb&lt;/a&gt; and &lt;a href="http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3"&gt;Rails&lt;/a&gt; announcement.&lt;/p&gt;
&lt;p&gt;You can think of Rails 3 as a massive refactoring and extraction project.  The amount of spring cleaning is, to put it bluntly, phenomenal.&lt;/p&gt;
&lt;p&gt;So as I go through each guide and update it, and it gets published, I&amp;#8217;ll link to it here, so you can all follow along :)  I would also like all the feed back in can get on these.  You can email me, send me a tweet or comment here.&lt;/p&gt;
&lt;h3&gt;Getting Started with Rails&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://guides.rails.info/getting_started.html"&gt;Getting started with Rails&lt;/a&gt; was, appropriately, the first guide that was updated.  This was different enough that the version 2 guide simply did not work on Rails 3.  You can also find all the code for the getting started guide at my &lt;a href="http://github.com/mikel/getting-started-code"&gt;Getting Started Code&lt;/a&gt; github repository.&lt;/p&gt;
&lt;h3&gt;Layouts and Rendering in Rails&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://guides.rails.info/layouts_and_rendering.html"&gt;Layouts and Rendering in Rails&lt;/a&gt; was the next guide updated.  Again, a lot of changes in Rails 3, highlights on the &lt;span class="caps"&gt;HTML&lt;/span&gt; 5 implementation, handling of the new &lt;span class="fixed"&gt;video_tag&lt;/span&gt; and &lt;span class="fixed"&gt;audio_tag&lt;/span&gt; helper methods and a big gotcha on partial rendering (you&amp;#8217;ll have to read the guide for all the juicy bits, but enough to say that a lot &lt;em&gt;&lt;span class="caps"&gt;LESS&lt;/span&gt;&lt;/em&gt; local variables get magically defined in partials now.&lt;/p&gt;
&lt;h3&gt;Next Up&lt;/h3&gt;
&lt;p&gt;I am mid way the Action Mailer guide now that the code has been updated to the new &lt;span class="caps"&gt;API&lt;/span&gt;.  Check back soon.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/new-actionmailer-api-in-rails-3</id>
    <published>2010-01-26T12:13:00+00:00</published>
    <updated>2010-01-26T12:13:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/new-actionmailer-api-in-rails-3"/>
    <title>New ActionMailer API in Rails 3.0</title>
    <content type="html">
&lt;p&gt;Action Mailer has long been the black sheep of the Rails family. Somehow, through many arguments, you get it doing exactly what you want.  But it takes work!  Well, we just fixed that.&lt;/p&gt; &lt;p&gt;Action Mailer now has a new &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;But why?  Well, I had an itch to scratch, I am the maintainer for TMail, but found it very hard to use well, so I sat down and wrote a really Ruby Mail library, called, imaginatively enough, &lt;a href="http://lindsaar.net/2010/1/23/mail-gem-version-2-released"&gt;Mail&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But Action Mailer was still using TMail, so then I replaced out &lt;a href="http://lindsaar.net/2009/12/30/mail-in-actionmailer"&gt;TMail with Mail in Action Mailer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And now, with all the flexibility that Mail gives us, we all thought it would be a good idea to re-write the Action Mailer &lt;span class="caps"&gt;DSL&lt;/span&gt;.  So with a lot of ideas thrown about between David, Yehuda and myself, we came up with a great &lt;span class="caps"&gt;DSL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I then grabbed &lt;a href="http://blog.plataformatec.com.br/"&gt;Jos&#233; Valim&lt;/a&gt; to pair program together (with him in Poland to me in Sydney!) on ripping out the guts of Action Mailer and replacing it with a lean, mean mailing machine.&lt;/p&gt;
&lt;p&gt;This was &lt;a href="http://github.com/rails/rails/commit/abad097016bf5243e9812f6a031f421a986b09f7"&gt;merged&lt;/a&gt; today.&lt;/p&gt;
&lt;p&gt;So what does this all mean?  Well, code speaks louder than words, so:&lt;/p&gt;
&lt;h3&gt;Creating Email Messages:&lt;/h3&gt;
&lt;p&gt;Instead of this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
 class Notifier &amp;lt; ActionMailer::Base
   def signup_notification(recipient)
     recipients      recipient.email_address_with_name
     subject         "New account information"
     from            "system@example.com"
     content_type    "multipart/alternative"
     body            :account =&amp;gt; recipient

     part :content_type =&amp;gt; "text/html",
       :data =&amp;gt; render_message("signup-as-html")

     part "text/plain" do |p|
       p.body = render_message("signup-as-plain")
       p.content_transfer_encoding = "base64"
     end
     
     attachment "application/pdf" do |a|
       a.body = generate_your_pdf_here()
     end

     attachment :content_type =&amp;gt; "image/jpeg",
       :body =&amp;gt; File.read("an-image.jpg")
     
   end
 end
&lt;/pre&gt;
&lt;p&gt;You can do this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
class Notifier &amp;lt; ActionMailer::Base
  default :from =&amp;gt; "system@example.com"
  
  def signup_notification(recipient)
    @account = recipient

    attachments['an-image.jp'] = File.read("an-image.jpg")
    attachments['terms.pdf'] = {:content =&amp;gt; generate_your_pdf_here() }

    mail(:to =&amp;gt; recipient.email_address_with_name,
         :subject =&amp;gt; "New account information")
  end
end
&lt;/pre&gt;
&lt;p&gt;Which I like a lot more :)&lt;/p&gt;
&lt;p&gt;Any instance variables you define in the method become available in the email templates, just like it does with Action Controller, so all of the templates will have access to the @account instance var which has the recipient in it.&lt;/p&gt;
&lt;p&gt;The mail method above also accepts a block so that you can do something like this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
def hello_email
  mail(:to =&amp;gt; recipient.email_address_with_name) do |format|
    format.text { render :text =&amp;gt; "This is text!" }
    format.html { render :text =&amp;gt; "&amp;lt;h1&amp;gt;This is HTML&amp;lt;/h1&amp;gt;" }
  end
end
&lt;/pre&gt;
&lt;p&gt;In the same style that a respond_to block works in Action Controller.&lt;/p&gt;
&lt;h3&gt;Sending Email Messages:&lt;/h3&gt;
&lt;p&gt;Additionally, sending messages has been simplified as well.  A Mail::Message object knows how to deliver itself, so all of the delivery code in Action Mailer was simply removed and responsibility given to the Mail::Message.&lt;/p&gt;
&lt;p&gt;Instead of having magic methods called deliver_* and create_* we just call the method which returns a Mail::Message object, and you just call deliver on that:&lt;/p&gt;
&lt;p&gt;So this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
Notifier.deliver_signup_notification(recipient)
&lt;/pre&gt;
&lt;p&gt;Becomes this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
Notifier.signup_notification(recipient).deliver
&lt;/pre&gt;
&lt;p&gt;And this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
message = Notifier.create_signup_notification(recipient)
Notifier.deliver(message)
&lt;/pre&gt;
&lt;p&gt;Becomes this:&lt;/p&gt;
&lt;pre class="fixed"&gt;
message = Notifier.signup_notification(recipient)
message.deliver
&lt;/pre&gt;
&lt;p&gt;You still have access to all the usual types of delivery agents though, :smtp, :sendmail, :file and :test, these all work as they did with the prior version of ActionMailer.&lt;/p&gt;
&lt;h3&gt;Receiving Emails&lt;/h3&gt;
&lt;p&gt;This has not changed, except now you get a Mail::Message object instead of a TMail object.&lt;/p&gt;
&lt;p&gt;Mail::Message will be getting a :reply method soon which will automatically map the Reply related fields properly.  Once this is done, we will re-vamp receiving emails as well to simplify.&lt;/p&gt;
&lt;h3&gt;Old &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;And&amp;#8230; of course, if you still &amp;#8220;like the old way&amp;#8221;, the new Action Mailer still supports the old &lt;span class="caps"&gt;API&lt;/span&gt; and all the old tests still pass.  We have moved everything relating to the old &lt;span class="caps"&gt;API&lt;/span&gt; into deprecated_api.rb and this will be removed in a future release of Rails.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;With Mail and this refactor, Action Mailer has now finally become just a &lt;span class="caps"&gt;DSL&lt;/span&gt; wrapper between Mail and Action Controller.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/mail-gem-version-2-released</id>
    <published>2010-01-23T17:05:00+00:00</published>
    <updated>2010-01-23T17:05:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/mail-gem-version-2-released"/>
    <title>Mail gem version 2 released</title>
    <content type="html">
&lt;p&gt;The past month has seen a flurry in activity on the &lt;a href="http://github.com/mikel/mail"&gt;Mail gem&lt;/a&gt; but I just pushed 2.0.3 to GemCutter, it is quite a release!&lt;/p&gt; &lt;p&gt;If you haven&amp;#8217;t heard of mail, you can get some background &lt;a href="http://lindsaar.net/2009/9/17/mail-tmail-the-future-of-ruby-email-handling"&gt;here&lt;/a&gt;, &lt;a href="http://lindsaar.net/2009/9/18/mail-and-bounced-emails"&gt;here&lt;/a&gt;, &lt;a href="http://lindsaar.net/2009/10/28/new-mail-gem-released"&gt;here&lt;/a&gt; and &lt;a href="http://lindsaar.net/2009/11/1/mail-gets-some-compliments"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mail is a very Ruby way to handle emails.&lt;/p&gt;
&lt;p&gt;Version 2.0.3 is the first gem release I have in the last couple of weeks, this is because I went through and (in good &lt;span class="caps"&gt;BDD&lt;/span&gt; style) refactored major parts of the Mail gem so it handles better.&lt;/p&gt;
&lt;p&gt;Some of the major things were:&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt; Delivery Agent revamped&lt;/h3&gt;
&lt;p&gt;I went through the &lt;span class="caps"&gt;SMTP&lt;/span&gt; delivery agent and cleaned it up, also adding examples for how you use Mail with GMail and MobileMe so there is no more guess work here.&lt;/p&gt;
&lt;h3&gt;Delivery agents are now instance based&lt;/h3&gt;
&lt;p&gt;This means that each mail object that you instantiate can have its own delivery method.  Why is this important?&lt;/p&gt;
&lt;p&gt;Well, say you are writing a web based email client for multiple users, but each user has their own &lt;span class="caps"&gt;SMTP&lt;/span&gt; hosts, when you make a mail object for that user, you could assign the delivery method for that user to that mail object, then delivery is just calling .deliver! on the mail object, and away it goes.&lt;/p&gt;
&lt;p&gt;There is still default class wide settings for all the major delivery agents (&lt;span class="caps"&gt;SMTP&lt;/span&gt;, Sendmail and File) however, you can now over ride these.&lt;/p&gt;
&lt;pre class="fixed"&gt;
mail1 = Mail.new
mail1.delivery_method #=&amp;gt; #&amp;lt;Mail::SMTP:0x101381c18 @setting
mail2 = Mail.new
mail2.delivery_method :sendmail
mail2.delivery_method #=&amp;gt; #&amp;lt;Mail::Sendmail:0x101381c18 @setting
mail1.delivery_method #=&amp;gt; #&amp;lt;Mail::SMTP:0x101381c18 @setting
&lt;/pre&gt;
&lt;h3&gt;Attachments are now just parts&lt;/h3&gt;
&lt;p&gt;Before, an Attachment had its own object type in Mail.  This was nice and all, but was just added cruft that got in there during the &lt;span class="caps"&gt;BDD&lt;/span&gt; cycle.  I ripped out the entire attachment class, and an attachment is now just a plain old Mail::Part.  This makes the code simpler, which is good for everyone.&lt;/p&gt;
&lt;p&gt;Mail also now has a very cool attachments &lt;span class="caps"&gt;API&lt;/span&gt;:&lt;/p&gt;
&lt;pre class="fixed"&gt;
mail = Mail.new
mail.attachments #=&amp;gt; []
mail.attachments['filename.jpg'] = File.read('filename.jpg')
mail.attachments['file.pdf'] = {:content_type =&amp;gt; 'application/x-pdf',
                                :content =&amp;gt; File.read('file')
mail.attachments.length #=&amp;gt; 2
mail.attachments[0].filename #=&amp;gt; 'filename.jpg'
mail.attachments['filename.jpg'] #=&amp;gt; &amp;lt;# Mail::Part, filename = 'filename.jpg' ...&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Yes, that is an ArrayHashThingy&#8482; class, and, it rocks :)  It is actually an AttachmentsList object that inherits from Array and implements a custom [] class.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="http://www.loudthinking.com/"&gt;David&lt;/a&gt; and &lt;a href="http://yehudakatz.com/"&gt;Yehuda&lt;/a&gt; who were brainstorming on the new ActionMailer 3.0 &lt;span class="caps"&gt;API&lt;/span&gt; with me, which I used for inspiration for this implementation.  (more on the ActionMailer 3.0 &lt;span class="caps"&gt;API&lt;/span&gt; that I am pair programming with &lt;a href="http://blog.plataformatec.com.br/"&gt;Jos&#233;&lt;/a&gt; later :)&lt;/p&gt;
&lt;h3&gt;Mail returns default values for fields, that can be modified&lt;/h3&gt;
&lt;p&gt;Mail returns an array of address specs when you call &lt;span class="fixed"&gt;mail.to&lt;/span&gt; and would re-initialize that array with new values when you called &lt;span class="fixed"&gt;mail.to=&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;However, this array object was just a result of a method, it was not a representation of the addresses within the address field, so then doing &lt;span class="fixed"&gt;mail.to &amp;lt;&amp;lt; value&lt;/span&gt; would seem to work (no error) but the address would get lost, for example:&lt;/p&gt;
&lt;pre class="fixed"&gt;
# Old (unintuitive method)
mail = Mail.new("To: mikel@test.lindsaar.net")
mail.to #=&amp;gt; ['mikel@test.lindsaar.net']
mail.to &amp;lt;&amp;lt; 'ada@test.lindsaar.net'
mail.to #=&amp;gt; ['mikel@test.lindsaar.net']
&lt;/pre&gt;
&lt;p&gt;This now works on all Address fields that can take more than one address, so&lt;/p&gt;
&lt;pre class="fixed"&gt;
# New (intuitive) method
mail = Mail.new("To: mikel@test.lindsaar.net")
mail.to #=&amp;gt; ['mikel@test.lindsaar.net']
mail.to &amp;lt;&amp;lt; 'ada@test.lindsaar.net'
mail.to #=&amp;gt; ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
&lt;/pre&gt;
&lt;p&gt;Thanks to &lt;a href="http://intertwingly.net/blog/"&gt;Sam&lt;/a&gt; for suggesting this feature.&lt;/p&gt;
&lt;h3&gt;Access returned to the Address objects&lt;/h3&gt;
&lt;p&gt;When you call &lt;span class="fixed"&gt;mail.to&lt;/span&gt; you get a list of address spec strings (&amp;#8216;mikel@test.lindsaar.net&amp;#8217; for example), but it will not give you the display name, or formatted address etc.&lt;/p&gt;
&lt;p&gt;To handle this, you can now call mail[:to] to get the actual ToField object, and then you can call #display_names, #formatted, and #addrs, the last of which will give you the actual Address objects in an array (the original behaviour of Mail), like so:&lt;/p&gt;
&lt;pre class="fixed"&gt;
mail = Mail.new("To: Mikel Lindsaar &amp;lt;mikel@test.lindsaar.net&amp;gt;")
mail.to #=&amp;gt; ['mikel@test.lindsaar.net']
to = mail[:to]  #=&amp;gt; #&amp;lt;Mail::Field:0x10137c718...
to.addrs #=&amp;gt; [#&amp;lt;Mail::Address:2165620900 Address: |mikel@test.lindsaar.net| &amp;gt;]
to.addrs.each do |addr|
  puts "Formatted: #{addr.format}"
  puts "Display:   #{addr.display_name}"
  puts "Address:   #{addr.address}"
end
# Produces:
Formatted: Mikel Lindsaar &amp;lt;mikel@test.lindsaar.net&amp;gt;
Display:   Mikel Lindsaar
Address:   mikel@test.lindsaar.net
=&amp;gt; [#&amp;lt;Mail::Address:2165518560 Address: |Mikel Lindsaar &amp;lt;mikel@test.lindsaar.net&amp;gt;| &amp;gt;]
&lt;/pre&gt;
&lt;p&gt;Thanks to &lt;a href="http://github.com/kbaum"&gt;Karl&lt;/a&gt; for suggesting this would be handy :)&lt;/p&gt;
&lt;h3&gt;More methods added to address fields&lt;/h3&gt;
&lt;p&gt;You can also access an array of the formatted, display_names or addresses directly from address fields:&lt;/p&gt;
&lt;pre class="fixed"&gt;
mail = Mail.new("To: Mikel Lindsaar &amp;lt;mikel@test.lindsaar.net&amp;gt;")
mail[:to].addresses   
#=&amp;gt; ["mikel@test.lindsaar.net"]
mail[:to].formatted
#=&amp;gt; ["Mikel Lindsaar &amp;lt;mikel@test.lindsaar.net&amp;gt;"]
mail[:to].display_names
#=&amp;gt; ["Mikel Lindsaar"]
&lt;/pre&gt;
&lt;h3&gt;Remaining Stuff&lt;/h3&gt;
&lt;p&gt;There are a lot of other small bug fixes, parts now get sorted recursively on encode, body objects will accept an array of strings and call join on them, and many other small things that are in the commit and change logs.  Check it out.&lt;/p&gt;
&lt;p&gt;As always, tickets (and patches) are always welcome, I use &lt;a href="http://github.com/mikel/mail/issues"&gt;GitHub&amp;#8217;s Tracker&lt;/a&gt; for this.  Or you can talk to us on the &lt;a href="http://groups.google.com/group/mail-ruby"&gt;Mail Google Group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy Mailing!&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rename-rails-3-application</id>
    <published>2010-01-19T14:01:00+00:00</published>
    <updated>2010-01-19T14:01:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rename-rails-3-application"/>
    <title>How to rename a Rails 3 Application</title>
    <content type="html">
&lt;p&gt;Renaming a Rails 3 application is something you have to think about now. No, really&amp;#8230; :)&lt;/p&gt; &lt;p&gt;When you create a new Rails 3.0 app with &amp;#8220;rails app_name&amp;#8221; Rails will create the application for you like before, but with a major difference.&lt;/p&gt;
&lt;p&gt;It will Classify your &amp;#8220;app_name&amp;#8221; and use this as the Ruby name space for your application.&lt;/p&gt;
&lt;p&gt;So if you do:&lt;/p&gt;
&lt;pre class="shell"&gt;
rails new app_name
&lt;/pre&gt;
&lt;p&gt;Then your Rails application will have sprinklings of &lt;span style="font-weight:bold"&gt;AppName&lt;/span&gt; throughout the tree.&lt;/p&gt;
&lt;p&gt;If you later decide that your application should be called something more specific than &amp;#8220;AppName&amp;#8221; you need to replace out AppName from the following files:&lt;/p&gt;
&lt;pre class="shell"&gt;
config/application.rb
config/environment.rb
config/environments/development.rb
config/environments/test.rb
config/environments/production.rb
config/routes.rb
config.ru
initializers/secret_token.rb
initializers/session_store.rb
&lt;/pre&gt;
&lt;p&gt;Of course, if you are using TextMate, a simple Project wide search and replace for AppName with your new name, should do the trick.  But it is something to be aware of.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;
&lt;p&gt;Edited 21 Sept 2010: to update per reader comments below.&lt;/p&gt;    </content>
  </entry>
  <entry>
    <id>tag:lindsaar.net,2007:/feed:post/rails-3-examples</id>
    <published>2010-01-19T13:38:00+00:00</published>
    <updated>2010-01-19T13:38:00+00:00</updated>
    <link rel="alternate" type="text/html" href="http://lindsaar.net/rails-3-examples"/>
    <title>Rails 3.0 Examples</title>
    <content type="html">
&lt;p&gt;Rails 3.0 has a lot of new features.  Getting to understand them can be a challenge.  I made a Rails 3.0 repository on github to help everyone get to know some of the new ActiveModel &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8230;&lt;/p&gt; &lt;p&gt;It is at &lt;a href="http://github.com/mikel/rails-examples/"&gt;git://github.com/mikel/rails-examples/&lt;/a&gt; and has instructions on how to download it and get it running.&lt;/p&gt;
&lt;p&gt;It is actually an entire Rails 3.0 App, ready to run.  So you just need to clone it, follow the four steps given in the &lt;span class="caps"&gt;README&lt;/span&gt; and you will have Rails 3.0 running on your system.&lt;/p&gt;
&lt;p&gt;The models directory contains a bunch of &amp;#8220;_person&amp;#8221; models that show off each main module of the ActiveModel &lt;span class="caps"&gt;API&lt;/span&gt; piece by piece.  The implementations are minimal on purpose to show you what you need to get the thing working&amp;#8230;  The instant gratification thing :)&lt;/p&gt;
&lt;p&gt;Please check it out and let me know what you think, or improvements we can make.&lt;/p&gt;
&lt;p&gt;One note, you should update the bundler gem if you are on a bundler version 0.7 or below.&lt;/p&gt;
&lt;p&gt;blogLater&lt;/p&gt;
&lt;p&gt;Mikel&lt;/p&gt;    </content>
  </entry>
</feed>
