<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>Tom Ward</title>
 <link href="http://tomafro.net/atom.xml" rel="self"/>
 <updated>2010-03-02T09:04:42+00:00</updated>
 <id>http://tomafro.net/</id>
 <author>
   <name>Tom Ward</name>
   <email>tom@popdog.net</email>
 </author>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2010/02/updated-rails-template-for-bundler"/>
   <title>An updated rails template for gem bundler</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;A few months ago I wrote &lt;a href=&quot;http://tomafro.net/2009/11/a-rails-template-for-gem-bundler&quot;&gt;a rails template for gem bundler&lt;/a&gt;. Since then, bundler has changed a lot, and my template no longer works. &lt;a href=&quot;http://github.com/tomafro/dotfiles/raw/master/resources/rails/bundler.rb&quot;&gt;Here then is an updated version&lt;/a&gt;, based on &lt;a href=&quot;http://gist.github.com/302406&quot;&gt;this gist&lt;/a&gt; from &lt;a href=&quot;http://arko.net/&quot;&gt;Andre Arko&lt;/a&gt;.  Using it, you should be able to get a rails 2.3.5 project working with bundler in less than 5 minutes.&lt;/p&gt;

&lt;p&gt;The first step is to install the latest bundler.  At the time of writing, this was 0.9.9.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundler&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you should be able to run the template, either on a new project, or on an existing rails 2.3.5 project.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;rails -m http://github.com/tomafro/dotfiles/raw/master/resources/rails/bundler.rb &amp;lt;project&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;On a fresh project, that should be all you need to do.  On an existing that used an older version of bundler, you'll need to remove the old hooks in &lt;code&gt;config/preinitializer.rb&lt;/code&gt; and &lt;code&gt;config/environment.rb&lt;/code&gt;, and the &lt;code&gt;gems&lt;/code&gt; folder.&lt;/p&gt;

&lt;h3&gt;Explaining the template, step by step&lt;/h3&gt;


&lt;p&gt;The first step creates the project &lt;code&gt;Gemfile&lt;/code&gt;, with rails available in all environments, and ruby-debug included in development.  If the project has other gems, they should be added here, rather than using rails own &lt;code&gt;config.gem&lt;/code&gt; mechanism.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Gemfile&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;source &amp;#39;http://rubygems.org&amp;#39;&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;gem &amp;#39;rails&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;#39;&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;group :development do&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  gem &amp;#39;ruby-debug&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The next step is get bundler to load correctly.  This is done in two stages.  First, in &lt;code&gt;config\preinitializer.rb&lt;/code&gt; bundler needs to be setup.  This adds all the bundled gems to the ruby load path, but doesn't initialise them.&lt;br/&gt;
&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;  
&lt;span class=&quot;n&quot;&gt;append_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/config/preinitializer.rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;begin&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  # Require the preresolved locked set of gems.&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  require File.expand_path(&amp;#39;../../.bundle/environment&amp;#39;, __FILE__)&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;rescue LoadError&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  # Fallback on doing the resolve at runtime.&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  require &amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  require &amp;quot;bundler&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  if Bundler::VERSION &amp;lt;= &amp;quot;0.9.5&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    raise RuntimeError, &amp;quot;Bundler incompatible.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;quot; +&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;      &amp;quot;Your bundler version is incompatible with Rails 2.3 and an unlocked bundle.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;quot; +&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;      &amp;quot;Run `gem install bundler` to upgrade or `bundle lock` to lock.&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  else&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    Bundler.setup&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Second, the rails boot process is modified to start the bundler environment.  This 'requires' all gems in the bundle, letting them run initialisation code.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;gsub_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;config/boot.rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Rails.boot!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  &lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;class Rails::Boot&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt; def run&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;   load_initializer&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;   extend_environment&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;   Rails::Initializer.run(:set_load_path)&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt; end&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt; def extend_environment&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;   Rails::Initializer.class_eval do&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;     old_load = instance_method(:load_environment)&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;     define_method(:load_environment) do&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;       Bundler.require :default, Rails.env&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;       old_load.bind(self).call&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;     end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;   end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt; end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;Rails.boot!&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;All that's left now is a little cleaning up.  The &lt;code&gt;.bundle&lt;/code&gt; folder should never be checked into the code repository as it holds machine-local configuration, so it's added to &lt;code&gt;.gitignore&lt;/code&gt;.  Finally, &lt;code&gt;bundle install&lt;/code&gt; is run to fetch the bundled gems.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;append_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/.gitignore&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;/.bundle&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;bundle install&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And that's it.  I hope you find it useful.&lt;/p&gt;
</content>
   <updated>2010-02-28T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="gem" label="gem" />
   <category scheme="http://tomafro.net/tags/" term="bundler" label="bundler" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2010/02/rails-3-direct-column-reader"/>
   <title>Rails 3 direct column reader</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;Whilst trying to get my head around &lt;a href=&quot;http://github.com/brynary/arel&quot;&gt;arel&lt;/a&gt; and it's relationship to ActiveRecord in rails 3, I've updated the simple ColumnReader class I &lt;a href=&quot;http://tomafro.net/2009/05/read-active-record-columns-directly-from-the-class&quot;&gt;introduced last year&lt;/a&gt;.  It lets you read the (correctly cast) column values for an ActiveRecord class, without the overhead of instantiating each object.&lt;/p&gt;

&lt;p&gt;Here's the updated code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ColumnReader&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;column_reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pluralize&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;columns_hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module_eval&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;      def self.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;        query = scoped.arel.project(arel_table[:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;        connection.select_all(query.to_sql).collect do |value| &lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;          v = value.values.first&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_cast_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;        end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;      end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    }&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The code isn't that different, though using &lt;code&gt;scoped&lt;/code&gt; over &lt;code&gt;construct_finder_sql&lt;/code&gt; feels a lot nicer.  If you've got suggestions for improvement &lt;a href=&quot;http://gist.github.com/301420&quot;&gt;gist away&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Usage is similar to before, only using the new rails 3 syntax:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;column_reader&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;column_reader&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;  
 
  &lt;span class=&quot;n&quot;&gt;named_scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dangerous&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:conditions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:carnivorous&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&amp;#39;Lion&amp;#39;, &amp;#39;Tiger&amp;#39;, &amp;#39;Zebra&amp;#39;, &amp;#39;Gazelle&amp;#39;]&lt;/span&gt;
 
&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&amp;#39;Lion&amp;#39;] (Normal finder options supported)&lt;/span&gt;
 
&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dangerous&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&amp;#39;Lion&amp;#39;, &amp;#39;Tiger&amp;#39;] (Scoping respected)&lt;/span&gt;
 
&lt;span class=&quot;no&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ids&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [1, 2, 3] (Values cast correctly)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I'm still not entirely convinced of the value of this helper, so if you find a good use &lt;a href=&quot;http://twitter.com/tomafro&quot;&gt;tweet me&lt;/a&gt;.  Enjoy!&lt;/p&gt;
</content>
   <updated>2010-02-11T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="rails3" label="rails3" />
   <category scheme="http://tomafro.net/tags/" term="active-record" label="active-record" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2010/01/how-to-use-rails3-gems-now"/>
   <title>How to easily use Rails 3 now</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;div class=&quot;update&quot;&gt;
&lt;h3&gt;Update 10th February 2010:&lt;/h3&gt;
The instructions below were useful earlier in the development cycle.  Now the &lt;a href=&quot;http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release&quot;&gt;beta gem has been released&lt;/a&gt;, the process is much easier:


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;gem uninstall bundler
gem install tzinfo builder memcache-client rack rack-test rack-mount 
gem install erubis mail text-format thor bundler i18n
gem install rails --pre
&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Now that rails 3 is getting closer to release, I wanted to start playing around with it.  I've seen a few articles on getting it up and running, but they all seemed a little bit complicated.  To use rails 2.3.5 before its release, I just built the gems myself and installed them.  It turns out you can easily do the same with rails 3.&lt;/p&gt;

&lt;p&gt;First, install rails main dependencies:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;gem install rake rack bundler
gem install arel --version 0.2.pre
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Next, get the latest rails code from github, and install the rails gems.  There may be a few errors you can safely ignore:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;git clone git://github.com/rails/rails.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rails
rake install
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And bang, you can start your first rails 3 project:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;rails ~/apps/playground/rails3 
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Your existing projects shouldn't be affected as rails is installed as a prerelease gem, but to be safe I'd recommend a tool like &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;rvm&lt;/a&gt; to switch to a clean set of gems.&lt;/p&gt;
</content>
   <updated>2010-01-24T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="rails3" label="rails3" />
   <category scheme="http://tomafro.net/tags/" term="gems" label="gems" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2010/01/tip-relative-paths-with-file-expand-path"/>
   <title>Tip: Relative paths with File.expand_path</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;You probably know about the &lt;code&gt;__FILE__&lt;/code&gt; magic constant.  It holds the filename of the currently executing ruby source file, relative to the execution directory.  So with the following saved as &lt;code&gt;/code/examples/path_example.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Running this file from the &lt;code&gt;/code&lt;/code&gt; folder will output &lt;code&gt;examples/path_example.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is often used to load files on paths relative to the current file.  The way I've used it before is like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;config_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;config.yml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This works, but it's a bit clunky.&lt;br/&gt;
&lt;/p&gt;

&lt;p&gt;What I didn't realise until reading the rails source code the other day, is that &lt;code&gt;File.expand_path&lt;/code&gt; can take a second argument - a starting directory.  Also, this argument doesn't actually have to be a path to a directory, it also accepts a path to a file.  With this knowledge we can shorten the above to the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;config_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;../config.yml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Much simpler.&lt;/p&gt;
</content>
   <updated>2010-01-23T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="tip" label="tip" />
   <category scheme="http://tomafro.net/tags/" term="tiny" label="tiny" />
   <category scheme="http://tomafro.net/tags/" term="file" label="file" />
   <category scheme="http://tomafro.net/tags/" term="expand-path" label="expand-path" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/11/taking-screenshots-of-web-pages-with-macruby"/>
   <title>Taking screenshots of web pages with macruby</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;Whilst playing around with the very exciting &lt;a href=&quot;http://macruby.org&quot;&gt;macruby&lt;/a&gt; last weekend, I thought I'd try building a web page screenshot grabber, based on &lt;a href=&quot;http://www.bencurtis.com/?p=128&quot;&gt;Ben Curtis' code&lt;/a&gt;.  The code was very easy to change translate from &lt;code&gt;rubycocoa&lt;/code&gt;, looks cleaner and seems to work really well:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Cocoa&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;WebKit&amp;#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Snapper&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:window&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;initialize_view&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFrameLoadDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Tell the webView what URL to load.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mainFrame&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NSURLRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestWithURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URLWithString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loadRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isLoading&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timed_out?&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;NSRunLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentRunLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runUntilDate&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NSDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@failedLoading&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Failed to load page at: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mainFrame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frameView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;documentView&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setContentSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setNeedsDisplay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayIfNeeded&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lockFocus&lt;/span&gt;
    
      &lt;span class=&quot;n&quot;&gt;bitmap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NSBitmapImageRep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithFocusedViewRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;docView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlockFocus&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Write the bitmap to a file as a PNG&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;representation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bitmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;representationUsingType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NSPNGFileType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;representation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writeToFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;atomically&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;bitmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;webView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;didFailLoadWithError&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forFrame&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@failedLoading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;webView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;didFailProvisionalLoadWithError&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forFrame&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@failedLoading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize_view&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;NSApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sharedApplication&lt;/span&gt;    
    
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;WebView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NSWindow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithContentRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;styleMask&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:NSBorderlessWindowMask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backing&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:NSBackingStoreBuffered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      
    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setContentView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    
    &lt;span class=&quot;c1&quot;&gt;# Use the screen stylesheet, rather than the print one.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setMediaStyle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;screen&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Set the user agent to Safari, to ensure we get back the exactly the same content as &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# if we browsed directly to the page&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setCustomUserAgent&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us)&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Make sure we don&amp;#39;t save any of the prefs that we change.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preferences&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAutosaves&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Set some useful options.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preferences&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setShouldPrintBackgrounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preferences&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setJavaScriptCanOpenWindowsAutomatically&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preferences&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAllowsAnimatedImages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Make sure we don&amp;#39;t get a scroll bar.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mainFrame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frameView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAllowsScrolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;timed_out?&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To use:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;macruby&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Snapper.new.save(&amp;#39;http://tomafro.net&amp;#39;, &amp;#39;tomafro.net.png&amp;#39;)&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The next step is to add some command line options, then try compilation and deployment with &lt;code&gt;macrubyc&lt;/code&gt; and &lt;code&gt;macruby_deploy&lt;/code&gt;&lt;/p&gt;
</content>
   <updated>2009-11-30T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="macruby" label="macruby" />
   <category scheme="http://tomafro.net/tags/" term="screenshots" label="screenshots" />
   <category scheme="http://tomafro.net/tags/" term="web" label="web" />
   <category scheme="http://tomafro.net/tags/" term="osx" label="osx" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/11/zoom-keyboard-shortcut-for-os-x"/>
   <title>Tip: Zoom keyboard shortcut for OS X</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;In the Terminal run:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;defaults write NSGlobalDomain NSUserKeyEquivalents &lt;span class=&quot;s1&quot;&gt;&amp;#39;{&amp;quot;Zoom&amp;quot; = &amp;quot;@^Z&amp;quot;; &amp;quot;Zoom Window&amp;quot; = &amp;quot;@^Z&amp;quot;; }&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Quit and relaunch your applications, and &lt;span class='osx-shortcut'&gt;⌃⌘Z&lt;/span&gt; should zoom and unzoom.&lt;/p&gt;

&lt;p&gt;Stolen from &lt;a href=&quot;http://www.macosxhints.com/article.php?story=20051227001809626&quot;&gt;macoshints.com&lt;/a&gt;, posted here for my own benefit.&lt;/p&gt;
</content>
   <updated>2009-11-06T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="tip" label="tip" />
   <category scheme="http://tomafro.net/tags/" term="osx" label="osx" />
   <category scheme="http://tomafro.net/tags/" term="keyboard" label="keyboard" />
   <category scheme="http://tomafro.net/tags/" term="shortcut" label="shortcut" />
   <category scheme="http://tomafro.net/tags/" term="zoom" label="zoom" />
   <category scheme="http://tomafro.net/tags/" term="tiny" label="tiny" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/11/building-gems-from-a-rails-branch"/>
   <title>Building rails gems from the 2-3-stable branch</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;For the latest application I've been working on, I wanted to use &lt;a href=&quot;http://github.com/NZKoz/rails_xss/&quot;&gt;Michael Koziarski's rails_xss plugin&lt;/a&gt;, to turn default escaping on in my erb templates.  I'm also using &lt;a href=&quot;http://github.com/wycats/bundler/&quot;&gt;wycats gem bundler&lt;/a&gt; to manage gems and their dependencies, including rails.&lt;/p&gt;

&lt;p&gt;This posed a problem: xss_rails requires changes made in rails 2-3-stable branch, but not yet released in a gem (though they will be included in 2.3.5).&lt;/p&gt;

&lt;p&gt;The solution was obvious: build my own gems, and get bundler to use them.  Luckily, rails makes this an easy process.&lt;/p&gt;

&lt;p&gt;First, clone rails from github, and change to the 2-3-stable branch:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;git clone git://github.com/rails/rails.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rails
git co -b 2-3-stable origin/2-3-stable
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Next, we need to build the gems.  Rails currently doesn't seem to have a Raketask to build all its constituent projects (though I'm planning a patch to include one), so you have to build each one in turn:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;actionmailer
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../actionpack
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../activerecord
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../activeresource
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../activesupport
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../railties
rake gem &lt;span class=&quot;nv&quot;&gt;PKG_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The key is the &lt;code&gt;PKG_BUILD&lt;/code&gt; variable.  It appends a suffix to the rails version, so rather than building 2.3.4 (the version I checked out), it will build 2.3.4.1.  If I decided to update my gems, I'd use PKG_BUILD=2, then 3 and so on.&lt;/p&gt;

&lt;p&gt;Finally, once all these gems are built, it's simply a case of finding them and using them.  For gem bundler, this means placing them in the cache and updating the Gemfile to look for rails '2.3.4.1'.  The gems are all built in pkg folders in their respective subprojects, so to copy them all somewhere else you can run:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;cp **/pkg/*.gem &amp;lt;project-folder&amp;gt;/gems/cache
&lt;/pre&gt;
&lt;/div&gt;



</content>
   <updated>2009-11-05T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="gem" label="gem" />
   <category scheme="http://tomafro.net/tags/" term="bundler" label="bundler" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/11/a-rails-template-for-gem-bundler"/>
   <title>A rails template for gem bundler</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;div class=&quot;update&quot;&gt;
&lt;h3&gt;Update 28th February 2010:&lt;/h3&gt;
Bundler has changed a lot since I first wrote this template, so I've &lt;a href=&quot;/2010/02/updated-rails-template-for-gem-bundler&quot;&gt;written a new version&lt;/a&gt;.  Please use the updated version rather than the one below.
&lt;/div&gt;


&lt;p&gt;Following Nick Quaranto's article &lt;a href=&quot;http://litanyagainstfear.com/blog/2009/10/14/gem-bundler-is-the-future/&quot;&gt;'Gem Bundler is the Future'&lt;/a&gt;, I was inspired to try out &lt;a href=&quot;http://github.com/wycats/bundler&quot;&gt;bundler&lt;/a&gt; on my latest rails project.  Previously, I've found rails' own gem management a massive headache.  In contrast, using bundler has been a pleasure.&lt;/p&gt;

&lt;p&gt;Getting it set up how I wanted took a fair bit of experimentation, so to make things easier both for me and the wider community, I've  made a rails template to do the hard work.&lt;/p&gt;

&lt;p&gt;Give it a try by running the following. You should be up and running in a couple of minutes:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;rails -m http://github.com/tomafro/dotfiles/raw/master/resources/rails/bundler.rb &amp;lt;project&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;That will give you a bundled project, ready for you to add your own gems.  Here's what each step of the template actually does:&lt;/p&gt;

&lt;p&gt;Gem bundler is itself a gem.  It can't be used to manage itself, so to ensure that all environments use the same version, the first step is to install it right into the project:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;inside&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;gems/bundler&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;  
  &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;git init&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;git pull --depth 1 git://github.com/wycats/bundler.git&amp;#39;&lt;/span&gt; 
  &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rm -rf .git .gitignore&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Just having bundler installed is no good without any way to run it; a script is needed.  Once this is installed the local bundler can be run with &lt;code&gt;script/bundle &amp;lt;options&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;script/bundle&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;path = File.expand_path(File.join(File.dirname(__FILE__), &amp;quot;..&amp;quot;, &amp;quot;gems/bundler/lib&amp;quot;))&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;$LOAD_PATH.unshift path&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require &amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require &amp;#39;rubygems/command&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require &amp;#39;bundler&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require &amp;#39;bundler/commands/bundle_command&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;Gem::Commands::BundleCommand.new.invoke(*ARGV)&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;chmod +x script/bundle&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Bundler uses Gemfiles to declare which gems are required in each environment.  This simple &lt;code&gt;Gemfile&lt;/code&gt; includes rails in all environments, and ruby-debug in all environments other than production:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Gemfile&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;clear_sources&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;source &amp;#39;http://gemcutter.org&amp;#39;&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;disable_system_gems&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;bundle_path &amp;#39;gems&amp;#39;&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;gem &amp;#39;rails&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;gem &amp;#39;ruby-debug&amp;#39;, :except =&amp;gt; &amp;#39;production&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Most of the files bundler will place in the &lt;code&gt;gem&lt;/code&gt; path can be regenerated; they shouldn't be added to the project repository.  The only things that should be added are the &lt;code&gt;.gem&lt;/code&gt; files themselves, and the local copy of bundler.  All the rest should be ignored:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;append_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;.gitignore&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;gems/*&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;!gems/cache&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;!gems/bundler}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The bundle script needs to be run for the first time:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;script/bundle&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally rails needs to be modified to ensure the bundler environment is loaded.  This is done it two parts.  First, a preinitializer is added to load the bundler's environment file before anything else:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;append_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/config/preinitializer.rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require File.expand_path(File.join(File.dirname(__FILE__), &amp;quot;..&amp;quot;, &amp;quot;gems&amp;quot;, &amp;quot;environment&amp;quot;))&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Second, rails initialization process is hijacked to require the correct bundler environment:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;gsub_file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;config/environment.rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;require File.join(File.dirname(__FILE__), &amp;#39;boot&amp;#39;)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%{&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;require File.join(File.dirname(__FILE__), &amp;#39;boot&amp;#39;)&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;# Hijack rails initializer to load the bundler gem environment before loading the rails environment.&lt;/span&gt;

&lt;span class=&quot;sx&quot;&gt;Rails::Initializer.module_eval do&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  alias load_environment_without_bundler load_environment&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  &lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  def load_environment&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    Bundler.require_env configuration.environment&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    load_environment_without_bundler&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And that's it.  The project is now fully bundled.  More gems can be added to the &lt;code&gt;Gemfile&lt;/code&gt; and pulled into the project with &lt;code&gt;script/bundle&lt;/code&gt;.&lt;/p&gt;
</content>
   <updated>2009-11-03T00:00:00+00:00</updated>
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="gem" label="gem" />
   <category scheme="http://tomafro.net/tags/" term="bundler" label="bundler" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/10/tip-cdpath-am-i-the-last-to-know"/>
   <title>Tip: cdpath - Am I the last to know?</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;This one is just so simple, I can't believe I didn't know about it earlier.&lt;/p&gt;

&lt;p&gt;First, setup the cdpath or CDPATH variable:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;cdpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;~ ~/Projects/apps ~/Projects/tools ~/Projects/plugins ~/Projects/sites&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, changing directory in the shell becomes a whole world easier:&lt;/p&gt;

&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class=&quot;s1&quot;&gt;tomw@fellini:~&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;super-secret-app
~/Projects/apps/super-secret-app
&lt;span class=&quot;s1&quot;&gt;tomw@fellini:~/Projects/apps/super-secret-app&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;Documents
~/Documents
&lt;span class=&quot;s1&quot;&gt;tomw@fellini:~/Documents&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;tomafro.net
~/Projects/sites/tomafro.net
&lt;span class=&quot;s1&quot;&gt;tomw@fellini:~/Projects/sites/tomafro.net &lt;span class='err'&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've already added this to &lt;a href=&quot;http://github.com/tomafro/dotfiles&quot;&gt;my dotfiles&lt;/a&gt;.&lt;/p&gt;
</content>
   <updated>2009-10-06T00:00:00+01:00</updated>
   <category scheme="http://tomafro.net/tags/" term="tiny" label="tiny" />
   <category scheme="http://tomafro.net/tags/" term="tip" label="tip" />
   <category scheme="http://tomafro.net/tags/" term="zsh" label="zsh" />
   <category scheme="http://tomafro.net/tags/" term="terminal" label="terminal" />
   <category scheme="http://tomafro.net/tags/" term="cdpath" label="cdpath" />
 </entry>
 
 <entry>
   <id>http://tomafro.net</id>
   <link href="http://tomafro.net/2009/09/tip-the-case-for-from-param"/>
   <title>Tip: The case for from_param</title>
   <author>
     <name>Tom Ward</name>
     <email>tom@popdog.net</email>
   </author>
   <content type="html">&lt;p&gt;There's one small method I add to every new rails project I work on:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Tomafro::FromParam&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:conditions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;primary_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Tomafro&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FromParam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In my controllers, where you might use &lt;code&gt;Model.find(params[:id])&lt;/code&gt; or &lt;code&gt;Model.find_by_id(params[:id)&lt;/code&gt;, I use &lt;code&gt;Model.from_param(params[:id])&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;All three methods have almost the same behaviour, the only difference being the handling of missing records.  &lt;code&gt;find&lt;/code&gt; throws a RecordNotFound, while &lt;code&gt;find_by_id&lt;/code&gt; and &lt;code&gt;from_param&lt;/code&gt; return nil.  So why use &lt;code&gt;from_param&lt;/code&gt; over the others?&lt;/p&gt;

&lt;p&gt;The answer comes when you want to change &lt;code&gt;to_param&lt;/code&gt;, the method rails uses to turn a record into a parameter.  It's a good principal (though often broken) not to expose database ids in urls.  An example might be to use a users nickname rather than their id in user urls, so &lt;code&gt;/users/12452&lt;/code&gt; becomes &lt;code&gt;/users/tomafro&lt;/code&gt;.  In rails this is easy to achieve, by overriding the &lt;code&gt;to_param&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_param&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nickname&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Rails will automatically use this method when generating routes, so &lt;code&gt;users_path(@user)&lt;/code&gt; will return &lt;code&gt;/users/tomafro&lt;/code&gt; as we'd like.  If I was using &lt;code&gt;find&lt;/code&gt; or &lt;code&gt;find_by_id&lt;/code&gt; in my controllers, I'd then have to go through each one and change it to &lt;code&gt;find_by_nickname&lt;/code&gt;.  Luckily though, I've used &lt;code&gt;from_param&lt;/code&gt;, so whenever I override &lt;code&gt;to_param&lt;/code&gt; I just have to remember to provide an equivalent implementation for &lt;code&gt;from_param&lt;/code&gt;, and my controllers will work without modification:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:conditions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:nickname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_param&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nickname&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've been doing this for years, but it's hardly a new principle, to provide a &lt;code&gt;from&lt;/code&gt; method for every &lt;code&gt;to&lt;/code&gt; method.  There's &lt;a href=&quot;http://dev.rubyonrails.org/ticket/11505&quot;&gt;even an old ticket on trac&lt;/a&gt; asking for it, but it's been considered too trivial to add.&lt;br/&gt;
&lt;/p&gt;

&lt;p&gt;I disagree - for me the value comes from having the method from the start, not when you need it.  Luckily it's easy to add to my own projects.&lt;/p&gt;
</content>
   <updated>2009-09-23T00:00:00+01:00</updated>
   <category scheme="http://tomafro.net/tags/" term="tip" label="tip" />
   <category scheme="http://tomafro.net/tags/" term="ruby" label="ruby" />
   <category scheme="http://tomafro.net/tags/" term="rails" label="rails" />
   <category scheme="http://tomafro.net/tags/" term="active-record" label="active-record" />
   <category scheme="http://tomafro.net/tags/" term="from-param" label="from-param" />
 </entry>
 
</feed>