<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description></description>
    <link></link>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Power Moves: SQL Server on Linux, Rails, and Docker</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/content/power-moves/masthead.jpg&quot; class=&quot;ms-Img ms-Img--full ms-Img--fancy&quot; alt=&quot;The Ultimate Teen Titans Power Move.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Microsoft is releasing new versions of SQL Server on Linux more and more frequently. Last month brought us &lt;a href=&quot;https://blogs.technet.microsoft.com/dataplatforminsider/2017/04/19/sql-server-2017-community-technology-preview-2-0-now-available/&quot;&gt;SQL Server 2017 Community Technology Preview 2.0&lt;/a&gt; and like the others before, it&amp;#39;s a breeze to use with &lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Around the same time, &lt;a href=&quot;http://weblog.rubyonrails.org/2017/4/27/Rails-5-1-final/&quot;&gt;Rails 5.1&lt;/a&gt; was released. Writing modern web applications using every technology from the backend database to frontend JavaScript has never been more enjoyable. Rails 5.1 also raises intergration with SQL Server to an all-time record high.&lt;/p&gt;

&lt;p&gt;Now... today... this very moment... it is time to get merge-obsessed and combine our developer super powers to form some sweet new &lt;a href=&quot;http://teen-titans-go.wikia.com/wiki/Power_Moves&quot;&gt;Power Moves&lt;/a&gt;. &lt;code&gt;GO!&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;your-environment&quot;&gt;Your Environment&lt;/h2&gt;

&lt;p&gt;Before moving on, we should pick a secure password for our local SQL Server administrator. The &lt;code&gt;SA_PASSWORD&lt;/code&gt; variable is used both by Rails and SQL Server on Docker. I recommend setting this in your Bash, ZSH or whatever config your shell uses.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SA_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;mysecretpassword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;install-docker&quot;&gt;Install Docker&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/power-moves/docker-memory-prefs.jpg&quot; class=&quot;ms-Img ms-Img--third ms-Img--half--sm&quot; alt=&quot;Docker Memory Resource Preferences&quot; /&gt;If you do not have it already, please download and install Docker. They offer a &lt;a href=&quot;https://www.docker.com/community-edition&quot;&gt;free Community Edition&lt;/a&gt; for most platforms. Once you have downloaded and verified your install, please update your Docker resource preferences to allow up to 4GB of memory. SQL Server will need a bit more than the 2GB default.&lt;/p&gt;

&lt;h2 id=&quot;install-sql-server&quot;&gt;Install SQL Server&lt;/h2&gt;

&lt;p&gt;This command will download the latest SQL Server image from Microsoft&amp;#39;s official hub on Docker, currently SQL Server 2017 CTP v2.0.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;docker pull microsoft/mssql-server-linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, start SQL Server using the previous environment settings. The first command will create a persistent data volume while the second starts SQL Server via Docker and attaches that volume to the container. All new databases will persist to the &lt;code&gt;mssqldata&lt;/code&gt; volume.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;docker create &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -v /var/opt/mssql &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  --name mssqldata microsoft/mssql-server-linux

&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;docker run -p 1433:1433 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -e &lt;span class=&quot;s2&quot;&gt;&quot;ACCEPT_EULA=Y&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -e &lt;span class=&quot;s2&quot;&gt;&quot;SA_PASSWORD=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SA_PASSWORD&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -d --volumes-from mssqldata &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  microsoft/mssql-server-linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;create-a-rails-application&quot;&gt;Create a Rails Application&lt;/h2&gt;

&lt;p&gt;This guide does not cover Ruby installation. Rails requires Ruby v2.2.2 or higher and if you are new to Ruby or do need to install the latest version, I recommend &lt;a href=&quot;https://github.com/rbenv&quot;&gt;rbenv&lt;/a&gt; for POSIX systems or &lt;a href=&quot;https://rubyinstaller.org&quot;&gt;RubyInstaller&lt;/a&gt; if you are on Windows.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s install the latest version of Rails and Bundler using RubyGems.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;gem install rails bundler
Successfully installed rails-5.1.1
Successfully installed bundler-1.15.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To create your new Rails application with SQL Server as the database, we pass the &lt;code&gt;-d&lt;/code&gt; flag with a value of &lt;code&gt;sqlserver&lt;/code&gt;. This will install the SQL Server Adapter and TinyTDS dependencies – the Ruby bindings to DBLIB. Finally, we test that we can boot our new Rails application and load it in a browser. If all goes well, you should see the following image.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rails new my_app -d sqlserver
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my_app
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./bin/rails server

&lt;span class=&quot;gp&quot;&gt;=&amp;gt; &lt;/span&gt;Booting Puma
&lt;span class=&quot;gp&quot;&gt;=&amp;gt; &lt;/span&gt;Rails 5.1.1 application starting &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;development on http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/assets/content/power-moves/welcome-to-rails.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; alt=&quot;Yay! You&#39;re on Rails! Welcome Screen&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;ultimate-power-move&quot;&gt;Ultimate Power Move&lt;/h2&gt;

&lt;p&gt;A static welcome page is fine and all, but let&amp;#39;s see if we can make sure our SQL Server database works with ActiveRecord.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./bin/rails db:setup

Created database &lt;span class=&quot;s1&quot;&gt;&#39;my_app_development&#39;&lt;/span&gt;
Created database &lt;span class=&quot;s1&quot;&gt;&#39;my_app_test&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success! The &lt;code&gt;db:setup&lt;/code&gt; command has shown us that it has created two databases for us and that everything is bootstraped to SQL Server correctly. We can create a model/table now via a migration.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./bin/rails generate model User name:string email:string
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./bin/rails db:migrate

&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; CreateUsers: migrating &lt;span class=&quot;o&quot;&gt;======================================&lt;/span&gt;
-- create_table&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:users&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   -&amp;gt; 0.0024s
   -&amp;gt; -1 rows
&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; CreateUsers: migrated &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.0025s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=============================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success again! Here we crated a User model/table with a few attributes. Running the migration creates the table and columns as needed and we can even fire up a console to test it all out.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./bin/rails console

&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;User.count
  SQL &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.9ms&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  USE &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;my_app_development]
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2.1ms&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  SELECT COUNT&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; FROM &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;users]
&lt;span class=&quot;gp&quot;&gt;=&amp;gt; &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks!&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/power-moves/thanks.jpg&quot; class=&quot;ms-Img ms-Img--fancy ms-Img--third ms-Img--half--sm&quot; alt=&quot;The MetaSkills Power Move&quot; /&gt;There are a lot of good people working hard every day to make your experience with Ruby &amp;amp; SQL Server amazing. From engineers at Microsoft all the way to individual contributors on the Rails SQL Server repos.&lt;/p&gt;

&lt;p&gt;In the coming weeks, we hope to do so much more. What might be next? Maybe better integration to JRuby within the adapter. Maybe native cross-platform tools to script large databases when the Rails DSL can not represent that schema. All of this is in the works.&lt;/p&gt;

&lt;p&gt;I am very proud to be a part of this community and hope you find time to stop by and help, or drop a friendly note/issue about your experiences with Ruby &amp;amp; SQL Server. Lastly, thanks to CustomInk for supporting our passion projects and individual causes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://weblog.rubyonrails.org/2017/4/27/Rails-5-1-final/&quot;&gt;Rails 5.1 Release Post: Loving JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://technology.customink.com/blog/2015/10/19/microsofts-first-open-source-datacamp/&quot;&gt;Microsoft&amp;#39;s Open Source Kickoff w/Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rails-sqlserver&quot;&gt;Rails &amp;amp; SQL Server on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/599&quot;&gt;Exploring JDBC Adapter Connection Mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 06 Jun 2017 00:00:00 -0400</pubDate>
        <link>/2017/06/06/power-moves-rails-docker-and-sql-server-on-linux/</link>
        <guid isPermaLink="true">/2017/06/06/power-moves-rails-docker-and-sql-server-on-linux/</guid>
      </item>
    
      <item>
        <title>Types of Pain</title>
        <description>&lt;p&gt;Just sharing some pains for the first commit(s) to the SQL Server Rails v5 support effort. These are very raw findings I captured while working. The idea is to share the pains/gains in making a 3rd party adapter for Rails 5. Goals include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have fun with ActiveRecord v5.&lt;/li&gt;
&lt;li&gt;Learn where things are hard for us because we may be doing it wrong!&lt;/li&gt;
&lt;li&gt;Learn where things are hard for 3rd party adapters in general.&lt;/li&gt;
&lt;li&gt;Make contributions to Rails when it makes sense.&lt;/li&gt;
&lt;li&gt;Share how the SQL Server adapter is different.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The title of this post is for humor only. The internals of Rails&amp;#39; ActiveRecord have moved forward with leaps and bounds. The ones most interesting for me &amp;amp; the adapter are the new type system. I wrote a little about Sean Griffin&amp;#39;s excellent work in a post called &lt;a href=&quot;http://technology.customink.com/blog/2015/01/06/activerecord-42s-type-casting/&quot;&gt;ActiveRecord 4.2&amp;#39;s Type Casting&lt;/a&gt; last year. This year, I was totally expecting Sean to deliver on his promises to decouple types and quoting to help make ActiveRecord better.&lt;/p&gt;

&lt;h2 id=&quot;forward-our-prepared-statement-methodology&quot;&gt;Forward: Our Prepared Statement Methodology&lt;/h2&gt;

&lt;p&gt;Is completely different than most other adapters whereby we use the &lt;code&gt;sp_executesql&lt;/code&gt; stored procedure to cache frequently used query plans at the database itself. See this &lt;a href=&quot;https://blog.engineyard.com/2011/sql-server-10xs-faster-with-rails-3-1&quot;&gt;2011 Engine Yard Blog&lt;/a&gt; which talks about this methodology.&lt;/p&gt;

&lt;h2 id=&quot;schema-reflection&quot;&gt;Schema Reflection&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;SchemaStatements#columns&lt;/code&gt; is the first thing that usually breaks when we upgrade for major Rails releases. Like many other low level adapter parts, when it breaks... NOTHING works till you get it fixed. I had a particularly fun time with the changes needed this time around.&lt;/p&gt;

&lt;p&gt;Our lowest level method to look up all things schema related is our &lt;code&gt;column_definitions&lt;/code&gt; method. The SQL here is responsible for joining many info schema tables to give us everything we need to know for the current database as well as other schemas. Even though there are caches in ActiveRecord just for schema reflection, we found this SQL has to be fast. Hence we create our own binds to leverage &lt;code&gt;sp_executesql&lt;/code&gt;&amp;#39;s statement cache abilities.&lt;/p&gt;

&lt;p&gt;Previously we created binds by making a new column object using the &lt;code&gt;INFORMATION_SCHEMA.COLUMNS.TABLE_NAME&lt;/code&gt; of type &lt;code&gt;nvarchar(128)&lt;/code&gt; with whatever table name value requested by ActiveRecord. Optionally we did the same with the &lt;code&gt;TABLE_SCHEMA&lt;/code&gt; if a table name identifier was fully qualified. This kept our DB reflection fast. However, binds no longer contain column information. This is what I found in the &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; class where binds and substitutions are made:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;QueryAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel_attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;type_for_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arel_attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In some ActiveRecord tests, we see the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;Relation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;QueryAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;type_for_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It was now apparent to me how ActiveRecord broke columns out of the type/cast/quote layer by using columns further up the stack. The &lt;code&gt;Relation::QueryAttribute&lt;/code&gt; is actually a subclass of &lt;code&gt;ActiveRecord::Attribute&lt;/code&gt;. My solution to fix schema reflection was to manually create some query attributes for our binds.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;nv128&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SQLServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UnicodeVarchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;limit: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;binds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Relation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;QueryAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TABLE_NAME&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nv128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;binds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Relation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;QueryAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TABLE_SCHEMA&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nv128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blank?&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sp_executesql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;SCHEMA&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we were able to reflect on the database again. However, because we need to know the SQL Server data type for our binds to work with &lt;code&gt;sp_executesql&lt;/code&gt;, we have extended our types to respond to a &lt;code&gt;sqlserver_type&lt;/code&gt; similar to the simplified type. This way, we can ask our binds for &lt;code&gt;type.sqlserver_type&lt;/code&gt; and get the tidy type arguments needed for &lt;code&gt;sp_executesql&lt;/code&gt;. That was a lot of type&amp;#39;in 😀&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveRecord&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ConnectionAdapters&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SQLServer&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Type&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Sql&lt;/span&gt;

          &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sqlserver_type&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&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;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ActiveModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SQLServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sql&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;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;updating-our-types&quot;&gt;Updating Our Types&lt;/h2&gt;

&lt;p&gt;This is where things get hard for us. Unlike other databases, quoting a Ruby type for the database is often dependent on the SQL Server data type of a specific column. For example, a string might be easy for MySQL. But for SQL Server, only non-national (single byte) strings/types can be quoted with single quotes. For multi-byte strings of database type &lt;code&gt;nchar&lt;/code&gt;, &lt;code&gt;nvarchar&lt;/code&gt;, &lt;code&gt;ntext&lt;/code&gt;, and &lt;code&gt;nvarchar(max)&lt;/code&gt; – we have to quote using the &lt;code&gt;N&amp;#39;string&amp;#39;&lt;/code&gt; &amp;quot;national&amp;quot; prefix. Fun! More interesting are supporting our date and time types. Many of which have different fractional precision and quoting is important to each.&lt;/p&gt;

&lt;p&gt;ActiveRecord&amp;#39;s types have been moved to ActiveModel and each needs their own &lt;code&gt;serialize(value)&lt;/code&gt; implementation vs the old &lt;code&gt;type_cast_for_database(value)&lt;/code&gt; which now resides at the connection and a type caster map object. We easily updated our type objects to use the serialize method. But I have yet to dig down to see how many types I will have to couple to quoting as the project moves forward.&lt;/p&gt;

&lt;p&gt;At first glance, our column objects are getting smaller and the type objects are getting fatter.&lt;/p&gt;

&lt;h2 id=&quot;during-inserts&quot;&gt;During Inserts&lt;/h2&gt;

&lt;p&gt;Our &lt;code&gt;exec_insert&lt;/code&gt; relied on knowing two critical things. First, if a identity column is being inserted. Second, the target table name of that insert so that we enable identity inserts (table scope) for the duration of that insert statement. Since binds no longer have column information, we are going to have to start trusting the &lt;code&gt;pk&lt;/code&gt; parameter signaling that an ID has been set. We were somewhat doing this anyway in our &lt;code&gt;sql_for_insert&lt;/code&gt; method. Also, once again, we need to pick up the pattern of using regular expressions on the &lt;code&gt;sql&lt;/code&gt; value to pull the table name out. It appears the PostgreSQL adapter does this as well. It will be interesting to see if this slows us down or not.&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Jul 2016 00:00:00 -0400</pubDate>
        <link>/2016/07/14/types-of-pain/</link>
        <guid isPermaLink="true">/2016/07/14/types-of-pain/</guid>
      </item>
    
      <item>
        <title>Microsoft&#39;s First Open Source DataCamp</title>
        <description>&lt;p&gt;Rarely do the words &amp;quot;open source&amp;quot; come to mind when the Microsoft Corporation is mentioned. As the maintainer of the SQL Server stack for both Ruby &amp;amp; Rails, and a long time Apple/UNIX fan, I have been engineering solutions to make working with SQL Server as easy as possible. Often times the work has required outside in hacks to a closed &amp;amp; proprietary set of technologies. That changed last week.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/ossdatacamp/meeting.jpg&quot; class=&quot;ms-Img ms-Img--fancy&quot; alt=&quot;First day of introductions at Microsoft&#39;s OSSDataCamp&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;a href=&quot;https://twitter.com/sgrif&quot;&gt;Sean Griffin&lt;/a&gt; and I were invited to represent the Ruby/Rails community at Microsoft&amp;#39;s first &lt;a href=&quot;https://twitter.com/hashtag/OSSDataCamp&quot;&gt;#OSSDataCamp&lt;/a&gt;. The idea is simple; to open up and engage our community at an intimate level. The results so far are incredibly positive and these new relationships feel lasting and honest.&lt;/p&gt;

&lt;p&gt;This post contains interesting details if you want to learn more about &lt;a href=&quot;http://azure.microsoft.com/&quot;&gt;Microsoft&amp;#39;s Azure&lt;/a&gt; platform. We were lucky enough to be exposed to some candid inner workings of their latest service offerings which look to be a strong competitor to Amazon&amp;#39;s Web Services.&lt;/p&gt;

&lt;h2 id=&quot;we-want-to-learn-from-you&quot;&gt;We Want To Learn From You&lt;/h2&gt;

&lt;p&gt;That sentiment was echoed by everyone I met. From engineers to leadership and various product managers in-between, Microsoft is hungry to learn and this time it does not feel like the old consume &amp;amp; conquer strategies from the &lt;a href=&quot;http://ironruby.net&quot;&gt;IronRuby&lt;/a&gt; days. Instead their new culture closely reflects that of &lt;a href=&quot;http://www.customink.com/about/our_story/&quot;&gt;CustomInk&amp;#39;s&lt;/a&gt; own Inkers. Our hosts were the most upbeat and polite folks I have seen.&lt;/p&gt;

&lt;h5 id=&quot;windows-support-a-diversity-issue&quot;&gt;Windows Support - A Diversity Issue&lt;/h5&gt;

&lt;p&gt;As Sean Griffin put it, we cannot require new engineers to buy a MacBook Pro to learn Ruby. Be it a &lt;a href=&quot;http://railsgirls.com&quot;&gt;Rails Girls&lt;/a&gt; workshop or your local meetup group, a poor Windows experience can literally lose good, diverse talent in our community. Thanks to projects like RailsInstaller, and the modern replacement &lt;a href=&quot;http://rubyinstaller.org&quot;&gt;RubyInstaller&lt;/a&gt;, we are stronger than we have historically been. But we can do better.&lt;/p&gt;

&lt;p&gt;To that end, Microsoft has kindly agreed to provide key projects like Rails, TinyTDS, and the ActiveRecord SQLServerAdapter with funded continuous integration using &lt;a href=&quot;http://www.appveyor.com&quot;&gt;AppVeyor&lt;/a&gt; services. Such a small cost can greatly impact our feedback loop and identify pain points quickly.&lt;/p&gt;

&lt;h5 id=&quot;a-changing-culture&quot;&gt;A Changing Culture&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/ossdatacamp/learn-ruby.jpg&quot; class=&quot;ms-Img ms-Img--fancy ms-Img--third ms-Img--third--sm&quot; alt=&quot;Jack Yang learns Ruby in 1 day!&quot; /&gt;Change is hard on all sides. For me, getting into the mindset that Microsoft can help was a big step. When Sean found issues with &lt;a href=&quot;https://github.com/sstephenson/execjs&quot;&gt;execjs&lt;/a&gt; that led back to Windows Script Host, they introduced us to that team. Likewise, the SQL Server adapter has always needed a bullet-proof cross platform binary to dump the schema. &amp;quot;We can help and here are the engineers...&amp;quot; was the reply. Wow!&lt;/p&gt;

&lt;p&gt;Some issues sit well in Microsoft&amp;#39;s sphere to solve. What most impressed me was how eager they were to address them. Being a large company, often times the immediate answer was to schedule a series of 1-on-1s with the team(s) responsible. Connections and conversations like this quickly led to even pondering if Ruby could be installed on Windows by default. Or maybe even build cross platform SQL Server development binaries! 😱&lt;/p&gt;

&lt;h5 id=&quot;quid-pro-quo&quot;&gt;Quid Pro Quo&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/ossdatacamp/keepit-weird.jpg&quot; class=&quot;ms-Img ms-Img--fancy ms-Img--half ms-Img--half--sm&quot; alt=&quot;Sean Griffin keeps it weird while helping you not blow up.&quot; style=&quot;float:left; margin-left:0; margin-right:1rem;&quot; /&gt;So what did Microsoft learn most from us? Other than Rubyists keep it weird? Likely their biggest takeaway was that Sean Griffin loves to play the &lt;a href=&quot;http://www.keeptalkinggame.com&quot;&gt;Keep Talking and Nobody Explodes&lt;/a&gt; game. I mean he &lt;em&gt;really&lt;/em&gt; loves to play this game.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s simple, use 2-way, fast-paced, verbal communication to quickly identify and defuse a virtual ticking time bomb. As it turned out, this is a great team building exercise. Becoming a bomb defusing expert is high on my list and I can not wait to play with a group of my fellow Inkers. Thanks Sean!&lt;/p&gt;

&lt;h2 id=&quot;coming-soon-to-ruby-rails&quot;&gt;Coming Soon To Ruby/Rails&lt;/h2&gt;

&lt;p&gt;We got a lot of work done along with establishing some big milestones for those using Windows and/or SQL Server with Ruby. Here are some things you can look forward to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgrade TinyTDS to the latest FreeTDS v0.95 which supports the TDS v7.3 protocol.&lt;/li&gt;
&lt;li&gt;Making the adapter pass all tests for Rails 5 under active development.&lt;/li&gt;
&lt;li&gt;Allow TinyTDS to be statically compiled on every platform w/OpenSSL for easier Azure support.&lt;/li&gt;
&lt;li&gt;ActiveRecord JSON support via a v4.2 update. Leverages SQL 16 Box/Azure built-in JSON.&lt;/li&gt;
&lt;li&gt;Binstub wrappers for all statically compiled FreeTDS binaries.&lt;/li&gt;
&lt;li&gt;First class Azure support for Rails which includes proper DB setup and clone tasks.&lt;/li&gt;
&lt;li&gt;Allow the rails-sqlserver adapter to use an alternate jTDS connection mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These items are tracked in the &lt;a href=&quot;https://github.com/rails-sqlserver/tiny_tds/milestones&quot;&gt;TinyTDS&lt;/a&gt; and/or the &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/milestones&quot;&gt;SQL Server Adapter&lt;/a&gt; milestones on GitHub. Follow along or contribute if anything interests you.&lt;/p&gt;

&lt;h2 id=&quot;microsoft-azure-in-brief&quot;&gt;Microsoft Azure In Brief&lt;/h2&gt;

&lt;p&gt;Azure != SQL Server, it is much more. Think AWS (Analytics, IoT, CDN, Etc) with a &lt;a href=&quot;https://portal.azure.com&quot;&gt;better frontend portal&lt;/a&gt;. Microsoft&amp;#39;s Azure platform and PaaS offerings are amazing and accessible for anyone looking to rapidly build out their new web application suite of microservices. Seriously, you really should consider it next time you are looking for a Heroku-style marketplace. Here is a quick brief:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 out of 4 VMs are Linux.&lt;/li&gt;
&lt;li&gt;7 million requests a second.&lt;/li&gt;
&lt;li&gt;1.6 million SQL databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;command-line-amp-application-interfaces&quot;&gt;Command Line &amp;amp; Application Interfaces&lt;/h5&gt;

&lt;p&gt;Portal smortal, who wants GUIs? The real power is in the command line and automation. Just like Heroku&amp;#39;s toolbelt, Azure has cross platform binaries that are open source on GitHub. This client has rich 2FA and is packed with interfaces. Services can even be stood up with a simple JSON template hosted on GitHub. Need an application interface? They have a Ruby SDK too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Azure/azure-xplat-cli&quot;&gt;Cross Platform Command Line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Azure/azure-quickstart-templates&quot;&gt;Quickstart Templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Azure/azure-sdk-for-ruby&quot;&gt;SDK for Ruby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;services-marketplace&quot;&gt;Services Marketplace&lt;/h5&gt;

&lt;p&gt;Their marketplace and open source service offerings are seriously impressive. One that stood out is their Elasticsearch service and how well it can integrate with any data source. They literally built an entire frontend GUI that can help you build out super impressive search indexes.&lt;/p&gt;

&lt;p&gt;The message, &amp;quot;We give you 99.99% uptime, you worry about how search works, and we take care of the rest.&amp;quot; really stood out to me as a market differentiator. Maintaining shard strategies and the complexities of Elasticsearch is not what I want to do.&lt;/p&gt;

&lt;h5 id=&quot;sql-server-2016&quot;&gt;SQL Server 2016&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/ossdatacamp/sql-server-stretch.png&quot; class=&quot;ms-Img ms-Img--fancy ms-Img--third ms-Img--third--sm&quot; alt=&quot;Stretch On-Premises SQL Servers to Azure.&quot; /&gt;I can&amp;#39;t even begin to go into all the amazing features of SQL Server 2016 now available on Azure. A quick list includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-In JSON Support.&lt;/li&gt;
&lt;li&gt;Always encrypted data with transparent app/client usage.&lt;/li&gt;
&lt;li&gt;Data Lake infinite storage with built-in Revolution-R analytics.&lt;/li&gt;
&lt;li&gt;Diverse sharding and multi-tenant structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One feature that stood out was SQL Server&amp;#39;s ability to &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/dn935011.aspx&quot;&gt;stretch&lt;/a&gt; or archive historical data transparently and securely. This can be done entirely via their hosted service or coupled with your on-premises SQL Server databases. All without the application caring about managing that cold &amp;lt;=&amp;gt; hot data.&lt;/p&gt;

&lt;h2 id=&quot;many-thanks&quot;&gt;Many Thanks!&lt;/h2&gt;

&lt;p&gt;Special thanks to Microsoft as a whole. Especially to Andrea Lam and Meet Bhagdev for their personal &amp;amp; professional support during our trip. You made us feel right at home. Also in attendance for the first #OSSDataCamp were &lt;a href=&quot;https://twitter.com/manfre&quot;&gt;Michael Manfre&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/michiyata&quot;&gt;Michiya Takahashi&lt;/a&gt;, and &lt;a href=&quot;https://github.com/timgraham?tab=activity&quot;&gt;Tim Graham&lt;/a&gt;. All of whom represented the Python/Django community and helped our open source cause.&lt;/p&gt;

&lt;p&gt;This is a process and one that I hope continues with Ruby and other languages. It will succeed if Microsoft actively contributes back to open source and in some cases, champions certain projects with an earnest level of excellence.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/ossdatacamp/fetch-tobias-ternstrom.jpg&quot; class=&quot;ms-Img ms-Img--fancy ms-Img--third ms-Img--third--sm&quot; alt=&quot;Tobias Ternstrom helped make FETCH happen in SQL Server.&quot; /&gt;To the right is Tobias Ternstrom and myself. The reason I am so happy in that photo is that Tobias literally helped &lt;a href=&quot;http://style.mtv.com//wp-content/uploads/style/2014/03/so-fetch.gif&quot;&gt;make FETCH happen&lt;/a&gt; in SQL Server. Supporting a sane limit/offset model &lt;a href=&quot;http://metaskills.net/2015/01/25/activerecord-sqlserver-v4.2.0---code-name-kantishna/&quot;&gt;allowed projects&lt;/a&gt; like the ActiveRecord adapter to delete hundreds of lines of code while becoming more maintainable. Thanks so much Tobias! All ORMs everywhere love you.&lt;/p&gt;

&lt;p&gt;And lastly, I want to give a shout out to &lt;a href=&quot;https://github.com/larskanis&quot;&gt;Lars Kanis&lt;/a&gt; who has been a huge contributor over the past many months by making TinyTDS work well on Windows. Let him know it if you see his pull requests.&lt;/p&gt;
</description>
        <pubDate>Mon, 19 Oct 2015 00:00:00 -0400</pubDate>
        <link>/2015/10/19/microsofts-first-open-source-datacamp/</link>
        <guid isPermaLink="true">/2015/10/19/microsofts-first-open-source-datacamp/</guid>
      </item>
    
      <item>
        <title>Customizing Rake Tasks In Rails 4.1 And Higher</title>
        <description>&lt;p&gt;I have been overriding, invoking, and executing custom Rake tasks since I was an early Ruby developer. Tweaking your project&amp;#39;s automated tasks are likely the closest thing Rails developers come to building their own light saber. Most popular are adding or changing how the Rails test suite behaves. For example, adding Capybara to your project.&lt;/p&gt;

&lt;p&gt;Recently I have been &lt;a href=&quot;/2014/09/16/from-rails-3.2-to-4.2/&quot;&gt;upgrading projects from 3.2 to 4.2&lt;/a&gt; and one thing that really stood out to me was how Rails testing tasks are created and run. Most obvious is that the default test task now runs all model, controller, mailer, helper, job, and integration tests in a single process now. Upon investigation, I found that these major changes were introduced in Rails 4.1. Go check out their new &lt;a href=&quot;https://github.com/rails/rails/blob/4-2-stable/railties/lib/rails/test_unit/testing.rake&quot;&gt;testing.rake&lt;/a&gt; file if you are interested. Much cleaner than before!&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;So what does this mean for you? Let me describe a real scenario I had to address in one of my projects. This project uses two custom test additions. The first is called &lt;a href=&quot;https://github.com/jfirebaugh/konacha&quot;&gt;Konacha&lt;/a&gt;, a gem that leverages the asset pipeline to easily test my projects JavaScript with Mocha &amp;amp; Chai under Capybara with PhantomJS. The second addition uses the Capybara::DSL within the standard Rails &lt;code&gt;test/integration&lt;/code&gt; namespace and directory structure.&lt;/p&gt;

&lt;p&gt;When moving to Rails 4.2 I found that my integration tests were mixed together with everything else. This was a problem since I really wanted my slower integration tests to run after all my other tests. No matter what I tried, I could not get the setup I wanted. So like most problems, I solved this by diving into the code and learning.&lt;/p&gt;

&lt;h2 id=&quot;deconstructing-rails-testtask&quot;&gt;Deconstructing Rails::TestTask&lt;/h2&gt;

&lt;p&gt;So we already had a look at the new testing.rake file above. But looking closer, we can see how the default test task is defined right at the top. Also of interest to us is that &lt;code&gt;test:run&lt;/code&gt; task.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rake/testtask&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rails/test_unit/sub_test_task&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: :test&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Runs all tests in test folder&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&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;TestTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test_creator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;top_level_tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;invoke_rake_task&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;c1&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;TestTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test/**/*_test.rb&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That description for &lt;code&gt;test&lt;/code&gt; is pretty helpful and quite accurate. Indeed even though we have distinct test tasks like &lt;code&gt;test:models&lt;/code&gt; and &lt;code&gt;test:mailers&lt;/code&gt;, this default task is somehow aggregating each into a single run. To learn more about this implementation, we need to open up the &lt;a href=&quot;https://github.com/rails/rails/blob/4-2-stable/railties/lib/rails/test_unit/sub_test_task.rb&quot;&gt;sub_test_task.rb&lt;/a&gt; file required at the top.&lt;/p&gt;

&lt;p&gt;In here we can see two new utility classes. One called &lt;code&gt;TestCreator&lt;/code&gt; and another called &lt;code&gt;TestInfo&lt;/code&gt;. The &lt;code&gt;TestCreator#invoke_rake_task&lt;/code&gt; instance method is what we came here for.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;invoke_rake_task&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;any?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_and_run_single_test&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reset_application_tasks&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TEST&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:single&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;invoke&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Without knowing too much about the &lt;code&gt;@info&lt;/code&gt; object initialized by &lt;code&gt;TestCreator&lt;/code&gt;, we can make a pretty good guess that &lt;code&gt;test:run&lt;/code&gt; is what we came here to find. By looking back at the &lt;code&gt;test:run&lt;/code&gt; tasks pattern of &lt;code&gt;&amp;quot;test/**/*_test.rb&amp;quot;&lt;/code&gt; it seems clear that this is the test responsible for running all of our tests at once. Knowing that, let&amp;#39;s start adding code to the project&amp;#39;s &lt;code&gt;Rakefile&lt;/code&gt; and make our new tests tasks do our bidding.&lt;/p&gt;

&lt;h2 id=&quot;customizing-your-rakefile&quot;&gt;Customizing Your Rakefile&lt;/h2&gt;

&lt;p&gt;Here is the first cut at customizing our Rails project&amp;#39;s Rakefile. These come right after the default &lt;code&gt;Rails.application.load_tasks&lt;/code&gt; line.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test:run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;js&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;konacha:run&#39;&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;TestTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:_run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FileList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test/**/*_test.rb&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;test/integration/**/*_test.rb&#39;&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;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:run&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;s1&quot;&gt;&#39;test:js&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:_run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:integration&#39;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first thing that is happening is we want to remove the existing &lt;code&gt;test:run&lt;/code&gt; task using the &lt;code&gt;clear&lt;/code&gt; method. We then open up the test task namespace and make a few additions. In order they are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a simple &lt;code&gt;test:js&lt;/code&gt; alias for the Konacha provided &lt;code&gt;konacha:run&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create our &lt;code&gt;test:run&lt;/code&gt; replacement but now named &lt;code&gt;test:_run&lt;/code&gt;. Note how we use &lt;code&gt;test_files&lt;/code&gt; vs a &lt;code&gt;pattern&lt;/code&gt; so we can use the exclude method on FileList to remove all integration tests.&lt;/li&gt;
&lt;li&gt;Make a new &lt;code&gt;test:run&lt;/code&gt; task that calls each other task in the order we want.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you were to run &lt;code&gt;rake test&lt;/code&gt; now, we would see that our integrations are still inter-mixed with all the other Rails test cases. But why!?!&lt;/p&gt;

&lt;h2 id=&quot;final-rakefile-separating-integrations&quot;&gt;Final Rakefile Separating Integrations&lt;/h2&gt;

&lt;p&gt;So why did our integration tests still run with all the other Rails test cases? The answer lies in one simple override that &lt;code&gt;Rails::TestTask&lt;/code&gt; implements. Normally the &lt;code&gt;Rake::TestTask&lt;/code&gt; calls an instance method named &lt;code&gt;define&lt;/code&gt; which basically builds a string and executes a Ruby subprocess. The &lt;code&gt;Rails::TestTask&lt;/code&gt; class implements the define method like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;define&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TESTOPTS&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;ARGV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Shellwords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TESTOPTS&#39;&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;n&quot;&gt;libs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@libs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt;
    &lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unshift&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;libs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;fl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;FileList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expand_path&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See what is happening there? At the end of the day, all &lt;code&gt;Rails::TestTask&lt;/code&gt; tasks do is require the test files. So now it makes perfect sense as to why it appeared that each task was being merged. With this knowledge, we can now customize our setup.&lt;/p&gt;

&lt;p&gt;Rather than using Rails test task, we will just bail out and use the default &lt;code&gt;Rake::TestTask&lt;/code&gt; instead. When doing so, we will have to push the test directory to the libs too. This is one of the few things done for us by &lt;code&gt;Rails::TestTask&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test:run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test:integration&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;js&#39;&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;s1&quot;&gt;&#39;konacha:run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:_run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;libs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FileList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test/**/*_test.rb&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;test/integration/**/*_test.rb&#39;&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;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;integration&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:prepare&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;libs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test/integration/**/*_test.rb&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:run&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;s1&quot;&gt;&#39;test:js&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:_run&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test:integration&#39;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we are cooking. All of our JavaScript tests will run first, then all normal Rails test cases, and finally our integration tests. By customizing the &lt;code&gt;test:run&lt;/code&gt; task we get the full benefit of the default &lt;code&gt;test&lt;/code&gt; task implementation which allows us to pass file and/or &lt;code&gt;TESTOPTS&lt;/code&gt; arguments. This happens to be one of my favorite features of Rails 4.1 and up too.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nb&quot;&gt;test test&lt;/span&gt;/models/user_test.rb
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nb&quot;&gt;test test&lt;/span&gt;/integration/app_stories_test.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And it all just works! Thanks for reading!&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Feb 2015 00:00:00 -0500</pubDate>
        <link>/2015/02/08/customizing-rake-tasks-in-rails-41-and-higher/</link>
        <guid isPermaLink="true">/2015/02/08/customizing-rake-tasks-in-rails-41-and-higher/</guid>
      </item>
    
      <item>
        <title>ActiveRecord SQLServer v4.2.0 - Code Name Kantishna</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/content/kantishna.jpg&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; alt=&quot;&quot; /&gt;
After 4 weeks of work, the ActiveRecord SQL Server adapter is now ready for Rails v4.2.0 and in pre-release status. The list of features is impressive. But first, some bad news. Code named Kantishna, after a small community in Denali area of Alaska, the adapter is only for SQL Server 2012 and higher. This is a good thing because these versions of SQL Server have something we have needed for a very long time, simple offset and limit windowing functions.&lt;/p&gt;

&lt;h2 id=&quot;fetch-can-happen&quot;&gt;FETCH Can Happen&lt;/h2&gt;

&lt;p&gt;Sure there are hacks like &lt;code&gt;ROW_NUMBER&lt;/code&gt; and in theory these work. In reality it has caused our code to &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/4-1-stable/lib/arel/visitors/sqlserver.rb&quot;&gt;be incredibly complex&lt;/a&gt; and infected all parts of the adapter. Problems were often solved by using regular expressions and affected performance. Even worse, I think it kept people from contributing to the project. Worry not, if you are on an older version of SQL Server, please feel free to use an older version of Rails and the adapter.&lt;/p&gt;

&lt;p&gt;For the rest, FETCH can happen and that is indeed what we are using, &lt;code&gt;OFFSET&lt;/code&gt; and &lt;code&gt;FETCH&lt;/code&gt;. Here is a &lt;a href=&quot;http://dbadiaries.com/new-t-sql-features-in-sql-server-2012-offset-and-fetch&quot;&gt;great article&lt;/a&gt; that describes its basic usage. To see the benefits, &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/arel/visitors/sqlserver.rb&quot;&gt;take a quick look&lt;/a&gt; at our latest Arel visitor and note the difference.&lt;/p&gt;

&lt;h2 id=&quot;whats-new&quot;&gt;Whats New&lt;/h2&gt;

&lt;p&gt;For full details check out the &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/CHANGELOG.md&quot;&gt;latest CHANGELOG&lt;/a&gt; on our project repo. But here is a great summary. The v4.2.0 adapter is the strongest version to date!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TYPE CASTING&lt;/strong&gt;: A few weeks ago I wrote a &lt;a href=&quot;http://technology.customink.com/blog/2015/01/06/activerecord-42s-type-casting/&quot;&gt;full article on the new Type&lt;/a&gt; objects in ActiveRecord 4.2. These objects help us do a much better job of ensuring data going in and out of the DB are proper. They will play a huge role in Rails 5.0 when the API becomes public. In Rails 4.2 they help us quote values and output proper schema.rb files. We have aliased our type namespace to &lt;code&gt;ActiveRecord::Type::SQLServer&lt;/code&gt; and these objects will help us win at every datatype FreeTDS supports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OBJECT IDENTIFICATION&lt;/strong&gt;: Inspired by the PostgreSQL adapter, we now have a &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/active_record/connection_adapters/sqlserver/utils.rb&quot;&gt;plain ruby object&lt;/a&gt; which is responsible for identifying servers, databases, objects, and schemas. No more ad-hoc quoting which caused us to blow up when needing to use quoted/unquoted identifier parts at different times. Our new identifier rules should allow legacy systems to easily use &lt;code&gt;dbo.&lt;/code&gt; or other schema prefixes in table names and everything from DDL statements to our schema cache &amp;amp; column reflection will just work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NATIONAL DEFAULTS&lt;/strong&gt;: Not new, but all Rails simplified types now default to matching SQL Server &amp;quot;national&amp;quot; or Unicode types. If you need to a non-national type or other special type, we have full column extensions in place. For example, need a &lt;code&gt;char(24)&lt;/code&gt; vs a full length national varying character, just use the &lt;code&gt;t.char&lt;/code&gt; method and proper Rails options in your schema migrations.&lt;/p&gt;

&lt;h1 id=&quot;whats-coming&quot;&gt;Whats Coming&lt;/h1&gt;

&lt;p&gt;The v4.2.0 adapter is now in pre-release and we only have a few issues to track down and fix. Check out the issues in &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/milestones/4-2-stable&quot;&gt;our Github milestone&lt;/a&gt; if you are interested in helping. The biggest feature will be turning on foreign key support!&lt;/p&gt;

&lt;p&gt;But why stop there? There is so much more to help with. From &lt;a href=&quot;http://confreaks.com/videos/5081-RubyConf2014-benchmarking-ruby&quot;&gt;benchmark and performance&lt;/a&gt; tuning, to Database task support. We sure could use your help. For now, give it a try. Thanks!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;activerecord-sqlserver-adapter&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 4.2.0.pre&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 25 Jan 2015 00:00:00 -0500</pubDate>
        <link>/2015/01/25/activerecord-sqlserver-v4-2-0-code-name-kantishna/</link>
        <guid isPermaLink="true">/2015/01/25/activerecord-sqlserver-v4-2-0-code-name-kantishna/</guid>
      </item>
    
      <item>
        <title>ActiveRecord 4.2&#39;s Type Casting</title>
        <description>&lt;p&gt;Last month &lt;a href=&quot;http://weblog.rubyonrails.org/2014/12/19/Rails-4-2-final/&quot;&gt;Rails 4.2&lt;/a&gt; was released and if you have been keeping up with my posts, I even covered &lt;a href=&quot;/2014/09/16/from-rails-3.2-to-4.2/&quot;&gt;how you can upgrade&lt;/a&gt; from 3.2 to 4.2 in one step! This speaks volumes to how easy it is to adopt to outward facing API changes within our beloved framework. But often times, version changes bring implementation changes that we never see. For example, all of Aaron Patterson&amp;#39;s work for &lt;a href=&quot;http://tenderlovemaking.com/2014/02/19/adequaterecord-pro-like-activerecord.html&quot;&gt;AdequateRecord Pro&amp;trade;&lt;/a&gt; are performance optimizations that affect no outward API interface at all. Unless you read the source, many of these awesome changes go unnoticed and that&amp;#39;s a damn shame because some of them can make our lives easier.&lt;/p&gt;

&lt;p&gt;Today I want to share some of the new hotness I found while working on the latest ActiveRecord &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter&quot;&gt;SQL Server Adapter&lt;/a&gt;. Specifically, how ActiveRecord type casts values. Up until Rails 4.2, all type casting was done in class methods like &lt;code&gt;value_to_date&lt;/code&gt; implemented on the &lt;code&gt;ActiveRecord::ConnectionAdapters::Column&lt;/code&gt; object. Sean Griffin does a &lt;a href=&quot;http://robots.thoughtbot.com/how-rails-works-type-casting&quot;&gt;great job&lt;/a&gt; explaining this convoluted process. Warning, it&amp;#39;s kind of boring and a chore to read.&lt;/p&gt;

&lt;p&gt;This process has been around for as long as I can remember. It made it really hard to write good abstract OO code that casts values going into and out of the database. All that has changed with the new &lt;code&gt;ActiveRecord::Type&lt;/code&gt; namespace. All objects within this namespace are simple POROs with very obvious and well documented interfaces. The base class is &lt;code&gt;ActiveRecord::Type::Value&lt;/code&gt; and below is a slightly trimmed down version of that object, sans comments. Take a quick read.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveRecord&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Type&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Value&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;type_cast_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;type_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&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;type_cast_from_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;type_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&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;type_cast_for_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&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;type_cast_for_schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&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;changed?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_new_value_before_type_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;old_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_value&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;changed_in_place?&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;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kp&quot;&gt;false&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;type_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cast_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&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;cast_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&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;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do you see what I see? This is amazing. I see an object that finally handles all of the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Casting raw DB values.&lt;/li&gt;
&lt;li&gt;Casting user input to prepare for DB quoting.&lt;/li&gt;
&lt;li&gt;Casting for default values in schema dumpers.&lt;/li&gt;
&lt;li&gt;Avoid &lt;code&gt;ActiveRecord::ConnectionAdapters::Column&lt;/code&gt; code bloat.&lt;/li&gt;
&lt;li&gt;So much more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Case in point, a lot of database connection gems still return raw strings for every value. Sub classes of &lt;code&gt;Value&lt;/code&gt; can define their own &lt;code&gt;type_cast_from_database&lt;/code&gt; implementation to deal with this. For example, here is the &lt;code&gt;Integer&lt;/code&gt; object&amp;#39;s default behavior. Super easy!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;type_cast_from_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One thing that Rails core team did to make this even better allows us to type check our Ruby values ahead of time during attribute assignment vs. when we save to the database. This is now done in the &lt;code&gt;Integer&lt;/code&gt; class using the &lt;code&gt;limit&lt;/code&gt; attribute parsed from the SQL type. Here are the salient points of that class.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveRecord&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Type&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Value&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@range&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max_value&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;cast_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;ensure_in_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;result&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ensure_in_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cover?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RangeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is out of range for &lt;/span&gt;&lt;span class=&quot;si&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;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; with limit &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max_value&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;limit&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;o&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;c1&quot;&gt;# 8 bits per byte with one bit for sign&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;min_value&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_value&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;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Any type aliased to use the &lt;code&gt;Integer&lt;/code&gt; value object will now type check that the value is within the accepted database range. As far as I can tell, only Integer objects in Rails core do this, but I plan on implementing these checks for Decimal and other values too. Here is how SQL Server&amp;#39;s &lt;code&gt;smallint(2)&lt;/code&gt; SQL type attribute behaves.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;small_int_value&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;32_768&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;small_int_value&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;32_769&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; RangeError!&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;small_int_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32_767&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;small_int_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32_768&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; RangeError!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is so much more that we can do with these objects. The PostgreSQL adapter already casts the JSON data type. I can even see SQL Server returning a Nokogiri object for an XML data type. The sky is the limit. The core &lt;code&gt;Value&lt;/code&gt; object allows the SQL Server Adapter to implement guards for different connection modes. Our &lt;code&gt;TinyTDS&lt;/code&gt; connection returns all DB values mapped to their proper Ruby primitive. To avoid wasting precious time, we bypass all Rails type casting in one single place now.&lt;/p&gt;

&lt;p&gt;These objects are a great step forward and they should open up all sorts of possibilities for gems to extend our DB objects. Thanks so much to Sean Griffin and anyone else working on ActiveRecord to make it better, faster, and easier to use!&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://robots.thoughtbot.com/how-rails-works-type-casting&quot;&gt;How Rails&amp;#39; Type Casting Works&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 06 Jan 2015 00:00:00 -0500</pubDate>
        <link>/2015/01/06/activerecord-42s-type-casting/</link>
        <guid isPermaLink="true">/2015/01/06/activerecord-42s-type-casting/</guid>
      </item>
    
      <item>
        <title>Custom Oak Display Stands</title>
        <description>&lt;p&gt;A few months ago I decided to address my ongoing neck pain by raising the height for all 3 of my displays. I knew that &lt;a href=&quot;http://lifehacker.com/5755870/how-to-ergonomically-optimize-your-workspace&quot;&gt;good ergonomics&lt;/a&gt; dictated the top of a display needed to be around eye level. However, my eyes still spent most of their time looking downward. Frankly, I blame bottom oriented chat interfaces as well as my tendency to scroll and focus on code/content at the bottom of files.&lt;/p&gt;

&lt;p&gt;My solution back then was to grab any random box or book and move my displays&amp;#39; center to around eye level. Four months later, my &lt;a href=&quot;http://en.wikipedia.org/wiki/Minimum_viable_product&quot;&gt;MVP&lt;/a&gt; display change worked, no more neck pain! But I did have a new eye sore, those janky risers. I take great pride in my home office which includes solid pine paneling and oak mission furniture. In short, it was time for a wood working project. Here is a peak at the results, read on for the details.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/13-final.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-rockwell-bladerunner&quot;&gt;The Rockwell BladeRunner&lt;/h2&gt;

&lt;p&gt;At &lt;a href=&quot;http://www.customink.com/&quot;&gt;CutomInk&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://booster.com/&quot;&gt;Booster&lt;/a&gt;, we know all too well that the Blade Runner font &lt;a href=&quot;https://twitter.com/brshirtsdotcom/status/439111923158614016&quot;&gt;makes a winning custom t-shirt&lt;/a&gt;. For that reason alone, I have been on the hunt for a &lt;a href=&quot;https://www.rockwelltools.com/en-US/BladeRunner-X2.aspx&quot;&gt;Rockwell BladeRunner&lt;/a&gt; table saw and this project seemed like a perfect excuse. The BladeRunner would allow me to easily cut oak planks to perfectly match the shape of each of my displays&amp;#39; base.&lt;/p&gt;

&lt;p&gt;I first made a template on paper, pictured below. This allowed me to get some crude dimensions on the size and shape of the lumber I would need. I highly recommend that you trace your final templates on cardboard. The studier template will make it easier to transfer an outline to your wood pieces. Also, note how every good woodworking project needs beer, ham, and cheese!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/01-patterns.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;Paper patterns for each display.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From here I marked and cut each plank on my new BladeRunner. A few things to watch out for. First, oak is obviously hard! Make sure to get a few spare blades. Second, it really helps if you can secure the BladeRunner to your work table. I did this using the same clamps that I would use later to hold my laminated pieces together. Securing the BladeRunner will allow you to use a bit of turning force when cutting rounded edges.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/02-bladerunner.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;My new Rockwell BladeRunner.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;putting-things-on-top-of-other-things&quot;&gt;Putting Things On Top Of Other Things&lt;/h2&gt;

&lt;p&gt;In the fine tradition of &lt;a href=&quot;https://www.youtube.com/watch?v=8pBTK-pdMP0&quot;&gt;placing things on top of other things&lt;/a&gt;, my custom stands will rely on laminating a stack of cut planks. My HP display needed to be 6&amp;quot; tall which required 8 total 3/4&amp;quot; pieces. To make the final stand appear more sculpted, each plank after the 4th downward was cut 1/8&amp;quot; wider than the previous. My Thunderbolt display stand followed the same technique but only required two pieces.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/03-cuts.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;Before laminating the HP display stand.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Depending on your final shape and dimensions, you will need some good clamps to hold everything together. Make sure to apply your glue with a craft brush so that the entire glue area is covered.&lt;/p&gt;

&lt;div class=&quot;ms-ImgGallery&quot;&gt;
  &lt;div class=&quot;ms-ImgGallery-item&quot;&gt;&lt;img src=&quot;/assets/content/oak-display-stands/05-fastened1.jpg&quot; class=&quot;ms-Img ms-Img--fancy&quot; alt=&quot;Glueing display stands.&quot; /&gt;&lt;/div&gt;
  &lt;div class=&quot;ms-ImgGallery-item&quot;&gt;&lt;img src=&quot;/assets/content/oak-display-stands/05-fastened2.jpg&quot; class=&quot;ms-Img ms-Img--fancy&quot; alt=&quot;Glueing display stands.&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;ad-hoc-sanding-station&quot;&gt;Ad Hoc Sanding Station&lt;/h2&gt;

&lt;p&gt;Given that I had to taper sand a self made oak &amp;quot;stump&amp;quot;, I knew my work was cut out for me. Ideally this type of sanding required some sort of fixed vertical belt sander. My solution was to mount my Porter Cable upside down in my work bench&amp;#39;s vice grip. I even built a dust hood out of an Amazon Prime box (we got tons of those) hooked up to the Shop-Vac.&lt;/p&gt;

&lt;div class=&quot;ms-ImgGallery&quot;&gt;
  &lt;div class=&quot;ms-ImgGallery-item&quot;&gt;&lt;img src=&quot;/assets/content/oak-display-stands/07-hood1.jpg&quot; class=&quot;ms-Img ms-Img--fancy&quot; alt=&quot;Sanding station for display stands.&quot; /&gt;&lt;/div&gt;
  &lt;div class=&quot;ms-ImgGallery-item&quot;&gt;&lt;img src=&quot;/assets/content/oak-display-stands/07-hood2.jpg&quot; class=&quot;ms-Img ms-Img--fancy&quot; alt=&quot;Sanding station for display stands.&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This setup worked really well. I placed a shop light in the box too so that I could watch the piece while I sanded it. This helped me keep from over sanding which would have been easy to do given that I was using a 30-grit ceramic belt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/08-technique.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;finishing-touches&quot;&gt;Finishing Touches&lt;/h2&gt;

&lt;p&gt;Here are all 3 pieces after all the sanding was done. I went from the 30-grit, 60, 120, and then 300. I did everything past the 30-grit using a simple hand block. Using a belt sander for finner grits easily leads to burn marks. Lastly, I made sure to round off the hard corners on the edges of the wood too.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/09-final-sanded.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the finish, I chose a simple traditional cherry stain since this both matches my office&amp;#39;s pine paneling and mission desk. The picture below shows one coat of satin polyurethane.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/10-finished.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After allowing the stain and polyurethane to dry for a day, I smoothed off any rough edges with a soft steel wool. The last step was to add a handful of small felt guards to the bottom of each stand. This would allow me to easily adjust all my displays without scratching my desk.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/11-padded-feet.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-results&quot;&gt;The Results&lt;/h2&gt;

&lt;p&gt;Back to a clean and clutter free work environment with no clunky boxes or books in the way :)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/12-results1.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/oak-display-stands/12-results2.jpg&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 16 Dec 2014 00:00:00 -0500</pubDate>
        <link>/2014/12/16/custom-oak-display-stands/</link>
        <guid isPermaLink="true">/2014/12/16/custom-oak-display-stands/</guid>
      </item>
    
      <item>
        <title>From Rails 3.2 to 4.2</title>
        <description>&lt;p&gt;Last week I set out to upgrade &lt;a href=&quot;https://homemarks.com/&quot;&gt;HomeMarks&lt;/a&gt;, a personal bookmarking project of mine. This application sat on a very &lt;a href=&quot;https://homemarks.com/blog/2014-02-26-homemarks-v3-launches&quot;&gt;recent upgrade&lt;/a&gt; to Rails 3.2. It is written as an API to both an iOS and HTML JavaScript interface. It is by no means huge and should represent a nominal service oriented application. Here are some stats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;8 Models (450 LOC)&lt;/li&gt;
&lt;li&gt;11 Controllers (550 LOC)&lt;/li&gt;
&lt;li&gt;2 Mailers (50 LOC)&lt;/li&gt;
&lt;li&gt;8 Libraries (500 LOC)&lt;/li&gt;
&lt;li&gt;Using Ruby 2.1.2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application is heavily tested with an emphasis on controller and integrations. It uses a standard Rails test setup with simple &lt;a href=&quot;https://github.com/metaskills/minitest-spec-rails#readme&quot;&gt;minitest-spec-rails&lt;/a&gt; usage. Integrations are done using the Capybara DSL with the &lt;a href=&quot;https://github.com/teampoltergeist/poltergeist&quot;&gt;Poltergeist&lt;/a&gt; driver. JavaScript tests use &lt;a href=&quot;https://github.com/jfirebaugh/konacha&quot;&gt;Konacha&lt;/a&gt; which leverage MochaJS and the Chai assertion library.&lt;/p&gt;

&lt;p&gt;With the introductions out of the way let&amp;#39;s do some fun upgrade work! Here is a step by step process of how I tackled the task and I hope you find it useful.&lt;/p&gt;

&lt;h2 id=&quot;grease-the-wheels&quot;&gt;Grease The Wheels&lt;/h2&gt;

&lt;p&gt;The first step I always recommend for any Rails upgrade is to update your entire bundle with your current Rails semver as the only gem constraint. The goal here is to have no gem versions other than &lt;code&gt;~&amp;gt; 3.2&lt;/code&gt; for Rails itself in your Gemfile - hence allowing Bundler to do all the work during your big 4.2 update. For this reason you should delete any explicit gem version specs and run &lt;code&gt;bundle update&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;During this time you will want to remove any non-essential gems as well. Great examples are test related gems. Spending time debugging any non-essential gem during an upgrade process is the worst time spent of all. Likewise, identify gems that are obsolete in your target upgrade. In my application, good examples were the &lt;code&gt;mail_view&lt;/code&gt; and the &lt;code&gt;quiet_assets&lt;/code&gt; gems. Hopefully your application has a tagging convention for notes when upgrading. At CustomInk, we use &lt;code&gt;PENDING: [Rails4]...&lt;/code&gt; style comment tags.&lt;/p&gt;

&lt;p&gt;Once done, update your master branch with this work and get that deployed. This is your new base for the push to Rails 4.2.&lt;/p&gt;

&lt;h2 id=&quot;make-a-template&quot;&gt;Make A Template&lt;/h2&gt;

&lt;p&gt;We want to reference a fresh 4.2 application as a guide. This will come in handy in many ways later on. During the time of this article Rails 4.2 was in beta1, so all examples will use that version. Please adjust your commands/examples as newer versions are released.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;gem install rails 4.2.0.beta1
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rbenv rehash
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rails new myapp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;the-big-bundle-update&quot;&gt;The Big Bundle Update&lt;/h2&gt;

&lt;p&gt;We need to focus on the Gemfile first. Start by changing that &lt;code&gt;~&amp;gt; 3.2&lt;/code&gt; twiddle-wakka to our target version of &lt;code&gt;~&amp;gt; 4.2.0.beta1&lt;/code&gt; as our Rails gem version. Go through your notes and delete those obsolete gems too and make any adjustments to any pessimistic version if you noted any.&lt;/p&gt;

&lt;p&gt;In Rails 4.2, there is no such thing as an &lt;code&gt;assets&lt;/code&gt; group for gems. So I removed my &lt;code&gt;group :assets&lt;/code&gt; and flattened my asset gems to the root of the Gemfile. I do suggest maintaining an comment and clustering your asset gems in your Gemfile as a way to keep them organized. Due to &lt;code&gt;sass-rails&lt;/code&gt; being in beta, I ended up with something like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bcrypt-ruby&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pg&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 4.2.0.beta1&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# PENDING: [Rails 4.2] Remove wakka.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Assets&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bourbon&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;coffee-rails&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jquery-rails&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sass-rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 5.0.0.beta1&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# PENDING: [Rails 4.2] Remove wakka.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uglifier&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, I find it extremely useful to delete the &lt;code&gt;Gemfile.lock&lt;/code&gt; now. In my experience Bundler will have a much better time coping by allowing the entire dep graph to be rebuilt. Now go for the big update with a simple bundle install.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ bundle install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you run into any problems here, take them on one by one. In some cases you could be using a gem that does not optimistically include 4.x versions. Before proceeding, find each project&amp;#39;s issue tracker and do a little research. If you encounter resistance, look broadly first and avoid hacking around it. This could be your time to shine and help with an open source pull request.&lt;/p&gt;

&lt;p&gt;Once you are bundled, you are ready for the next step. &lt;strong&gt;Avoid the temptation to launch your application or running tests!&lt;/strong&gt; You are no where near ready for that, so slow your roll. We still have some good work to do.&lt;/p&gt;

&lt;h2 id=&quot;the-mimic-process&quot;&gt;The Mimic Process&lt;/h2&gt;

&lt;p&gt;This is a great time to open the template application we created above. It is a very straightforward process to go through each of the application&amp;#39;s files &amp;amp; folders and mimic the template within your own application.&lt;/p&gt;

&lt;p&gt;In my experience I have seen a lot of pain in converting over &lt;code&gt;config/environments&lt;/code&gt; files to the newer format. If you have never done so, I highly recommend following a simple practice that makes upgrading of these files easier in the future. Always keep the environment file largely untouched and add your configs to the bottom of each below a comment like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ... Rails generated ...&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# My Configs&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ----------&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;action_mailer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show_previews&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This makes updating these files in the future go much quicker. Here are some general notes I had when doing my entire mimesis process.&lt;/p&gt;

&lt;h4 id=&quot;environments-amp-initializers&quot;&gt;Environments &amp;amp; Initializers&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Removed &lt;code&gt;config.filter_parameters&lt;/code&gt; from application.rb to config/initializers/filter_parameter_logging.rb&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;config.assets.precompile&lt;/code&gt; and &lt;code&gt;config.assets.version&lt;/code&gt; have moved to config/initializers/assets.rb&lt;/li&gt;
&lt;li&gt;Many files now use the &lt;code&gt;Rails.application&lt;/code&gt; singleton resource vs &lt;code&gt;MyApp::Application&lt;/code&gt; constant.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;concerns-directories&quot;&gt;Concerns Directories&lt;/h4&gt;

&lt;p&gt;I fully embraced the new concern directories. I created both &lt;code&gt;app/controllers/concerns/.keep&lt;/code&gt; and &lt;code&gt;app/models/concerns/.keep&lt;/code&gt;. I found there were a few files in my lib directory that were actually concerns. For example, I moved both my AuthenticatedSystem and RenderInvalidRecord modules to the controller concerns. This allowed me to remove any hacks I had for setting the auto load path on the lib directory too.&lt;/p&gt;

&lt;h4 id=&quot;bin-directory-amp-spring&quot;&gt;Bin Directory &amp;amp; Spring&lt;/h4&gt;

&lt;p&gt;I have been using both bundler bin stubs and Spring in all of my 3.2 applications. Now that Rails supports both the local &lt;code&gt;bin&lt;/code&gt; directory and Spring in an integrated way, I wanted to follow the golden path of least resistance.&lt;/p&gt;

&lt;p&gt;The first step was to blow away my entire bin directory and just copy over the one from the application template. These new bin files for &lt;code&gt;rake&lt;/code&gt; and &lt;code&gt;rails&lt;/code&gt; leverage the Spring preloader. Make sure to delete your local or global bundle config for installing bins too. Do this with &lt;code&gt;bundle config --delete bin&lt;/code&gt;. Now, instead of having Bundler install bin stubs for every gem which could conflict with the preloader bins, we should be explicit on a per gem basis. For example, this would install the bins for guard.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ bundle binstubs guard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, if you have never done so, change your shell&amp;#39;s &lt;code&gt;PATH&lt;/code&gt; to look for the local &lt;code&gt;./bin&lt;/code&gt; directory before any others. I do this after my rbenv initialization.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;rbenv init -&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;routes-file&quot;&gt;Routes File&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Removed my &lt;code&gt;match&lt;/code&gt; methods in favor of &lt;code&gt;get&lt;/code&gt; verb method.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;new-test-directories&quot;&gt;New Test Directories&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Renamed &lt;code&gt;test/functional&lt;/code&gt; folder to &lt;code&gt;test/controllers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Renamed &lt;code&gt;test/unit&lt;/code&gt; folder to &lt;code&gt;test/models&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Created a &lt;code&gt;test/mailers&lt;/code&gt; folder and moved all my mailer tests from units to it.&lt;/li&gt;
&lt;li&gt;Renamed &lt;code&gt;ActionController::IntegrationTest&lt;/code&gt; to &lt;code&gt;ActionDispatch::IntegrationTest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;framework-changes&quot;&gt;Framework Changes&lt;/h2&gt;

&lt;p&gt;Now is the time where you can start to run your tests and identify what needs to change. I recommend starting with the model tests and moving on from there. Though I am a big fan of Guard for automatic test runs, Rails now has a new option when using rake. Just pass the filename after the test argument. For example, this would run a single model test and since the new &lt;code&gt;bin/rake&lt;/code&gt; file uses Spring, you can run this command over and over again very quickly.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ rake test test/models/user_test.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Below are things I found while moving through my tests. I have organized them by framework. They are by no means comprehensive and your application may expose more differences between Rails 3.2 and 4.2.&lt;/p&gt;

&lt;h4 id=&quot;activerecord&quot;&gt;ActiveRecord&lt;/h4&gt;

&lt;p&gt;You are going to see a lot of &lt;code&gt;ArgumentError: Unknown key: ...&lt;/code&gt; errors. The reason is that Rails 4.0 now requires that scopes use a callable object such as a Proc or lambda. I saw these errors mostly on &lt;code&gt;:order&lt;/code&gt; and the &lt;code&gt;:readonly&lt;/code&gt; option arguments. Here are a few before/after examples.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Old&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;order: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;position&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;through: :foos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;readonly: &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;ss&quot;&gt;order: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;foos.position, bars.position&#39;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# New&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foos&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;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;position&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bars&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;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;foos.position, bars.position&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;readonly&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;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;through: :foos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seems the callable object has to be the second argument and you can easily chain the scopes within. I took a wild guess that the &lt;code&gt;readyonly&lt;/code&gt; scope took an optional &lt;code&gt;false&lt;/code&gt; argument and was handsomely rewarded.&lt;/p&gt;

&lt;p&gt;I also got a few good &lt;code&gt;ArgumentError: The provided regular expression is using multiline anchors (^ or $) ...&lt;/code&gt; errors. This was easy to fix by using the suggested \A and \z instead. Really happy to see the framework warning on this common errors when using regular expressions for validations.&lt;/p&gt;

&lt;p&gt;I deleted all the &lt;code&gt;attr_accesible&lt;/code&gt; declarations from my models and switched to strong parameters in the controllers. If you are new to strong parameters, &lt;a href=&quot;http://easyactiverecord.com/blog/2014/04/01/rails4-strong-parameters-and-the-attr-accessible-macro&quot;&gt;check out this article&lt;/a&gt; which goes into great depth on the topic. Alternatively, you can start using strong parameters before you upgrade to Rails 4.x by using the backward compatible &lt;a href=&quot;https://github.com/rails/strong_parameters&quot;&gt;strong parameters gem&lt;/a&gt;. A great strategy to ease large application transitions. Thanks to &lt;a href=&quot;http://about.me/cmar&quot;&gt;Chris Mar&lt;/a&gt; for pointing out this approach to our team.&lt;/p&gt;

&lt;p&gt;The class &lt;code&gt;update_all&lt;/code&gt; no longer takes a second conditions argument. I always disliked methods that took two option hashes and this is a great change. For example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Old&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;author: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;David&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# New&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;author: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;David&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, the &lt;code&gt;all&lt;/code&gt; method no longer takes finder options.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Old&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&#39;ken@metaskills.net&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# New&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&#39;ken@metaskills.net&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;actionmailer&quot;&gt;ActionMailer&lt;/h4&gt;

&lt;p&gt;Using &lt;code&gt;_path&lt;/code&gt; url methods in mailers will now result in a &lt;code&gt;DEPRECATION WARNING... cannot be used here as a full URL is required&lt;/code&gt; message. Unless you were manually augmenting these paths to have a host, this is a good thing and will keep developers from including partial URLs in mailers.&lt;/p&gt;

&lt;p&gt;MailView is now fully integrated into ActionMailer. Read &lt;a href=&quot;http://brewhouse.io/blog/2013/12/17/whats-new-in-rails-4-1.html&quot;&gt;this article&lt;/a&gt; for full details. If you have never used MailView in a Rails 3 application, it allows you to develop your mails in the browser as if they were controller view. When moving from old MailView support to Rails 4.x usage, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;config.action_mailer.show_previews&lt;/code&gt; to config/environments/development.rb file.&lt;/li&gt;
&lt;li&gt;Moved previous mailer previews to new &lt;code&gt;test/mailers/previews&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;actionpack&quot;&gt;ActionPack&lt;/h4&gt;

&lt;p&gt;Partials can no longer have &lt;code&gt;-&lt;/code&gt; hyphens in the filename. I had to change a few.&lt;/p&gt;

&lt;p&gt;There is a new and &lt;a href=&quot;https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/request_forgery_protection.rb&quot;&gt;better request forgery protection&lt;/a&gt; in Rails 4.x. Read the source link for full error messages and documentation. In my case, I had already redefined a protected &lt;code&gt;protect_against_forgery?&lt;/code&gt; for a special controller and needed to only add &lt;code&gt;skip_before_action :verify_authenticity_token&lt;/code&gt; to my filters to fully work around the security warning.&lt;/p&gt;

&lt;h4 id=&quot;asset-pipeline&quot;&gt;Asset Pipeline&lt;/h4&gt;

&lt;p&gt;The biggest issue that I had is that asset compilation no longer generates non-digest filenames for each asset. This &lt;a href=&quot;https://github.com/rails/sprockets-rails/issues/49&quot;&gt;github issue&lt;/a&gt; explains the rationale, but I do believe there are some corner cases where you do want to reference the non-digest asset filename.&lt;/p&gt;

&lt;p&gt;If after careful examination you find yourself in need of this corner case, do not disable digests for all files. Instead install the &lt;a href=&quot;https://github.com/alexspeller/non-stupid-digest-assets&quot;&gt;non-stupid-digest-assets&lt;/a&gt; gem which allows you to whitelist specific asset files and thereby including a non-digest filename along with the fingerprinted filenames for said asset(s). I recommend putting the &lt;code&gt;NonStupidDigestAssets.whitelist&lt;/code&gt; settings at the bottom of the new &lt;code&gt;config/initializers/assets.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;h4 id=&quot;testing&quot;&gt;Testing&lt;/h4&gt;

&lt;p&gt;The Rails testing task strategy has changed a lot. By default now, when you run &lt;code&gt;rake test&lt;/code&gt; all models, mailers, controllers and integrations are run in one collective suite run. If you are interested in learning how, read the &lt;a href=&quot;https://github.com/rails/rails/blob/master/railties/lib/rails/test_unit/testing.rake&quot;&gt;testing.rake&lt;/a&gt; source. I also talked about how to add different directories to this process within a &lt;a href=&quot;https://github.com/metaskills/minitest-spec-rails/issues/49&quot;&gt;github issues under the minitest-spec-rails&lt;/a&gt; project where &lt;a href=&quot;http://blowmage.com&quot;&gt;Mike Moore&lt;/a&gt; contributed a few helpful hints too.&lt;/p&gt;

&lt;p&gt;The reason I mention this is that it is somewhat common to expect your Capybara enhanced integrations to run in a distinct process. Because of this, it is also common to see monkey patches to the ActiveRecord connection pool to support integration tests that leverage DB transactions. Depending on your setup, you may be required to make a few tweaks.&lt;/p&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In Closing&lt;/h2&gt;

&lt;p&gt;Upgrading Rails applications used to be a pain! My recent upgrade only took two evenings of my spare time. In my opinion Rails 3.1 and up have become much more stable for both application and gem authors to leverage the framework. Thus making upgrades approachable. Keep your applications small and focused as a way to win the upgrade wars!&lt;/p&gt;

&lt;p&gt;In closing, thanks for reading and I hope you found this information helpful. If you have any questions, feel free to ask in the comments. Cheers!&lt;/p&gt;
</description>
        <pubDate>Tue, 16 Sep 2014 00:00:00 -0400</pubDate>
        <link>/2014/09/16/from-rails-3-2-to-4-2/</link>
        <guid isPermaLink="true">/2014/09/16/from-rails-3-2-to-4-2/</guid>
      </item>
    
      <item>
        <title>Dynamic SVGs Using &amp;lt;defs&amp;gt; Elements &amp;amp; JavaScript</title>
        <description>&lt;p&gt;The scalable vector graphics format has a really nifty way to define and reuse objects. It does this by allowing objects or paths to be defined in the &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; element and then used one or many times with the &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; element. It is a great way to keep your SVG&amp;#39;s file size low. Even better, it makes for a great programmatic interface to dynamically compose an image.&lt;/p&gt;

&lt;p&gt;While designing the third iteration of my personal &lt;a href=&quot;http://metaskills.net/&quot;&gt;MetaSkills.net&lt;/a&gt; blog, I decided to carry the retro space theme into the background of the fixed left navigation area. The design called for something like this image below. Besides the planet, it has three distinct types of stars that are scattered all over the place. Each has a different scale and opacity with plans to animate a few.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/svg-planet-stars.png&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;MetaSkills.net Planet &amp; Stars SVG Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So where to start? We could export a final pre-designed SVG image from any type of vector program – but that would bloat the file size since it would copy and paste each star&amp;#39;s path. It would also make animating distinct stars tricky and require post production edits. Lastly, who has time to randomly scatter stars? Not me! So let&amp;#39;s program up a solution that solves all of this for us. Here is the base SVG structure that we are going to work with.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;svg&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.1&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;300px&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;700px&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;viewBox=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0 0 300 700&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;preserveAspectRatio=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;xMidYMax slice&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;xmlns:xlink=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/1999/xlink&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Define star objects here. --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;style&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    .star    { fill: #95a8b1; }
    .burst   { fill: #e4522a; }
    .steeler { fill: #fffbe1; }
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;rect&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;100%&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;100%&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;fill=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#052838&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;g&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;starfield&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Use stars objects here. --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/ecmascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Dynamically create stars here. --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our image will have a slender vertical portrait area to match the general proportions of the sidebar. The SVG is setup to preserve the &lt;a href=&quot;http://www.justinmccandless.com/blog/Making+Sense+of+SVG+viewBox&amp;#x27;s+Madness&quot;&gt;aspect ratio&lt;/a&gt; in such a way that allows the bottom planet to always be in view when scaled. We have a &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; area where we can add reusable objects, an in-line style sheet for our awesome CSS, and a &lt;code&gt;&amp;lt;g&amp;gt;&lt;/code&gt; starfield element to hold each star. Lastly, a place to write some JavaScript.&lt;/p&gt;

&lt;h2 id=&quot;base-star-objects&quot;&gt;Base Star Objects&lt;/h2&gt;

&lt;p&gt;Adding these to our SVG is really easy. I started by creating a canvas in my favorite vector program, &lt;a href=&quot;http://bohemiancoding.com/sketch/&quot;&gt;Sketch&lt;/a&gt;. We want to make sure our exported paths start at 0,0 position and are are generally the size you expect to use them. This will help you later when translating these paths to different positions.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/content/svg-our-awesome-sketch.png&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;Setting up our base stars in the Sketch v3 application.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I exported each star type as an SVG and then copied the path into the &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; area of our template above. When you do this make sure that each path has its own unique id. Also, you may want to optimize your paths. Many programs export 6 or more decimal points for a path&amp;#39;s data. I recommend running them through some sort of &lt;a href=&quot;http://petercollingridge.appspot.com/svg_optimiser&quot;&gt;SVG optimiser&lt;/a&gt; or tweaking your export settings if your art program has them. Now we have our reusable path objects, see below. Examples have truncated &lt;code&gt;d&lt;/code&gt; attributes for brevity.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;path&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;star&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;d=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;M2.395,0.409 C2.026,0.973 ... Z&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;path&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;burst&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;d=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;M6.092,4.816 L1.661,3.4 ... Z&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;path&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;steeler&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;d=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;M3.231,6.211 L0,5.830 ... Z&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;using-defined-objects&quot;&gt;Using Defined Objects&lt;/h2&gt;

&lt;p&gt;If we were to view our SVG now, it would be pretty boring and contain only the colored background rect. So lets add some stars by using the defined objects above. We do this with the &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; element by setting each &lt;code&gt;xlink:href&lt;/code&gt; to the id of that object we want to target. To move and size each star, we use the SVG &lt;code&gt;transform&lt;/code&gt; attribute to both translate and scale each star. Adding these elements right before the JavaScript tag will create the following image.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;use&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xlink:href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#star&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;transform=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;translate(10,10) scale(1.0)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;star&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;use&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xlink:href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#burst&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;transform=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;translate(30,20) scale(1.0)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;burst&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;use&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xlink:href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#steeler&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;transform=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;translate(60,10) scale(1.5)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;steeler&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/assets/content/svg-planet-stars-v1.png&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; alt=&quot;MetaSkills.net Planet &amp; Stars SVG Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Still kind of boring... and who has time to stochastically place several dozen stars around the canvas? Time for some JavaScript automation.&lt;/p&gt;

&lt;h2 id=&quot;svgs-amp-javascript&quot;&gt;SVGs &amp;amp; JavaScript&lt;/h2&gt;

&lt;p&gt;Yes! SVGs are distinct documents that can have their own CSS and JavaScript. But in order for this JavaScript to execute, we must embed it into the parent HTML document. Linking to an SVG via an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag will not allow this due to security concerns. We can get around that issue by using an &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; tag instead.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;object&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;our-awesome.svg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image/svg+xml&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/object&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that our SVG&amp;#39;s JavaScript will execute, how do we go about adding &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; elements to our SVG&amp;#39;s document? Fortunately the techniques are very similar to how you would do this with vanilla JavaScript and the HTML DOM. The minor difference is that we have to use two namespaces. One for creating elements and the second for adding the xlink attribute. I recommend we start our JavaScript off with these namespaces as vars. We also want to create variables for our canvas width and height. Finally, we want a handle to our starfield group element.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xmlns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;xlinkns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://www.w3.org/1999/xlink&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;700&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;starfield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;starfield&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;random-javascript-helpers&quot;&gt;Random JavaScript Helpers&lt;/h2&gt;

&lt;p&gt;Before we just start adding some stars, we need some random functions to help us position and scale our stars. I like to start low level and build up. So here is our random function that takes a min and max value.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;min&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;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;nx&quot;&gt;randomBase&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;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// 229.5510318595916&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomBase&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;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// -22.134714818093926&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Building on that, we want to made a random position function to help place each star in our field. This helper only needs the &lt;code&gt;max&lt;/code&gt; argument which will be either our &lt;code&gt;width&lt;/code&gt; or &lt;code&gt;height&lt;/code&gt;. Notice too how it blankets our canvas area by setting the minimal and maximum to -50 and +50. This will ensure each star could be placed slightly off canvas and keeping them from appearing clustered toward the middle. We also floor the return value, no decimals are needed for position.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;randomBase&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;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is our random scale function which takes a &lt;code&gt;min&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt; threshold. This will allow us to adjust the weight of each star type in the cluster and possibly adjust the exported size differences from our image program into the &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; area. This function returns a two decimal float value.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;randomBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&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;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 0.6&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 0.85&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, here is a helper function that builds on top of &lt;code&gt;randomScale&lt;/code&gt;. It takes a star &lt;code&gt;name&lt;/code&gt; and returns the proper value.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScaleNamed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;star&#39;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;burst&#39;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;steeler&#39;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;adding-use-elements&quot;&gt;Adding Use Elements&lt;/h2&gt;

&lt;p&gt;Now that we have the boring random functions out of the way, time to create our star-agnostic &lt;code&gt;addElement&lt;/code&gt; function. This will create a new &lt;code&gt;&amp;lt;g&amp;gt;&lt;/code&gt; element for each star&amp;#39;s &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; element. The group is for placement and size, the use is for twinkle and shine animations.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElementNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElementNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;use&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;translate(&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&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;s1&quot;&gt;&#39;,&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&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;s1&quot;&gt;&#39;) &#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&#39;scale(&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomScaleNamed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&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;s1&quot;&gt;&#39;)&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttributeNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttributeNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xlinkns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;xlink:href&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttributeNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;transform&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;starfield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function ends by placing the newly created element within the starfield. For example, calling &lt;code&gt;addElement(&amp;#39;burst&amp;#39;)&lt;/code&gt; once would create this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;g&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;starfield&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;g&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;transform=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;translate(58,151) scale(0.9)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;use&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xlink:href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#burst&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;burst&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To add a bunch of stars!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;addElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;steeler&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;addElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;burst&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;addElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;star&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going Further&lt;/h2&gt;

&lt;p&gt;Thanks for reading this far! If you are interested in how I handled star animations using Bourbon &amp;amp; Sass, check out &lt;a href=&quot;https://gist.github.com/metaskills/f3be83a2cabf9e1061fc&quot;&gt;this gist&lt;/a&gt; on GitHub for my source code. It also shows how I animated the planet to spin at the bottom of the image and cover the background stars.&lt;/p&gt;

&lt;p&gt;I hope you have as much fun as I have with animating SVGs using JavaScript and Sass!&lt;/p&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs&quot;&gt;SVG &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; documentation on MDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use&quot;&gt;SVG &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; documentation on MDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.justinmccandless.com/blog/Making+Sense+of+SVG+viewBox&amp;#x27;s+Madness&quot;&gt;Making Sense of SVG viewBox&amp;#39;s Madness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bohemiancoding.com/sketch/&quot;&gt;Sketch v3 - Lightweight Design Program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://petercollingridge.appspot.com/svg_optimiser&quot;&gt;SVG Optimiser Tools &amp;amp; Experiments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 29 Aug 2014 00:00:00 -0400</pubDate>
        <link>/2014/08/29/dynamic-svgs-using-defs-elements-and-javascript/</link>
        <guid isPermaLink="true">/2014/08/29/dynamic-svgs-using-defs-elements-and-javascript/</guid>
      </item>
    
      <item>
        <title>Jekyll-Style Blogging On Rails</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/jekyll-on-rails.png&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt;
Do you want to use your existing Rails&amp;#39; layouts &amp;amp; business logic for your new Blog? Do you know and love &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt;, but cant seem to get the two to play nice together?&lt;/p&gt;

&lt;p&gt;In the spirit of &lt;a href=&quot;http://c2.com/cgi/wiki?DoSimpleThings&quot;&gt;doing the simplest thing&lt;/a&gt; that could possibly work, I set out on a solution to this problem. Besides mimicing Jekyll as closely as possible, my requirements were loosly defined as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a directory of markdown files with a &lt;code&gt;YYYY-MM-DD-blog-post-title.md&lt;/code&gt; naming convention.&lt;/li&gt;
&lt;li&gt;Have fast syntax highlighting via fenced code blocks.&lt;/li&gt;
&lt;li&gt;Expose model class finders for a single resource &amp;amp; collections.&lt;/li&gt;
&lt;li&gt;Some model object to ask posts for their title, date, html, etc.&lt;/li&gt;
&lt;li&gt;Make local development follow Rails conventions. Like page refreshes.&lt;/li&gt;
&lt;li&gt;Provide a reasonable amount of caching in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally if I had time or the gumption:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use YAML front matter for different post titles &amp;amp; other options.&lt;/li&gt;
&lt;li&gt;Preprocess markdown with ERB and allow Rails routes &amp;amp; helpers to be used.&lt;/li&gt;
&lt;li&gt;Ask each post for an excerpt so we can render teasers elsewhere.&lt;/li&gt;
&lt;li&gt;Create a rake task that tees up a new post using the current date.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;

&lt;p&gt;Most times I like to start coding to high-level interfaces. It helps me think about the smaller details I will need to build later. A Rails controller is a good option but be careful and keep it simple! If you are the type of person that likes to jump to the end, check out &lt;a href=&quot;https://gist.github.com/metaskills/11071934&quot;&gt;the final gist&lt;/a&gt; of our completed work.&lt;/p&gt;

&lt;p&gt;First, we are going to make our blog routes and controller. We want two actions, an &lt;code&gt;index&lt;/code&gt; to list all blog posts and a &lt;code&gt;show&lt;/code&gt; to render each post.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In config/routes.rb&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:blog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;only: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# In app/controllers/blog_controller.rb&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;site&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:find_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;only: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BlogPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&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;show&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;text: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;layout: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;site&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stale?&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;public: &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;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;find_post&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BlogPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blog_index_path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@post&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty simple looking, but this code exposes some neat details that we will have to build while accomplishing a lot too. Our &lt;code&gt;index&lt;/code&gt; action shows we will need a class finder for all posts and assumes they will be ordered somehow. The &lt;code&gt;show&lt;/code&gt; action which is behind our &lt;code&gt;find_post&lt;/code&gt; filter tells us we need some type of key for our posts – likewise we have determined that we need an &lt;code&gt;html&lt;/code&gt; instance method. Lastly, we are going to check when a post is stale somehow while setting the public Cache-Control header for proxies.&lt;/p&gt;

&lt;h2 id=&quot;our-blogpost-model&quot;&gt;Our BlogPost Model&lt;/h2&gt;

&lt;p&gt;Our &lt;code&gt;:id&lt;/code&gt; key will use the file name as our &lt;a href=&quot;http://en.wikipedia.org/wiki/Clean_URL#Slug&quot;&gt;slug&lt;/a&gt;. Our markdown files will be located where our controller would normally find them, in the &lt;code&gt;app/views/blog&lt;/code&gt; directory. Feel free to create your first post there, name it &lt;code&gt;2014-04-19-my-first-post.md&lt;/code&gt; using the current date. Now here is our first itteration of our new &lt;code&gt;BlogPost&lt;/code&gt; model that allows us to find our posts.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:slug&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;all_slugs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&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;slug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&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;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;detect&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;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&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;directory&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;app&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;views&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;blog&#39;&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;all_slugs&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@all_slugs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/*.md&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&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;f&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\.md$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;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;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how we memoize the private &lt;code&gt;all_slugs&lt;/code&gt; class method to avoid hiting the filesystem again and again in production? This idea is definitly not complete and if needed, we can update it later. So, with the class methods out of the way, we can flesh out the model more. But first, we need to think about Jekyll.&lt;/p&gt;

&lt;h2 id=&quot;time-for-jekyll&quot;&gt;Time For Jekyll&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ve used Jekyll for a handful of static sites and blogs. Most of which have been running the next major version which is not quite out yet. Jekyll v2 is amazing and we totally need it for this project. Below are the gem deps you will need to bundle up. Remember, when Jekyll v2 is released, you can change your Gemfile as needed.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In Gemfile&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jekyll&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 2.0.0.alpha&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;redcarpet&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rouge&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, most of us are familiar with the &lt;a href=&quot;https://github.com/vmg/redcarpet&quot;&gt;Redcarpet&lt;/a&gt; gem. That will be the markdown converter we use, but what about rouge? The &lt;a href=&quot;https://github.com/jayferd/rouge&quot;&gt;Rouge&lt;/a&gt; gem is a pure-ruby syntax highlighter. It can highlight over 60 languages, and output HTML or ANSI 256-color text. Its HTML output is compatible with existing stylesheets designed for pygments.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ...&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;to_html&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Converters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Markdown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RedcarpetParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;highlighter&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rouge&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;redcarpet&#39;&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;s1&quot;&gt;&#39;extensions&#39;&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;s2&quot;&gt;&quot;no_intra_emphasis&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fenced_code_blocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;autolink&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;strikethrough&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;lax_spacing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;superscript&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;with_toc_data&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is not just sexy, Rouge is fast too! And by using it, we avoid bundling to pygments which has Python dependencies. We are going to let Jekyll do the heavy lifting and implement our private &lt;code&gt;to_html&lt;/code&gt; method like so. This will give us Github flavored markdown using Rouge for our fenced code blocks.&lt;/p&gt;

&lt;h2 id=&quot;other-blogpost-details&quot;&gt;Other BlogPost Details&lt;/h2&gt;

&lt;p&gt;In our &lt;code&gt;BlogPost.all&lt;/code&gt; class method, we called sort on the collection with the expectation that the newest post comes first. To fulfill this we are going to use Ruby&amp;#39;s &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; spaceship operator by comparing each post&amp;#39;s date. This completes our controller&amp;#39;s &lt;code&gt;index&lt;/code&gt; requirement.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;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;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We want each post to have a &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;date&lt;/code&gt; method. We can easily parse these form the slug. I even made a &lt;code&gt;date_formatted&lt;/code&gt; method using ActiveSupport&amp;#39;s Inflector that will be useful for our views. It returns date strings like April 19th, 2014. We also have a &lt;code&gt;path&lt;/code&gt; method that we can use when linking to our posts from elsewhere in our site. It will use the slug as the &lt;code&gt;:id&lt;/code&gt; param. This completes our controller&amp;#39;s &lt;code&gt;find_post&lt;/code&gt; requirement and gives us pretty URLs just like Jekyll.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\d{4}-\d{2}-\d{2}-/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;titleize&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;date&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&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;date_formatted&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;day_format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Inflector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ordinalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%B &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;day_format&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, %G&quot;&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;path&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;/blog/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before implementing our markdown to HTML conversion, we should think about caching. Following Rails&amp;#39; &lt;a href=&quot;http://guides.rubyonrails.org/caching_with_rails.html&quot;&gt;conventions&lt;/a&gt; we implment a &lt;code&gt;cache_key&lt;/code&gt; method that combines the blog namespace with the posts unique slug and timestamp. The &lt;code&gt;updated_at&lt;/code&gt; timestamp is simply the last time the file was modified on disk. Convention is to convert this to an integer which is seconds since Unix Epoch. The &lt;code&gt;cache_key&lt;/code&gt; will be used by the controller&amp;#39;s &lt;code&gt;show&lt;/code&gt; method when determining the ETag for the response.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updated_at&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&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;cache_key&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expand_cache_key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;blog&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updated_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&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;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the fun part, converting our markdown to HTML. We are going to use the &lt;code&gt;Rails.cache&lt;/code&gt; which in local development is a simple memory store and Memcached in production. The &lt;code&gt;fetch&lt;/code&gt; method takes a key and a block. The block is only executed if there is a cache miss.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlogPost&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;html&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache_key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_html&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;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;file_path&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;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.md&quot;&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;markdown&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache_key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/markdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;code-highlighting&quot;&gt;Code Highlighting&lt;/h2&gt;

&lt;p&gt;The only thing left to do is style the highlighted output from the Rouge gem. Thankfully, there are many existing pygment theme options spread accross the internet. Here are a few to get you started.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/richleland/pygments-css&quot;&gt;pygments-css&lt;/a&gt; - CSS files created from pygment&amp;#39;s built-in styles.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/StylishThemes/GitHub-Dark/&quot;&gt;GitHub-Dark&lt;/a&gt; - GitHub Dark theme for Stylish. Browse the themes directory.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aahan/pygments-github-style&quot;&gt;pygments-github-style&lt;/a&gt; - GitHub style for Pygments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the &lt;a href=&quot;http://homemarks.com/&quot;&gt;HomeMarks&lt;/a&gt; blog, I used the github &lt;code&gt;jekyll-github.css&lt;/code&gt; from the last resource above. Have fun choosing your own and &lt;code&gt;@import&lt;/code&gt; it into your existing CSS bundle in the manner that matches your own project.&lt;/p&gt;

&lt;h2 id=&quot;taking-it-further&quot;&gt;Taking It Further?&lt;/h2&gt;

&lt;p&gt;So that&amp;#39;s it, we can ship it! But what about those other great requirements like YAML front matter, ERB templates, Rails&amp;#39; routes/helpers, and more? The good news is that I found the time to do them all. You can find each implemented in the final &lt;a href=&quot;https://gist.github.com/metaskills/11071934&quot;&gt;Jekyll-Style Blogging On Rails&lt;/a&gt; gist.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;scope&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;helpers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url_helpers&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One aspect that I was particularly proud of was ERB pre-processing with a evaluation scope to Rails&amp;#39; routes and helpers. The solution turned out to be simple after digging into the &lt;a href=&quot;https://github.com/rails/rails/tree/4-1-stable/railties/lib/rails/console&quot;&gt;railties IRB console&lt;/a&gt; helpers and ActionPack. My solution above used this &lt;code&gt;scope&lt;/code&gt; with the Tilt&amp;#39;s erubis template.&lt;/p&gt;

&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where To Go From Here?&lt;/h2&gt;

&lt;p&gt;With &lt;a href=&quot;https://gist.github.com/metaskills/11071934&quot;&gt;this setup&lt;/a&gt;, you have a great foundation for Jekyll on Rails. Feel free to customize it as needed. Some ideas include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better caching in production. Currently hits the filesystem for &lt;code&gt;cache_key&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Maybe make a jekyll-rails engine that does all of this for you?&lt;/li&gt;
&lt;li&gt;Add an Emoji HTML filter to your posts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;Thanks for reading! Would love to hear your feedback too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/metaskills/11071934&quot;&gt;The Final &amp;quot;Jekyll-Style Blogging On Rails&amp;quot; Gist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://c2.com/cgi/wiki?DoSimpleThings&quot;&gt;Do Simple Things&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 19 Apr 2014 00:00:00 -0400</pubDate>
        <link>/2014/04/19/jekyll-style-blogging-on-rail/</link>
        <guid isPermaLink="true">/2014/04/19/jekyll-style-blogging-on-rail/</guid>
      </item>
    
      <item>
        <title>Thanks To My Mother For The Career I Have Today!</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/mom-linda-brazie-collins-1.jpg&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
As a white male in the computer industry, I have never felt like I could add value to the conversations that call for diversity and respect to all those that share the same passions I do. Instead, since teaching myself to program several years ago, I have worked very hard to openly advocate the love I have for software development through our local &lt;a href=&quot;http://757rb.org&quot;&gt;@757rb&lt;/a&gt; user group and whomever would give me a platform to do so. Never murmuring a comment that came close to gender related.&lt;/p&gt;

&lt;p&gt;However, today, I really felt compelled to share something that only recently occurred to me. I owe my entire career path and love of computers to my Mom. In fact, the more I think about it – she is my primary &amp;quot;you can do anything&amp;quot; influence that nurtured both my creative thinking and technical know how.&lt;/p&gt;

&lt;h2 id=&quot;rosie-the-riveter&quot;&gt;Rosie the Riveter&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/mom-linda-brazie-collins-2.jpg&quot; alt=&quot;Linda Brazie&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
So let me introduce you to my Mom and share a bit of her story which seems to strike a chord even today. These photos are her working at the Norfolk Naval Shipyard here in Portsmouth, Virginia. Most everyone knows that during WWII there were many women working in places like the Shipyard doing jobs only men would do. After the war, there were little or no women I am told working in these positions. My Mom was the first female apprentice to join their ranks again on October 3rd 1965 and she was gunning for a position only the guys had.&lt;/p&gt;

&lt;p&gt;I talked to my Mom today about women in software and she was kind enough to share a few of her personal stories with me. For example, unlike most girls her age, she took 4 years of mechanical drawing in High School. And being the only girl in the class, the teacher used to send her to the office on errands so he could chum up and tell dirty jokes to the boys. She also told me that even after successfully completing the apprenticeship program at the Shipyard and being promoted to the design division, that guys would ask her out just to test if she was a lesbian or not.&lt;/p&gt;

&lt;p&gt;To be honest, it never occurred to me that these and many other things debased her experiences. She told me the hardest thing about being a woman in a male dominated career was that most interactions were polarized. In one group, her male counterparts would be overly helpful. In the other, overly negative or outright trying to sabotage her work. Nothing ever felt &amp;quot;normal&amp;quot;. And I guess that is my biggest take away and source of empathy.&lt;/p&gt;

&lt;h2 id=&quot;my-nerd-mentor&quot;&gt;My Nerd Mentor&lt;/h2&gt;

&lt;p&gt;So despite her troubles, my Mom has and always will be successful. She exposed me and my twin Brother to as many different things as possible. She taught us how to draw, how to build things, and how to believe in ourselves. From skiing to firewalking and everything in between, she wanted us to learn and do. But most of all, her love of computers &lt;a href=&quot;/pages/colophon.html&quot;&gt;affected me the most&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To this day I joke that she loved her computer way too much. I have fond memories of the 1986 Mac Plus getting a front seat in the Dodge Caravan (with a seat belt) while I and my Brother had to ride in the back. Before then, she used to turn the house into a social software copy party and we spent family time notching disks before the guests would arrive.&lt;/p&gt;

&lt;h2 id=&quot;thanks-mom&quot;&gt;Thanks Mom!&lt;/h2&gt;

&lt;p&gt;In closing, many thanks to my Mom for allowing me to share her story with you all. I am forever grateful to her teaching me that I can do anything I want and exposing me to computers and many other things. Maybe this is not uncommon? Maybe many more male software developers owe many things to a strong matriarchal influence? That would be really neat and I&amp;#39;d love to hear your story about it. Thanks for reading mine.&lt;/p&gt;
</description>
        <pubDate>Sat, 15 Mar 2014 00:00:00 -0400</pubDate>
        <link>/2014/03/15/mom/</link>
        <guid isPermaLink="true">/2014/03/15/mom/</guid>
      </item>
    
      <item>
        <title>Instrumenting Your Code With ActiveSupport Notifications</title>
        <description>&lt;p&gt;&lt;span class=&quot;&quot;&gt;
  &lt;img src=&quot;/assets/asn_log_lady.jpg&quot; alt=&quot;Moving past the supernatural ability to garner information from the log!&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
&lt;/span&gt;
Have you ever wondered how tools like New Relic are able to gain valuable metrics to your Rails application&amp;#39;s internals? Or maybe you are interested in learning how to write your own libraries and gems so they can be instrumented using those same techniques? Once again the answer is to look deep into the Rails source code – and the answer is &lt;a href=&quot;http://apidock.com/rails/ActiveSupport/Notifications&quot;&gt;&lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;&lt;/a&gt;. A simple and powerful instrumentation API for Ruby available in Rails v3.0 and upward.&lt;/p&gt;

&lt;p&gt;Today I want to share a working example of how you might use ActiveSupport::Notifications. Instead of presenting some contrived code, I thought it would be fun to &lt;a href=&quot;http://vimeo.com/17420638#t=27m27s&quot;&gt;freedom-patch&lt;/a&gt; a popular gem so that we can garner supernatural metrics that would have otherwise been lost or hidden deep in our log. For this exercise I have chosen the &lt;a href=&quot;https://github.com/nulayer/subexec&quot;&gt;Subexec&lt;/a&gt; gem. Subexec is a simple library that spawns an external command with an optional timeout parameter. It is used by other gems like &lt;a href=&quot;https://github.com/minimagick/minimagick&quot;&gt;MiniMagick&lt;/a&gt; – a popular minimal replacement for RMagick.&lt;/p&gt;

&lt;h2 id=&quot;building-subexec-notifications&quot;&gt;Building Subexec::Notifications&lt;/h2&gt;

&lt;p&gt;Our goal will be to build a new gem called subexec-notifications that instruments all commands run by the Subexec library. Once completed, third-party subscribers would be able collect these metrics thereby opening up developer/operational insights into how long certain commands were taking and on which server(s).&lt;/p&gt;

&lt;p&gt;Lucky for us, the Subexec gem has one interface, the &lt;code&gt;Subexec#run!&lt;/code&gt; method. So our work is going to be straight forward. All we have to do is &lt;a href=&quot;http://erniemiller.org/2011/02/03/when-to-use-alias_method_chain/&quot;&gt;alias method chain&lt;/a&gt; that instance method and wrap it with some instrumentation. Assuming you are up to speed on this practice, here is our new implementation.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run_with_notifications!&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;payload&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;ss&quot;&gt;sub: &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;ss&quot;&gt;hostname: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gethostname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instrument&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;subexec.run&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;run_without_notifications!&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This small snippet of code exemplifies how simple it is to instrument our code. The Notifications instrument class method takes two arguments, a string for the name and an optional payload hash. The name will be used by subscribers and the payload hash can contain anything you want.&lt;/p&gt;

&lt;p&gt;Since the Subexec instance has tons of valuable information like the commands output, process id, exit status, and the command string itself - I decided to include it with our payload. The host name is provided with the payload to help us aggregate or subdivide our metrics for each server.&lt;/p&gt;

&lt;p&gt;Believe it or not, that pretty much wraps up all that is needed for our new gem&amp;#39;s code. Everything else like tests and gem structure are orthogonal to our learning today. But please, browse the entire &lt;a href=&quot;https://github.com/customink/subexec-notifications&quot;&gt;subexec-notifications&lt;/a&gt; gem if you are interested in how it is put together.&lt;/p&gt;

&lt;h2 id=&quot;choosing-a-metrics-service&quot;&gt;Choosing A Metrics Service&lt;/h2&gt;

&lt;p&gt;So now we have a way to instrument all of our system commands, but how do we collect and view that data? To be honest, your options are incredibly numerous at this point. While learning ActiveSupport::Notifications myself, these two services kept appearing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.datadoghq.com&quot;&gt;Datadog - Monitoring Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://metrics.librato.com&quot;&gt;Librato - Highly Scalable Metrics, Monitoring &amp;amp; Alerts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My examples below will use Librato since I found their service extremely simple to use. I was able to quickly get metrics submitted to them and viewable via their dashboard gauges. Librato also has a very nice presence on Github and some impressive tools for Ruby. Datadog is no slouch in any of these areas either. So please use what best fits your own needs.&lt;/p&gt;

&lt;p&gt;IMPORTANT: The example Rails application code that follows makes direct use of the &lt;a href=&quot;https://github.com/librato/librato-metrics&quot;&gt;librato-metrics&lt;/a&gt; gem. This means that submissions will happen synchronously while your application is running. You would never do this in your Rails application! If you choose to use Librato, please use the &lt;a href=&quot;https://github.com/librato/librato-rails&quot;&gt;librato-rails&lt;/a&gt; gem instead. Metrics are then delivered asynchronously behind the scenes so they won&amp;#39;t affect the performance of your requests. Other possibilities would be to use background jobs or some other worker message queue.&lt;/p&gt;

&lt;h2 id=&quot;subscribing-to-events&quot;&gt;Subscribing To Events&lt;/h2&gt;

&lt;p&gt;Assuming we have a Rails application that makes use of MiniMagick, Subexec or both, all we have to do now is bundle up our new notification gem along with librato-metrics.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In Gemfile&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;subexec-notifications&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;librato-metrics&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we need to subscribe to the &lt;code&gt;subexec.run&lt;/code&gt; events that we instrumented in the subexec-notifications gem. For a Rails application, this is best done in an initializer named after the gem.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In config/initializers/subexec_notifications.rb&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;subscribe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;subexec.run&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Subscribers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SubexecLibrato&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&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;args&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;publishing-metrics&quot;&gt;Publishing Metrics&lt;/h2&gt;

&lt;p&gt;As you can see in the code above, subscribing to an event will yield an array of arguments. Technically, these will be the name of the event, a few timestamps, a unique id, and the payload. Because dealing with individual arguments is not very object-oriented, I always recommend creating an event object using the &lt;code&gt;ActiveSupport::Notifications::Event&lt;/code&gt; class. It consumes these arguments and gives you a clean interface to the &lt;code&gt;duration&lt;/code&gt; of the event, &lt;code&gt;payload&lt;/code&gt;, and more.&lt;/p&gt;

&lt;p&gt;To accomplish this in one place for our publishing code, I created a simple base class for all our subscribers to inherit from. This base class creates our &lt;code&gt;event&lt;/code&gt; object as well as a &lt;code&gt;process&lt;/code&gt; method that subclasses must implement.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In app/models/subscribers/base.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Subscribers&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Base&lt;/span&gt;

    &lt;span class=&quot;kp&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:event&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Notifications&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&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;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;process&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;process&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NotImplementedError&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now to the fun part, sending some metrics to Librato. Below is the full implementation of our &lt;code&gt;SubexecLibrato&lt;/code&gt; event consumer. This creates two different types of metrics. One for each command/binary that was run and the other for the host the commands are run on. Each of these metrics will allow us to build some interesting gauges. The Librato site has a great developer section titled &lt;a href=&quot;http://dev.librato.com/v1/metrics&quot;&gt;What Are Metrics&lt;/a&gt; that can guide you on what type of data you may want to submit.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In app/models/subscribers/subexec_librato.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Subscribers&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SubexecLibrato&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&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;process&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;sub&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;dur&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;duration&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:hostname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;time&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Librato&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;subexec.hosts&#39;&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;measure_time: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;source: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Librato&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;subexec.types&#39;&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;measure_time: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;source: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;viewing-metrics&quot;&gt;Viewing Metrics&lt;/h2&gt;

&lt;p&gt;Here are what each of these metrics look like in Librato. To generate some commands, I wrote a small tests case that did some random MiniMagick commands along with a few &lt;code&gt;echo&lt;/code&gt; and &lt;code&gt;uptime&lt;/code&gt; commands. All of these ran on my local machine.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/asn_metrics_command.png&quot; alt=&quot;Librato - Subexec Commands&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/asn_metrics_host.png&quot; alt=&quot;Librato - Subexec Hosts&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In Closing&lt;/h2&gt;

&lt;p&gt;Hopefully these simple examples we built will help get you excited both about instrumenting your application as well as collecting and viewing those metrics. If you are hungry for more, check out the links in the resources below. You can even dig deep into the Rails source to see where and how it uses ActiveSupport::Notifications. Thanks!&lt;/p&gt;

&lt;h2 id=&quot;other-resources&quot;&gt;Other Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://apidock.com/rails/ActiveSupport/Notifications&quot;&gt;APIdock ActiveSupport::Notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://speakerdeck.com/nextmat/digging-deep-with-activesupportnotifications&quot;&gt;Digging Deep with ActiveSupport::Notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/customink/subexec-notifications&quot;&gt;Final Subexec::Notifications Gem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.datadoghq.com&quot;&gt;Datadog - Monitoring Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/DataDog&quot;&gt;Datadog - On Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://metrics.librato.com&quot;&gt;Librato - Highly Scalable Metrics, Monitoring &amp;amp; Alerts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/librato&quot;&gt;Librato - On Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 15 Dec 2013 00:00:00 -0500</pubDate>
        <link>/2013/12/15/instrumenting-your-code-with-activesupport-notifications/</link>
        <guid isPermaLink="true">/2013/12/15/instrumenting-your-code-with-activesupport-notifications/</guid>
      </item>
    
      <item>
        <title>Using Dotenv In Rails</title>
        <description>&lt;p&gt;Environment variables as a configuration means are everywhere in Ruby. For instance, ActiveRecord will use the single &lt;code&gt;DATABASE_URL&lt;/code&gt; environment variable for every part of it&amp;#39;s configuration, no database.yml needed! If you are not on board with environment variables, check out &lt;a href=&quot;http://12factor.net/config&quot;&gt;The Twelve-Factor App&lt;/a&gt; for configuration. This is exactly how good software platforms like &lt;a href=&quot;https://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; work, all through environment variables.&lt;/p&gt;

&lt;p&gt;But using environment variables in a Rails application can be tricky. During local development, you may not want to set everything in your Bash or ZSH profile. Perhaps you want per project settings. And then there is the trouble of using different environment variables when running your tests. Enter the &lt;a href=&quot;https://github.com/bkeepers/dotenv&quot;&gt;Dotenv&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;In my examples below of how to integrate Dotenv, I will be using @ecbypi&amp;#39;s fork until this &lt;a href=&quot;https://github.com/bkeepers/dotenv/pull/61&quot;&gt;pull request for overloading environment variables&lt;/a&gt; is accepted. This pull request is key to overriding development or local settings for our Rails test environment. If you like how these examples look below, weigh in on that pull request and lobby for a fresh hot Dotenv release.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s get started. First, let&amp;#39;s add the gem to your Rails project&amp;#39;s Gemfile.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In Gemfile&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;dotenv&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;github: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;ecbypi/dotenv&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;branch: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;overload-environment-variables&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next up, open your &lt;code&gt;config/application.rb&lt;/code&gt; and add this line right after the require &amp;#39;rails/all&amp;#39; line. This will require the Dotenv gem, then load your own per-developer local settings (if present), then a .env file that matches the current &lt;code&gt;Rails.env&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In config/application.rb&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rails/all&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;dotenv&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.env.local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.env.&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, create individual &lt;code&gt;.env.RAILS_ENV&lt;/code&gt; files with your configurations. YMMV on this one, but the idea is to check all of these in. The &lt;code&gt;.env.development&lt;/code&gt; will hold all the default configurations for a new developer to get up and running quickly. The &lt;code&gt;.env.test&lt;/code&gt; will hold all the configurations for your test runs. Past that, how you handle the production file or not, is left up to you. In my examples below, we are setting the environment variable for the Awesome gem.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ echo &quot;AWESOME_GEM_URL=https://awesome.dev&quot;          &amp;gt; .env.development
$ echo &quot;AWESOME_GEM_URL=https://sandbox.awesome.com&quot;  &amp;gt; .env.test
$ echo &quot;AWESOME_GEM_URL=https://awesome.com&quot;          &amp;gt; .env.production
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This covers our bases, but what if a developer wants to override a configuration. They can use good ol&amp;#39; environment variables and get the behavior they expect. Or they create their own &lt;code&gt;.env.local&lt;/code&gt; file and set their configurations there. The benefit of the local file is that your Rails application via the console or the development server (for example Pow) will automatically get the same thing when using the .env.local file. Oh yea, it is a good idea to add the this file to your &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ echo &quot;AWESOME_GEM_URL=https://my-awesome.dev&quot;       &amp;gt; .env.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, one last thing. We need to make sure that our tests do not use any real, development or local environment settings. This is where @ecbypi overload feature comes in handy. I have added this to the top of the Rails &lt;code&gt;test/test_helper.rb&lt;/code&gt; file.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In test/test_helper.rb&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;RAILS_ENV&quot;&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;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;dotenv&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;overload&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.env.test&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Happy environment usage! Have you been solving environment and application configuration in a different way (don&amp;#39;t say YAML), if so, I would love to hear about it!&lt;/p&gt;
</description>
        <pubDate>Thu, 03 Oct 2013 00:00:00 -0400</pubDate>
        <link>/2013/10/03/using-dotenv-in-rails/</link>
        <guid isPermaLink="true">/2013/10/03/using-dotenv-in-rails/</guid>
      </item>
    
      <item>
        <title>Jekyll Tips And Tricks</title>
        <description>&lt;p&gt;&lt;a href=&quot;http://757rb.org?utm_source=metaskills&amp;utm_medium=site&quot;&gt;
  &lt;img class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; src=&quot;/assets/757rb_site.png&quot; alt=&quot;757.RB New Website&quot; /&gt;
&lt;/a&gt;
Last week, our localy Ruby community in Norfolk, VA re-launched the &lt;a href=&quot;http://757rb.org?utm_source=metaskills&amp;amp;utm_medium=site&quot;&gt;757rb.org&lt;/a&gt; website. This was the third static website I have build using &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; and the second since the official v1.0.0 release. It was also completely different than any creative approach I have taken on. Please, go ahead and &lt;a href=&quot;http://757rb.org?utm_source=metaskills&amp;amp;utm_medium=site&quot;&gt;check it out&lt;/a&gt; real quick, I will wait.&lt;/p&gt;

&lt;p&gt;Many things have changed with Jekyll over the years and it is always fun to stay current with the latest technical aspects of the tools we use. So I thought I would put a few of my own techniques out there to see what others think. If you find any of these useful or know of better ways to solve them, let me know.&lt;/p&gt;

&lt;h2 id=&quot;use-task-scripts&quot;&gt;Use Task Scripts&lt;/h2&gt;

&lt;p&gt;I have no idea where I picked this up, but the general idea is to create a &lt;code&gt;tasks&lt;/code&gt; directory that holds a set of useful shell scripts. My Jekyll projects usually contain the following executables.&lt;/p&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  Remember to add the tasks directory to jekyll&#39;s exclude array in your config file(s).
&lt;/aside&gt;

&lt;ul&gt;
&lt;li&gt;jekyll&lt;/li&gt;
&lt;li&gt;jekyll-livereload&lt;/li&gt;
&lt;li&gt;deploy&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/metaskills/6414700&quot;&gt;optipng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/metaskills/6414713&quot;&gt;post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;jekyll&lt;/code&gt; wrapper script is only useful to those projects that need to perform additional steps before or after building the site. Notice the usage of &lt;code&gt;$*&lt;/code&gt; after the jekyll build command. This is akin to Ruby&amp;#39;s reverse splat args. It allows you to send any arguments to your own script that the jekyll command would normally take.&lt;/p&gt;

&lt;p&gt;I will cover &lt;code&gt;jekyll-livereload&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; later in this post. The &lt;a href=&quot;https://gist.github.com/metaskills/6414700&quot;&gt;optipng&lt;/a&gt; script is a useful command line utility that compresses assets. While the &lt;a href=&quot;https://gist.github.com/metaskills/6414713&quot;&gt;post&lt;/a&gt; script allows you to easily create a new post. For example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ ./tasks/post &quot;Jekyll Tips And Tricks&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;development-amp-production-environments&quot;&gt;Development &amp;amp; Production Environments&lt;/h2&gt;

&lt;p&gt;Sometimes you do not want a production feature turned on when developing your site locally. Blogs backed by &lt;a href=&quot;https://disqus.com&quot;&gt;DISQUS&lt;/a&gt; comments would be a great example. Likewise, maybe you want to develop a new feature that you can see during local development only to be enabled at a later time. Thanks to v1.0 of Jekyll and up, this is easy to do with different configuration files.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In _config.yml&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;production: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;timezone: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;America/New_York&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# In _config_production.yml&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;production: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;timezone: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;America/New_York&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we have the default &lt;code&gt;_config.yml&lt;/code&gt; acting as our default development configuration. It sets the production site variable to false while the &lt;code&gt;_config_production.yml&lt;/code&gt; sets it to true. Remember the &lt;code&gt;deploy&lt;/code&gt; task I mentioned above? This is a great place to pass down the &lt;code&gt;--config&lt;/code&gt; argument to your own jekyll task. Here is a partial example of a deploy task.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; -e

./tasks/jekyll --config _config_production.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can write code like the following examples in your layouts or includes. Jekyll will automatically take any additional top level configurations and turn them into properties on the &lt;code&gt;site&lt;/code&gt; object.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Only show DISQUS comments in production. --&amp;gt;&lt;/span&gt;
{% if site.production %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;...&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
{% endif %}

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Developing a local only feature not ready for production. --&amp;gt;&lt;/span&gt;
{% unless site.production %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;promotion&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;header&amp;gt;&lt;/span&gt;T-SHIRT FUNDRAISER!&lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  ...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
{% endunless %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;use-the-asset-pipeline&quot;&gt;Use The Asset Pipeline&lt;/h2&gt;

&lt;p&gt;If you have written Jekyll sites prior to the v1.0 release you have likely concocted up your own scripts to use &lt;a href=&quot;http://coffeescript.org&quot;&gt;CoffeeScript&lt;/a&gt;, &lt;a href=&quot;http://sass-lang.com&quot;&gt;Sass&lt;/a&gt; or both. Love it or hate it, as Ruby developers we got it good with Sprockets.&lt;/p&gt;

&lt;p&gt;But now Jekyll has the power of the asset pipeline too. Just install the &lt;a href=&quot;https://github.com/ixti/jekyll-assets&quot;&gt;jekyll-assets&lt;/a&gt; gem. Here are a few tips to get you up and running faster.&lt;/p&gt;

&lt;p&gt;First, remember that Sprockets is built on top of a gem named Tilt which is a generic interface to multiple template engines. Installing tilt does not install template engines, so make sure to install the ones you want to work with by explicitly declaring them in your Gemfile.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jekyll-assets&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;coffee-script&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;compass&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sass&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uglifier&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I found the default configuration for jekyll-assets very confusing. It mimicked a production environment Rails setting. All the files used the digest as part of the file name and compression was on by default. This made it really hard to debug. So to make jekyll-assets more like Rails defaults. Use these configurations for each jekyll environment.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In _config.yml&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;assets:
  js_compressor:
  css_compressor:
  cache:
  cachebust: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# In _config_production.yml&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;assets:
  js_compressor: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uglifier&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;css_compressor: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sass&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cache: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cachebust: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;pow-it-up&quot;&gt;Pow It Up&lt;/h2&gt;

&lt;p&gt;Sure the new jekyll release has a &lt;code&gt;serve&lt;/code&gt; option to boot up a web server. But like good software developers, we should be too lazy for such things. If you develop on a Mac and use &lt;a href=&quot;http://pow.cx&quot;&gt;Pow&lt;/a&gt; already for your Rails applications, why not just hook it up to serve your Jekyll site(s) too. Here are the steps.&lt;/p&gt;

&lt;p&gt;First, add both rack and rack-rewrite to your &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rack&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rack-rewrite&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now create a &lt;code&gt;config.ru&lt;/code&gt; file at the root of your project with the following contents.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rack-rewrite&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rack/rewrite&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rewrite&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;r301&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;%r{^([^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;]*[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\/&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;])$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;$1/&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;r301&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;%r{^(.*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\/&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;)$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;$1index.html&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, sym link the &lt;code&gt;_site&lt;/code&gt; directory of your Jekyll project to the &lt;code&gt;public&lt;/code&gt;. Then symlink your Jekyll project directory to Pow as you normally would do any Rails or Rack app.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ ln -s _site public
$ cd ~/.pow
$ ln -s /path/to/myjekyllapp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can now access your generated site at &lt;code&gt;http://myjekyllapp.dev&lt;/code&gt; via Pow.&lt;/p&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  Remember to add both config.ru and the public directory to jekyll&#39;s exclude array in your config file(s).
&lt;/aside&gt;

&lt;h2 id=&quot;live-reloads&quot;&gt;Live Reloads&lt;/h2&gt;

&lt;p&gt;I love &lt;a href=&quot;http://livereload.com&quot;&gt;LiveReload&lt;/a&gt; and have purchased the native OS X client for $9 from the &lt;a href=&quot;http://itunes.apple.com/us/app/livereload/id482898991?mt=12&quot;&gt;Mac App Store&lt;/a&gt;. Personally, I could never get the guard-livereload gem working and just opted for the GUI client. So this tip will only focus on using the native Mac app.&lt;/p&gt;

&lt;p&gt;It solves a few problems. First, it overcomes LiveReload&amp;#39;s lack of &lt;a href=&quot;https://github.com/sstephenson/rbenv&quot;&gt;rbenv&lt;/a&gt; support. It also assumes that your jekyll site is rather large and takes several seconds to build. Finally, assuming that you are working on your latest post and all you need to do is build a single page over and over again.&lt;/p&gt;

&lt;p&gt;Setup LiveReload like you normally would by dragging your project&amp;#39;s folder to their setup window. From here we want to configure your jekyll project to &amp;quot;Run a custom command...&amp;quot;. Click on &amp;quot;Options...&amp;quot; and add the full path to your &lt;code&gt;jekyll-livereload&lt;/code&gt; task script.&lt;/p&gt;

&lt;div&gt;
  &lt;img src=&quot;/assets/livereload_custom_command1.png&quot; alt=&quot;LiveReload Run Custom Command&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;
  &lt;img src=&quot;/assets/livereload_custom_command2.png&quot; alt=&quot;LiveReload Run Custom Command&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/livereload_exclude.png&quot; alt=&quot;LiveReload Exclude Directories&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
Also, make sure to exclude any directories that you do not want LiveReload to monitor. One critical folder is the jekyll &lt;code&gt;_site&lt;/code&gt; directory. Watching this directly usually results in a indefinite LiveReload loop. Not good.&lt;/p&gt;

&lt;p&gt;Your mileage may vary, but here is what I have found works for me in my &lt;code&gt;jekyll-livereload&lt;/code&gt; script. This forces the LiveReload sub shell script to load up rbenv again. It then uses the &lt;code&gt;--limit_posts&lt;/code&gt; argument to build just the last post. I have found this quickly refreshes the browser page automatically for me while working on my latest Jekyll post in markdown.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; -e

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LANG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;en_US.UTF-8&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.rbenv/shims:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.rbenv/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.rbenv/plugins/ruby-build/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;rbenv init -&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

jekyll build --limit_posts 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;aside class=&quot;ms-Flash&quot;&gt;
  Remember turn off LiveReload while you are deploying!
&lt;/aside&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://757rb.org?utm_source=metaskills&amp;amp;utm_medium=site&quot;&gt;757RB.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll - Simple, blog-aware, static sites.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ixti/jekyll-assets&quot;&gt;jekyll-assets - Asset pipeline for Jekyll.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pow.cx&quot;&gt;Pow - A zero-config Rack server for OS X.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://livereload.com&quot;&gt;LiveReload&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 02 Sep 2013 00:00:00 -0400</pubDate>
        <link>/2013/09/02/jekyll-tips-and-tricks/</link>
        <guid isPermaLink="true">/2013/09/02/jekyll-tips-and-tricks/</guid>
      </item>
    
      <item>
        <title>In Loving Memory of Kenneth Earle Collins</title>
        <description>&lt;h4 id=&quot;kenneth-earle-collins-66-of-chesapeake-virginia-passed-away-january-5th-2013&quot;&gt;Kenneth Earle Collins, 66, of Chesapeake, Virginia, passed away January 5th, 2013.&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-sheriff.jpg&quot; alt=&quot;Kenneth Earle Collins - Master Deputy Sheriff&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
My father, known to his friends and family as Kenny, was born in Logan, West Virginia and was the son of the late Edgar and Frances Collins. He was a retired Master Deputy with the Chesapeake Sheriff&amp;#39;s Department. Kenny is survived by his beloved wife of 7 years, Lois V. Collins; a sister, Lanna DeVites and husband John of Zuni, VA; 4 sons, Benjamin M. Collins and fiancée Samantha of Williamsburg, VA, Kenneth Collins and wife Kelly of Portsmouth, VA, Brian Seabold and wife Kelly of Chesapeake, VA, and George Seabold and wife Terri of Elizabeth City, North Carolina; a daughter, Lisa Berger and husband Keith Berger of VA Beach, VA; and 6 grandchildren, Marcus, Zachery, Grayson, Bryson, Jacob, and Trey.&lt;/p&gt;

&lt;h2 id=&quot;service&quot;&gt;Service&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-bootcamp-fort-jackson.jpg&quot; alt=&quot;Kenneth Earle Collins - Fort Jackson, South Carolina&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
I am not sure when my father&amp;#39;s parents moved from West Virginia, but my Dad did grow up here locally in the Hodges Manor section of Portsmouth, Virginia - right next to Elizabeth Manor Golf &amp;amp; Country Club. Dad graduated from Portsmouth High School with the class of 1965. He was drafted into the US Army and trained at Fort Jackson, South Carolina.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-army-vietnam.jpg&quot; alt=&quot;Kenneth Earle Collins - Vietnam&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
Dad, served two years in Vietnam from 1966 to 1968. Like most veterans, he never talked about his service. After he passed, I decided to use DD 214 to order replacement decorations. Thankfully, the Medals Of America company put in a rush order for me so we could decorate his uniform for the memorial service. He also saved his short-timers stick and jacket with hand sew patches and lettering. The text on the back of the jacket says &amp;quot;I am certain to go to Heaven because I spent my time in Hell.&amp;quot;&lt;/p&gt;

&lt;p&gt;Below is a list of his decorations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;National Defense Service Medal&lt;/li&gt;
&lt;li&gt;Vietnam Service Medal&lt;/li&gt;
&lt;li&gt;Republic of Vietnam Campaign Medal w/60 Device&lt;/li&gt;
&lt;li&gt;Good Conduct Medal&lt;/li&gt;
&lt;li&gt;Expert Badge (M-14 Rifle)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shortly after serving in the Army, my Dad joined the Portsmouth Police Department where he served till mid 1974, a few years after I was born. During his time there he became a Detective, State Arson investigator, and served on the bomb squad. His detective work focused on the narcotics division and he served much of that time undercover. &lt;img src=&quot;/assets/dad-point-elizabeth-home.jpg&quot; alt=&quot;Kenneth Earle Collins - With Ken and Ben At Our New Point Elizabeth Home&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;I have numerous family photos with my Dad sporting pot leafs on his shirt or a nice Budweiser cap. After he passed, I finally found a copy of his resignation letter with the force where he quoted salary and the need to be more of a &amp;quot;family man&amp;quot;.&lt;/p&gt;

&lt;p&gt;After resigning from the force, Dad started a private investigation company with a long time friend, Ken Riddleberger. It was aptly named Double K Incorporated and they primarily handled arson and insurance fraud cases. Dad did this till the late 80&amp;#39;s. I really believe he thought of himself as Magnum PI. Often he would wake up in the morning and drive around calling out on the CB Radio till his partner Ken Riddleberger woke up and did the same. They would promptly head towards a local Texaco station where they would play Ms. PacMan while they discussed their case load.&lt;/p&gt;

&lt;p&gt;Because investigation work often required a lot of travel, Dad eventually got a desk job as head of security at the Portsmouth Naval Base and eventually came back to law enforcement with the Chesapeake Sheriff&amp;#39;s office. I am very proud of my father&amp;#39;s service and work. Below are some shadow boxes I made to commemorate his service.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-shadow-boxes.png&quot; alt=&quot;Kenneth Earle Collins - Shadow Boxes&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;lifestyle&quot;&gt;Lifestyle&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-golfing-with-ben.jpg&quot; alt=&quot;Kenneth Earle Collins - Golfing With Ben Collins&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
Dad was an avid golfer! I mean really, he played every spare moment he could and passed the love of the game to both my brother and myself. We owned our first set of clubs at the age of 9 after Dad won a tournament at Bide-A-Wee golf course. Dad loved the game so much, the family opened up a small golf shop in Chesapeake called Links Golf Shop. Ben and I even attended the GolfWorks school for club manufacture and repair in Newark, OH.&lt;/p&gt;

&lt;p&gt;Golf was not our only sport. For some reason Dad made me and my brother try our luck with many others. We played basketball, football, and baseball. Most years we played baseball and even though we both sucked and never had more than a 0 batting average, Dad was there for us and helped coach all of our teams.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-with-lois.jpg&quot; alt=&quot;Kenneth Earle Collins - With Wife Lois Collins At My Wedding&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
After getting divorced in 1991, my Dad eventually remarried in July 2006 to Lois V. Collins. Dad and Lois met at a Parents Without Partners (PWP) group and dated for some time. Lois is a real class act and took care of my Dad during his last few years while battling lung cancer. I can not count the number of times she would drive them both to his favorite destinations or other out of state trips. Lois will always be a Collins and is family to me. I love her dearly.&lt;/p&gt;

&lt;h2 id=&quot;stories&quot;&gt;Stories&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/dad-and-linda.jpg&quot; alt=&quot;Kenneth Earle Collins - With My Mom, Linda Collins&quot; class=&quot;ms-Img ms-Img--quarter ms-Img--fancy&quot; /&gt;
My Mom, Linda Campbell - now remarried, recently told this story to my Brother and myself and I hope she does not mind sharing it here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your Dad and I must have been in junior high school, you know the age where you are scared and everything embarrasses you and you know if you do anything, it will be wrong? I remember feeling especially confident though because I had on an ironed white shirt and a brand new pair of Bermuda shorts that my mom had sewn for me. I was Sandra Dee and – well, we didn&amp;#39;t really know each other or hang out at the time but we were with a bunch of neighborhood kids all hanging around on a hot summer day with nothing to do.&lt;/p&gt;

&lt;p&gt;As it was back then, kids didn&amp;#39;t hang out inside so we were all standing and sitting on a friends chain link fence and being shy about the opposite sex. I was one of the kids on the fence, don&amp;#39;t know why, because the wire went above the top pipe bar and was not very comfortable at all to sit on. The kids generally agree to go beg something cold to drink from one of the mothers – mothers were always home back then, just like June Cleaver. So, I jumped down from the fence.&lt;/p&gt;

&lt;p&gt;Uh-oh, my feet hit the ground, but most of my brand new Bermuda shorts were still attached to the wicked fence. Standing there in my white cotton undies and very little of my shorts, I wanted to crawl under the fence. Everyone was laughing and making fun – everyone but your Dad. He calmly went to the clothes line and pulled down an ironing board cover that had dried in the sunlight and approached me with his head turned sideways, and his arms spread wide, holding the ironing board cover for me like a mother holding a towel for a wet toddler emerging from the bathtub.&lt;/p&gt;

&lt;p&gt;We didn&amp;#39;t cross paths again until after graduation, when he worked at James&amp;#39; Texaco. I had just gotten my new spiffy, metallic blue Corvair with 4 in the floor and was gassing up at his station, trying to look prim and proper. He never mentioned the shorts eating fence until later but when he asked me on a date, I remembered his gallantry from many years earlier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--
* Made pottery (as trays) in 1st grade and he kept all of them.
* Leaf report at coleman&#39;s nursury.
* Gather up other stories.
--&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In Closing&lt;/h2&gt;

&lt;p&gt;The Collins family has always been close, despite long durations without seeing one another. Often times I went weeks without checking in on my immediate family. The great part about family is that you can always pick up right where you left off. Time has no meaning. But with my Dad&amp;#39;s passing, I will really miss that next time when I want to call and talk to him.&lt;/p&gt;

&lt;h2 id=&quot;other-links&quot;&gt;Other Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hollomon-brown.com/obituary/Kenneth-Earle-Collins/Chesapeake-VA/1158699&quot;&gt;Hollomon-Brown Obituary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.medalsofamerica.com&quot;&gt;Medals Of America&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 05 Jan 2013 00:00:00 -0500</pubDate>
        <link>/2013/01/05/in-loving-memory-kenneth-earle-collins/</link>
        <guid isPermaLink="true">/2013/01/05/in-loving-memory-kenneth-earle-collins/</guid>
      </item>
    
      <item>
        <title>HolyGrailHarness</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  The latest README for HolyGrailHarness project will always be on the &lt;a href=&quot;http://github.com/metaskills/holy_grail_harness&quot;&gt;Github project&lt;/a&gt; page.
&lt;/aside&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.github.com/metaskills/holy_grail_harness/master/app/assets/images/holy_grail_harness.png&quot; class=&quot;ms-Img ms-Img--responsive&quot;/&gt;&lt;/p&gt;

&lt;p&gt;A curated Rails application prototype that focuses on simple test patterns for Ruby &amp;amp; JavaScript!&lt;/p&gt;

&lt;p&gt;Unlike normal &lt;a href=&quot;http://guides.rubyonrails.org/rails_application_templates.html&quot;&gt;Rails Application Templates&lt;/a&gt; or more modern Rails application generators like &lt;a href=&quot;http://railsapps.github.com/rails-composer/&quot;&gt;Rails Composer&lt;/a&gt;, the HolyGrailHarness is a basic Rails application that can be considered a prototype and customized via a simple setup script. It is also somewhat opinionated in that it promotes simple and powerful testing choices and focuses on using Ruby 1.9 and up, MiniTest::Spec, Capybara, Poltergeist/PhantomJS, and Konacha. More details on each component and what HolyGrailHarness provides are below.&lt;/p&gt;

&lt;p&gt;The HolyGrailHarness is perfect for any of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bootstrapping your next Rails application.&lt;/li&gt;
&lt;li&gt;Learning and promoting MiniTest::Spec&lt;/li&gt;
&lt;li&gt;Modern JavaScript testing setups.&lt;/li&gt;
&lt;li&gt;Teaching Rails and/or JavaScript at your next meetup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/archive/master.zip&quot;&gt;Download&lt;/a&gt; the project.&lt;/li&gt;
&lt;li&gt;Now from the root of &amp;quot;holy_grail_harness&amp;quot; directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This code will be highlighted&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make sure to replace &lt;code&gt;my_app_name&lt;/code&gt; above with the name of your new Rails application. The setup script has a few options, but the end result will be a new Rails application all ready to go. &lt;strong&gt;So why not a normal Rails application template?&lt;/strong&gt; Although, Rails application templates provide a really nice feature set. It was much easier to bootstrap a new Rails application using this prototype method. The end result is a cleaner Gemfile and application setup that can be vetted and tested from within HolyGrailHarness itself.&lt;/p&gt;

&lt;p&gt;The script will rename your directory and prompt you to &lt;code&gt;cd&lt;/code&gt; to that directory. Once you do that, run &lt;code&gt;rake test:all&lt;/code&gt; to see that everything is working.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ../my_app_name
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;rake &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;:all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;rails-3&quot;&gt;Rails 3&lt;/h2&gt;

&lt;p&gt;This application prototype will focus on the latest Rails version. At this time, the bundle is locked down to v3.2.9. As Rails updates and is compatible with each component, so will this prototype application be updated. The bundle includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/evrone/quiet_assets&quot;&gt;QuietAssets&lt;/a&gt; gem for silent pipeline logging.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/macournoyer/thin/&quot;&gt;Thin&lt;/a&gt; webserver. Primarily to be automatically used by Konacha but also good for development if you are not using something like &lt;a href=&quot;http://pow.cx&quot;&gt;Pow&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;

&lt;h3 id=&quot;minitest-spec-all-the-way-across-the-sky&quot;&gt;MiniTest::Spec All The Way Across The Sky!&lt;/h3&gt;

&lt;p&gt;Don&amp;#39;t wait for Rails 4 to use MiniTest::Spec! This application is using the &lt;a href=&quot;https://github.com/metaskills/minitest-spec-rails&quot;&gt;minitest-spec-rails&lt;/a&gt; gem which forces &lt;code&gt;ActiveSupport::TestCase&lt;/code&gt; to subclass &lt;code&gt;MiniTest::Spec&lt;/code&gt;. This means that you can start using the MiniTest&amp;#39;s Spec or Unit structure and assertions directly within the familiar Rails unit, functional, or integration directories. For full details, check out the &lt;a href=&quot;https://github.com/metaskills/minitest-spec-rails&quot;&gt;minitest-spec-rails&lt;/a&gt; documentation or some of the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/test/functional/application_controller_test.rb&quot;&gt;test shims&lt;/a&gt; within HolyGrailHarness. For example, a &lt;code&gt;test/unit/user_test.rb&lt;/code&gt; might look like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test_helper&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:admin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:admin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;must respond true to #admin? for administrators only&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;must_be&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:admin?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wont_be&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:admin?&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;capybara-integration-tests-with-poltergeist-using-phantomjs&quot;&gt;Capybara Integration Tests With Poltergeist Using PhantomJS&lt;/h3&gt;

&lt;p&gt;You don&amp;#39;t need Cucumber to write good integration tests. Instead use the basic &lt;a href=&quot;https://github.com/jnicklas/capybara#the-dsl&quot;&gt;Capybara DSL&lt;/a&gt; directly within a Rails integration tests with the most bad ass driver available, &lt;a href=&quot;https://github.com/jonleighton/poltergeist&quot;&gt;Poltergeist&lt;/a&gt;, which is built on top of &lt;a href=&quot;http://phantomjs.org&quot;&gt;PhantomJS&lt;/a&gt;. Never again worry about installing Qt so you can compile capybara-webkit, just go download a &lt;a href=&quot;http://phantomjs.org/download.html&quot;&gt;pre-compiled PhantomJS binary&lt;/a&gt; for your specific platform and enjoy 20% faster integration test runs vs capybara-webkit.&lt;/p&gt;

&lt;p&gt;Integration tests are still within the &lt;code&gt;ActionDispatch::IntegrationTest&lt;/code&gt; class and as promised, MiniTest::Spec is available here too. Each test file needs to require the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/test/test_helper_integration.rb&quot;&gt;test_helper_integration&lt;/a&gt; which provides the following base features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets page size to that of a 13&amp;quot; MacBook Air.&lt;/li&gt;
&lt;li&gt;Resets Capybara sessions after each test.&lt;/li&gt;
&lt;li&gt;Provides a &lt;code&gt;#save_and_open_page&lt;/code&gt;, or &lt;code&gt;#page!&lt;/code&gt; for short, screen shot method.&lt;/li&gt;
&lt;li&gt;Ensures a single ActiveRecord DB connection for transactional test runs.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;#execjs&lt;/code&gt; helper for bridging Ruby and the JavaScript under test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HolyGrailHarness comes with a integration test example in the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/test/integration/application_test.rb&quot;&gt;test/integration/application_test.rb&lt;/a&gt; file. An integration test might look something like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test_helper_integration&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ApplicationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionDispatch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;IntegrationTest&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;h1&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;renders&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;must_be&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:present?&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;konacha-javascript-tests-using-phantomjs&quot;&gt;Konacha JavaScript Tests Using PhantomJS&lt;/h3&gt;

&lt;p&gt;Move over Jasmine(rice), &lt;a href=&quot;https://github.com/jfirebaugh/konacha&quot;&gt;Konacha&lt;/a&gt; is the way to test your JavaScript now. Konacha is a Rails engine that allows you to test your JavaScript with the &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; test framework and &lt;a href=&quot;http://chaijs.com&quot;&gt;Chai&lt;/a&gt; assertion library. Konacha&amp;#39;s killer feature is a sandboxed &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; for each test spec to run within as well as full Rails asset pipeline integration. The HolyGrailHarness does all the work to get your Konacha &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/tree/master/spec/javascripts&quot;&gt;&lt;code&gt;spec/javascripts&lt;/code&gt;&lt;/a&gt; directory all setup and ready to go. Highlights include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/config/initializers/konacha.rb&quot;&gt;initializer&lt;/a&gt; that sets up Poltergeist as the Capybara driver.&lt;/li&gt;
&lt;li&gt;A directory structure for model, view, and controller specs.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/spec/javascripts/spec_helper.js.coffee&quot;&gt;&lt;code&gt;spec_helper.js.coffee&lt;/code&gt;&lt;/a&gt; for your specs to require. Provides global setup, configurations and vendor requires.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HolyGrailHarness also has a &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/tree/master/spec/javascripts/spec_helper&quot;&gt;&lt;code&gt;spec/javascripts/spec_helper&lt;/code&gt;&lt;/a&gt; directory meant for helpers and extensions that should be available to all specs. We have included a &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/spec/javascripts/spec_helper/fixtures.js.coffee&quot;&gt;&lt;code&gt;fixtures.js.coffee&lt;/code&gt;&lt;/a&gt; file that demonstrates how to setup JSON data fixtures for use from anything to stubbing requests to instantiating new model objects. We also have a &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/spec/javascripts/spec_helper/helpers.js.coffee&quot;&gt;&lt;code&gt;helpers.js.coffee&lt;/code&gt;&lt;/a&gt; file that exposes a few top level functions that make debugging your JavaScript easy. Below are the vendored JavaScript libraries that are required by the &lt;code&gt;spec_helper&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sinonjs.org&quot;&gt;Sinon.JS&lt;/a&gt; - For spies, stubs, faking time, etc.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/appendto/jquery-mockjax&quot;&gt;jQuery Mockjax&lt;/a&gt; - Best way to mock jQuery&amp;#39;s AJAX functions.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/chaijs/chai-jquery&quot;&gt;Chai jQuery&lt;/a&gt; - Chai assertions for jQuery.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/NV/jsDump&quot;&gt;jsDump&lt;/a&gt; - Used by the &lt;code&gt;myLog()&lt;/code&gt; helper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because your CI system should run all your tests, the HolyGrailHarness has added a Rake task to the test namespace that runs the default rails test task (units, functional, integrations) then your Konacha tests.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;:all     &lt;span class=&quot;c&quot;&gt;# Runs all Rails tests, then Konacha tests.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;guard&quot;&gt;Guard&lt;/h3&gt;

&lt;p&gt;TDD in style and run your tests when you hit save! Both &lt;a href=&quot;https://github.com/guard/guard-minitest&quot;&gt;guard-minitest&lt;/a&gt; and &lt;a href=&quot;https://github.com/alexgb/guard-konacha&quot;&gt;guard-konacha&lt;/a&gt; are bundled and ready to go. A basic &lt;code&gt;Guardfile&lt;/code&gt; is already setup too. Unlike most, this one is split into two groups &lt;code&gt;:ruby&lt;/code&gt; or &lt;code&gt;:js&lt;/code&gt;. This lets you focus on either everything or a specific language for your tests.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;guard             &lt;span class=&quot;c&quot;&gt;# Monitor both Ruby and JavaScript tests.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;guard -g ruby     &lt;span class=&quot;c&quot;&gt;# Monitor Ruby tests.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;guard -g js       &lt;span class=&quot;c&quot;&gt;# Monitor JavaScript tests.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Guardfile assumes you are running OS X and wish to use the Ruby GNTP (Growl Notification Transport Protocol). If this is not the case, consult the Guard documentation on different &lt;a href=&quot;https://github.com/guard/guard#system-notifications&quot;&gt;system notification&lt;/a&gt; alternatives.&lt;/p&gt;

&lt;h3 id=&quot;factories-and-fixtures&quot;&gt;Factories And Fixtures&lt;/h3&gt;

&lt;p&gt;ActiveRecord YAML fixtures suck, but so do slow tests that rely on an empty database with excessive setups based on factories. The answer? Take advantage of the best each has to offer. Use factories to populate fixtures into the test database while leveraging database transactions during your test runs. The end result is a known factory story with the ability to create more test data as needed using the same factories. Allowing factories to properly hook into model logic means no more decomposing business logic into YAML text files. How?&lt;/p&gt;

&lt;p&gt;The HolyGrailHarness bundles the &lt;a href=&quot;https://github.com/metaskills/named_seeds&quot;&gt;named_seeds&lt;/a&gt; gem along with the &lt;a href=&quot;https://github.com/thoughtbot/factory_girl&quot;&gt;factory_girl&lt;/a&gt; gem. The NamedSeeds library checks for the existence of a &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/db/test/seeds.rb&quot;&gt;&lt;code&gt;db/test/seeds.rb&lt;/code&gt;&lt;/a&gt; file and if present, loads that file. Just like Rails&amp;#39; own &lt;code&gt;db/seeds.rb&lt;/code&gt; anything in this file goes. The only difference is that this seed file is populated right before you tests are run so they persist between transactions. You also get the benefit of using this same seed data in development as part of the normal Rails &lt;code&gt;db:setup&lt;/code&gt; process. Read the &lt;a href=&quot;https://github.com/metaskills/named_seeds#namedseeds&quot;&gt;full documentationn&lt;/a&gt; on their site on how to use it. Below is a brief example.&lt;/p&gt;

&lt;p&gt;Create factories in the &lt;code&gt;test/factories&lt;/code&gt; directory. Note, factories are best when they make &lt;code&gt;valid garbage™&lt;/code&gt;, so the HolyGrailHarness also requires the &lt;a href=&quot;https://github.com/sevenwire/forgery&quot;&gt;forgery&lt;/a&gt; gem to help with that.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In test/factories/user_factory.rb&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;FactoryGirl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;factory&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Forgery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Forgery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last_name&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Forgery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;   &lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When making seed data, be explicit with your attributes that may be forged in the factory, database seeds should be consistent and have meaningful attributes. In this example we are creating an admin user. Note too how we are using &lt;code&gt;NamedSeeds.identify&lt;/code&gt; which mimics AcctiveRecord&amp;#39;s fixture identity. This gives us a handle to the fixture within our tests. We also create the &lt;code&gt;@admin&lt;/code&gt; instance variable because we might want to use that user later on in the fixture story.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In db/test/seeds.rb&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;factory_girl&#39;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;FactoryGirl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_definitions&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FactoryGirl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Syntax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Methods&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@admin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;id: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NamedSeeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;identify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:admin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                       &lt;span class=&quot;ss&quot;&gt;first_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Admin&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;last_name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;User&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;email: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;admin@test.com&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lastly, in your &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/test/test_helper.rb&quot;&gt;&lt;code&gt;test/test_helper.rb&lt;/code&gt;&lt;/a&gt; file, declare that you have a named seed to the users model. This will allow your tests to act just like those with ActiveRecord fixtures and use the &lt;code&gt;users(:admin)&lt;/code&gt; helper to get to that seeded fixture.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In test/test_helper.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;named_seeds&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;mvc-javascript&quot;&gt;MVC JavaScript&lt;/h2&gt;

&lt;p&gt;The HolyGrailHarness wants you to use some type MV* structure for your JavaScript. The setup script supports &lt;a href=&quot;http://spinejs.com&quot;&gt;Spine.js&lt;/a&gt; as an option, however you can decline and all traces of Spine.js will be removed. If so, the following features will still remain.&lt;/p&gt;

&lt;p&gt;A single JavaScript &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/javascripts/holy_grail_harness/lib/namespaces.js.coffee&quot;&gt;namespace&lt;/a&gt; on the window object. This namespace creates a model, view, controller object structure that direly matches to the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/tree/master/app/assets/javascripts/holy_grail_harness&quot;&gt;&lt;code&gt;app/assets/javascripts/#{my_app_name}/(model|view|controller)&lt;/code&gt;&lt;/a&gt; directory structure within the Rails asset pipeline. This JavaScript namespace and matching directories will be changed to your new application name as part of the setup task. Here is an example of a User model whose corresponding file would be found in the &lt;code&gt;app/assets/javascripts/my_app_name/models/user.js.coffee&lt;/code&gt; file.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;MyAppName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;configure&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;User&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;id&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;email&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The main &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/javascripts/application.js&quot;&gt;&lt;code&gt;application.js&lt;/code&gt;&lt;/a&gt; file requires all vendor frameworks, then the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/javascripts/holy_grail_harness/index.js.coffee&quot;&gt;&lt;code&gt;index.js.coffee&lt;/code&gt;&lt;/a&gt; within your application name directory. Use this file to boot your JavaScript application and/or setup your root view controller.&lt;/p&gt;

&lt;p&gt;Also included is the &lt;a href=&quot;https://github.com/nathansobo/space-pen&quot;&gt;SpacePen&lt;/a&gt; view framework. SpacePen is a powerful and minimalist client-side view framework authored in CoffeeScript. It is actually a jQuery subclass which makes your views really easy to traverse and respond to controller events. Read my &lt;a href=&quot;http://metaskills.net/2012/05/22/view-controller-patterns-with-spine-js-and-spacepen/&quot;&gt;&lt;em&gt;View Controller Patterns With Spine.js &amp;amp; SpacePen&lt;/em&gt;&lt;/a&gt; article to learn why views should not be dumb and how you can take advantage of SpacePen no matter what JavaScript MV* framework you use.&lt;/p&gt;

&lt;h3 id=&quot;with-spine-js&quot;&gt;With Spine.js&lt;/h3&gt;

&lt;p&gt;If you choose to use Spine.js as your JavaScript MVC structure, the setup script will create a git submodule to the Spine repository to the &lt;code&gt;vendor/assets/javascripts/spine&lt;/code&gt; directory. This allows your project to use the the source CoffeeScript files, which makes for a wonderful &lt;a href=&quot;http://metaskills.net/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;learning experience&lt;/a&gt; to both Spine.js and idomatic CoffeeScript.&lt;/p&gt;

&lt;p&gt;By default the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/javascripts/holy_grail_harness/index.js.coffee&quot;&gt;&lt;code&gt;index.js.coffee&lt;/code&gt;&lt;/a&gt; will require all Spine components. This includes manager (stacks), ajax, route, and relation. Remove anything that you do not need. This file also defines the root view controller along with a &lt;code&gt;MyAppName.App.Index.init()&lt;/code&gt; class level initialization function. This is called in the main &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/views/layouts/application.html.erb&quot;&gt;&lt;code&gt;application.html.erb&lt;/code&gt;&lt;/a&gt; layout file for you too. Likewise, the application init is done in the Mocha before filters mentioned above in both the &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/spec/javascripts/spec_helper.js.coffee&quot;&gt;&lt;code&gt;spec_helper.js.coffee&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/spec/javascripts/spec_helper/fixtures.js.coffee&quot;&gt;&lt;code&gt;fixtures.js.coffee&lt;/code&gt;&lt;/a&gt; files. If you examine these files closely, you will see how they make use of Mocha&amp;#39;s &lt;code&gt;done()&lt;/code&gt; callback so that you can cleanly abstract AJAX mocks and anything else related to your JavaScript application&amp;#39;s boot process. Here is an example of how you might setup your &lt;code&gt;initApplication()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;initApplication&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;nx&quot;&gt;callback&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;nx&quot;&gt;bob&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyAppName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Seeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bob&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mockjax&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/users/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;responseText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyAppName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bobInitial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;responseText&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;MyAppName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;MyAppName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;one&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;refresh&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No JavaScript project should be without a local notification system to help keep disparate components up to date. Thankfully, Spine&amp;#39;s event module makes a local PubSub system a breeze. The HolyGrailHarness has a &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/javascripts/holy_grail_harness/lib/notifications.js.coffee&quot;&gt;&lt;code&gt;notifications.js.coffee&lt;/code&gt;&lt;/a&gt; that exposes a class level &lt;code&gt;bind()&lt;/code&gt; and &lt;code&gt;trigger()&lt;/code&gt; to any event string/namespace you want. To make more simple, we recommend creating class level functions that expose the event name as the function name and pass the args to the &lt;code&gt;handle()&lt;/code&gt; function. We have done this for the &lt;code&gt;MyAppName.Notifications.appReady()&lt;/code&gt; to demonstrate. Calling this function will trigger the &lt;code&gt;app.ready&lt;/code&gt; event and passing a function to this function will bind that function to the same event name.&lt;/p&gt;

&lt;h2 id=&quot;sass-amp-compass&quot;&gt;Sass &amp;amp; Compass&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://sass-lang.com&quot;&gt;Sass&lt;/a&gt; is the only way to write CSS for today&amp;#39;s modern web applications. &lt;a href=&quot;http://compass-style.org&quot;&gt;Compass&lt;/a&gt; is the CSS framework that no Sass user should go without. Together they provide a foundation for writing beautiful CSS using pre-built time saving functions. The HolyGrailHarness includes both the &lt;a href=&quot;https://github.com/rails/sass-rails&quot;&gt;sass-rails&lt;/a&gt; and &lt;a href=&quot;https://github.com/Compass/compass-rails&quot;&gt;compass-rails&lt;/a&gt; gems.&lt;/p&gt;

&lt;p&gt;To get you started on the right path, we have also created a basic structure within the &lt;code&gt;app/assets/stylesheets&lt;/code&gt; asset pipeline directory to help you organize your Sass files. Here is the directory structure below.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;├── application.css
├── application
│   ├── _layout.scss
│   ├── index.scss
│   ├── components
│   │   └── _foo.scss
└── shared
    ├── _animations.scss
    ├── _fonts.scss
    ├── _mixins.scss
    ├── _placeholders.scss
    ├── _variables.scss
    └── base.scss
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;the-application-css-file&quot;&gt;The application.css file.&lt;/h3&gt;

&lt;p&gt;Never write CSS in &lt;code&gt;application.css&lt;/code&gt;. Say what? I know right, but trust me. Just consider this file a top level bundle dependency that only requires other top level bundle assets. Here is the contents of that file. Notice how it requires a bundle called twitter and an index. One is for twitter bootstrap, see section below, and the other is the index to your own Sass framework.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/*
 *= require application/twitter
 *= require application/index
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;the-shared-directory&quot;&gt;The shared directory.&lt;/h3&gt;

&lt;p&gt;Think of this as your own Compass framework. The &lt;a href=&quot;https://github.com/metaskills/holy_grail_harness/blob/master/app/assets/stylesheets/shared/base.scss&quot;&gt;&lt;code&gt;base.scss&lt;/code&gt;&lt;/a&gt; is your single file to &lt;code&gt;@import&lt;/code&gt; to get everything loaded and ready to go. &lt;strong&gt;Nothing in any of the shared files should generate CSS!&lt;/strong&gt; Importing &lt;code&gt;shared/base&lt;/code&gt; should act just like importing &lt;code&gt;compass&lt;/code&gt;. Use these files for setting your own variables and creating misc helper functions &amp;amp; mixins. There is a variables file for... variables! Another for animations, fonts and mixins too.&lt;/p&gt;

&lt;p&gt;Pay special attention to the &lt;code&gt;_placeholders.scss&lt;/code&gt; file. If you do not know about Sass 3.2&amp;#39;s placeholder selectors (silent classes) and how they make presentational classes efficiently extended by semantic ones, then I highly suggest you read Dale Sande&amp;#39;s presentation titled &lt;a href=&quot;https://speakerdeck.com/anotheruiguy/sass-32-silent-classes&quot;&gt;Sass 3.2 Silent Classes&lt;/a&gt; on Speaker Deck.&lt;/p&gt;

&lt;p&gt;Below is the contents of the &lt;code&gt;base.scss&lt;/code&gt; file, take note of the order. See too how we import the entire Compass framework. This means that all of your Sass code in any of the shared files can take full advantage of both Bootstrap and Compass&amp;#39; variables and mixins. Epic win!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sass&quot; data-lang=&quot;sass&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Think of this file as your own compass. Importing the base, never generates CSS.
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/variables&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bootstrap/mixins&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;compass&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;compass/layout&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;compass/css3/user-interface&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/fonts&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/mixins&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/animations&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/placeholders&quot;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;the-application-directory&quot;&gt;The application directory.&lt;/h3&gt;

&lt;p&gt;Organize this as you see fit. We have started you off by creating a &lt;code&gt;_layout.scss&lt;/code&gt; file for your general layout/structure styles. There is also a &lt;code&gt;components&lt;/code&gt; directory which all sub files are imported via a glob. The idea is that components are not dependent upon another. Files that might go in here are things like datepicker, navigation, and general files named after components or widgets. Below is what the &lt;code&gt;application/index.scss&lt;/code&gt; looks like.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sass&quot; data-lang=&quot;sass&quot;&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/base&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./layout&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;components/*&quot;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you are more advanced with your CSS and like the idea of style guides, take a looks a the &lt;a href=&quot;https://github.com/Anotheruiguy/toadstool&quot;&gt;Toadstool&lt;/a&gt; style guide framework.&lt;/p&gt;

&lt;h2 id=&quot;twitter-bootstrap&quot;&gt;Twitter Bootstrap&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter Bootstrap&lt;/a&gt; is awesome, but &lt;a href=&quot;http://metaskills.net/2012/02/27/too-less-should-you-be-using-sass/&quot;&gt;LESS is not&lt;/a&gt;. That is why the HolyGrailHarness uses the &lt;a href=&quot;https://github.com/thomas-mcdonald/bootstrap-sass&quot;&gt;bootstrap-sass&lt;/a&gt; gem that converts all the Bootstrap LESS files to Sass. Making them ready to import via the Rails asset pipeline.&lt;/p&gt;

&lt;p&gt;As shown above in the Sass section, we require the &lt;code&gt;application/twitter.scss&lt;/code&gt; bundle asset from the top level &lt;code&gt;application.css&lt;/code&gt; bundle file. This twitter bundle file, contents below, take advantage of your shared variables before importing bootstrap from the gem. In this way you can define variables that tweak bootstrap. A good example would be button colors, column widths, etc. Later on in the file you can extend bootstrap styles to your liking. For instance, add more padding to buttons.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sass&quot; data-lang=&quot;sass&quot;&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shared/variables&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bootstrap&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;font-awesome&quot;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Tweak or redefine Twitter classes below.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;font-awesome&quot;&gt;Font Awesome&lt;/h3&gt;

&lt;p&gt;The glyph icons included in Twitter Bootstrap are horrible for hi-resolution &amp;quot;retina&amp;quot; displays typically found on mobile devices. Thankfully the &lt;a href=&quot;http://fortawesome.github.com/Font-Awesome/&quot;&gt;Font Awesome&lt;/a&gt; project provides a drop in replacement that instead uses icon fonts vs raster images.&lt;/p&gt;

&lt;p&gt;The HolyGrailHarness vendors these font files and the needed &lt;code&gt;font-awesome.scss&lt;/code&gt; file and requires them as part of the Twitter Bootstrap bundle shown above. More advanced users may prefer to only include the icon fonts needed in their application or a few custom icons. If that is the case, check out &lt;a href=&quot;http://endtwist.github.com/fontcustom/&quot;&gt;Font Custom&lt;/a&gt;, webfonts from the comfort of the command line.&lt;/p&gt;
</description>
        <pubDate>Wed, 05 Dec 2012 00:00:00 -0500</pubDate>
        <link>/2012/12/05/holygrailharness/</link>
        <guid isPermaLink="true">/2012/12/05/holygrailharness/</guid>
      </item>
    
      <item>
        <title>Synchronized Times In Ruby &amp;amp; JavaScript Acceptance Tests Using Capybara, Timecop &amp;amp; Sinon.JS</title>
        <description>&lt;p&gt;
  Any good Ruby developer that tests time-dependent code has used the &lt;a href=&quot;http://github.com/jtrupiano/timecop&quot;&gt;Timecop&lt;/a&gt; gem. Timecop provides dead simple time travel and freezing capabilities to Ruby&#39;s standard library. But what if you are working on a rich JavaScript application that is backed and tested by something like a Rails application and you want to alter the test browser&#39;s clock as well? The answer is pretty simple, but let&#39;s first examine all the parts at play here.
&lt;/p&gt;

&lt;h2&gt;Rails &amp;amp; Capybara&lt;/h2&gt;

&lt;p&gt;
  My examples leverage a very simple Rails integration test setup using &lt;a href=&quot;http://github.com/jnicklas/capybara/#the-dsl&quot;&gt;Capybara&#39;s DSL&lt;/a&gt; within a basic Rails integration test case. Much like &lt;a href=&quot;http://techiferous.com/2010/04/using-capybara-in-rails-3/&quot;&gt;Wyatt has described here&lt;/a&gt; and I have shown in a &lt;a href=&quot;http://github.com/metaskills/holygrail_rails31&quot;&gt;demo project on github&lt;/a&gt;. So if your integration test setup is different, transpose my code to fit your needs. Also, there are a few drivers for Capybara that support full JavaScript integration, most notably capybara-webkit. But the latest on the scene is &lt;a href=&quot;http://github.com/jonleighton/poltergeist&quot;&gt;Poltergeist&lt;/a&gt; which uses the badass PhantomJS project. I highly recommend you switch to this driver! That said, any Capybara driver that fully supports Capybara&#39;s &lt;code&gt;#execute_script&lt;/code&gt; should work just fine.
&lt;/p&gt;

&lt;h2&gt;Ruby &amp;amp; JavaScript Times&lt;/h2&gt;

&lt;p&gt;
  JavaScript date values represent time in milliseconds since Unix Epoch. Many 3rd-party JavaScript date libraries use millisecond integers for both instantiating and altering these objects. Ruby on the other hand has a much higher precision and thanks to ActiveSupport&#39;s core extensions to Ruby&#39;s date and time classes we can easily represent these values for JavaScript. Specifically, ActiveSupport adds a &lt;code&gt;#to_i&lt;/code&gt; method that returns an integer which represents that date or time in seconds since Unix Epoch. In my example code, you will see that I multiple this by 1000 to get the millisecond representation.
&lt;/p&gt;

&lt;p&gt;
  ActiveSupport also provides an &lt;code&gt;#advance&lt;/code&gt; core extension to all date and time classes. This method is Valuable As Fuck&amp;trade; since it returns a new time instance that has moved backwards or forwards given a hash of options. For example, returning a time instance moved forward by 20 minutes would look like this &lt;code&gt;@time.advance(minutes:20)&lt;/code&gt;. See the &lt;a href=&quot;http://api.rubyonrails.org/classes/Time.html#method-i-advance&quot;&gt;documentation&lt;/a&gt; for all the options and remember, you can provide negative values to move backward. In short, the advance method is awesome!
&lt;/p&gt;

&lt;h2&gt;Faking Time With Sinon.JS&lt;/h2&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  &lt;a href=&quot;http://pivotal.github.com/jasmine/#section-Mocking_the_JavaScript_Clock&quot;&gt;Jasmine 1.2 now has a similiar mocking technique for the JavaScript clock.&lt;/a&gt;
&lt;/aside&gt;

&lt;p&gt;
  &lt;a href=&quot;http://sinonjs.org&quot;&gt;Sinon.JS&lt;/a&gt; is a small stand-alone library that provides spies, stubs and mocks for your JavaScript. To be honest, I use Jasmine and supporting extensions for most of these features. However, Sinon.JS has one killer feature, faking time! Yup, it allows you to freeze JavaScript&#39;s clock to a specific time and tick it forward as needed. I want you to ponder the benefits of that for awhile. Imagine you have time sensitive JavaScript code that uses &lt;code&gt;setInterval()&lt;/code&gt; or the like. Sinon.JS will actually allow you to tick time forward and still maintain compatibility with that code&#39;s behavior! Basically Sinon.JS is equal to our Ruby Timecop gem and then some! Check out their &lt;a href=&quot;http://sinonjs.org/docs/#clock-api&quot;&gt;clock API&lt;/a&gt; or read the code if you want to learn more. Remember, it is safe to include Sinon.JS in any existing JavaScript project since it will not do anything unless you ask it too. So no fear in it clashing with your other JavaScript test setup.
&lt;/p&gt;

&lt;h2&gt;Putting It All Together&lt;/h2&gt;

&lt;p&gt;
  So now the fun part, some code examples. First, you need to get Sinon.JS in your Rails JavaScript manifest. If you are smart, you have already setup a system where you can specify top level asset manifests for your JavaScript application per test environment. If not, you might want to take a look at two posts I previously published on setting up Jasminerice for testing Spine.JS applications.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  These file snippets below assume you have an &lt;code&gt;integration.js&lt;/code&gt; manifest which includes both a vendored Sinon.JS then a sub file which actually initializes Sinon.JS for our integration test run. In this case below, we are first processing a CoffeeScript file with ERB and then initializing Sinon.JS&#39; fake timers to a default time. In my case, this is 8:30am central standard time. Now we can assure that Capybara&#39;s browser engine will be frozen at that time and ready to move forward for each test.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// File app/assets/javascripts/integration.js&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//= require sinon-1.4.2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//= require integration/sinon&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//= require application&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File app/assets/javascripts/integration/sinon.js.coffee.erb
&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;central&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TimeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;Central Time (US &amp;amp; Canada)&#39;&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;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;8:30am&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sinon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;useFakeTimers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now, the Ruby code. Here is slimmed down version of my base integration test case which &lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;uses MiniTest::Spec&lt;/a&gt; to drive Capybara tests. The first thing I do before any integration test is use Timecop to travel to 8:30am. This means that both Ruby and JavaScript are synced to the exact millisecond in time. Any test that needs to move time forward must call the &lt;code&gt;#advance_time&lt;/code&gt; test helper. This method takes a hash of options which is passed directly to the &lt;code&gt;#advance&lt;/code&gt; method I previously talked about. It measures the milliseconds between now and the advancement and sends that directly to Sinon.JS&#39; fake timers using Capybara&#39;s &lt;code&gt;#execute_script&lt;/code&gt; method. So calling &lt;code&gt;advance_time(seconds:20)&lt;/code&gt; in Ruby now moves time forward in both Ruby and JavaScript. Epic win!!!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File test/test_helper_integration.rb&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test_helper&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;capybara/rails&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActionDispatch&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Capybara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DSL&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;travel&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;8:30am&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Capybara&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reset_sessions!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&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;travel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseable_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Timecop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Timecop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;travel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parse_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseable_time&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;parse_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Chronic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&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;advance_time&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;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;now_ms&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Timecop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;travel&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;advance&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;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;traveled_ms&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;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&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;now_ms&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;advance_sinon&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;traveled_ms&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;advance_sinon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute_script&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;if (window.clock) { window.clock.tick(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;); }&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  I have found the following technique critical to fully testing a recent time based JavaScript application I have developed. I hope you find this technique useful as well and as always, please contribute your thoughts or questions below. Cheers!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/jtrupiano/timecop&quot;&gt;Timecop - A gem providing &quot;time travel&quot; and &quot;time freezing&quot; capabilities, making it dead simple to test time-dependent code.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/jnicklas/capybara/&quot;&gt;Capybara - Acceptance test framework for web applications.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/jonleighton/poltergeist&quot;&gt;Poltergeist - A PhantomJS driver for Capybara.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://sinonjs.org&quot;&gt;Sinon.JS - Standalone test spies, stubs and mocks for JavaScript.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 07 Aug 2012 00:00:00 -0400</pubDate>
        <link>/2012/08/07/synchronized-times-in-ruby-and-javascript-acceptance-tests-using-capybara-timecop-and-sinon-js/</link>
        <guid isPermaLink="true">/2012/08/07/synchronized-times-in-ruby-and-javascript-acceptance-tests-using-capybara-timecop-and-sinon-js/</guid>
      </item>
    
      <item>
        <title>Rails, Moment.js And Time Zones</title>
        <description>&lt;p&gt;
  Here are a few quick tips for the time zone aware Rails developer that finds themselves deep into JavaScript date objects. First, use the &lt;a href=&quot;http://momentjs.com&quot;&gt;Moment.js&lt;/a&gt; JavaScrpt date library! Moment.js has a very &lt;a href=&quot;http://momentjs.com/docs/&quot;&gt;rich API for parsing and working with times&lt;/a&gt;, very similiar to ActiveSupport&#39;s extensions. However, it does not have a solid way of moving times across zones. Especially if those zones may or may not observer daylight savings time (DST).
&lt;/p&gt;

&lt;p&gt;
  Many JavaScript time zone libraries require a huge set of geographic data to both identify zones and their observance of DST. These data files can add a significant overhead to JavaScript. But wouldn&#39;t it be great if there was a simple way of leveraging your Rails model&#39;s time zone settings? There is, but first we need to serialize an &lt;code&gt;ActiveSupport::TimeZone&lt;/code&gt; object in JSON. Easy, just define an &lt;code&gt;#as_json&lt;/code&gt; method like the one below. I suggest adding this to an initializer in your Rails &lt;code&gt;config/initializers/active_support.rb&lt;/code&gt; directory. The key attribute here is the &lt;code&gt;utc_total_offset&lt;/code&gt;. This will be a number in minutes that properly observes DST.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveSupport&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TimeZone&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_json&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;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;                &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:identifier&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tzinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:friendly_identifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tzinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;friendly_identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:utc_offset&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utc_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:utc_total_offset&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tzinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current_period&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;utc_total_offset&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now assuming you have serialized a models time zone attribute using the full &lt;code&gt;ActiveSupport::TimeZone&lt;/code&gt; object, we can easily use this information client side via a quick extension to Moment.js&#39; prototype. Here is a &lt;code&gt;moment.js.coffee&lt;/code&gt; file I have required in my Rails applications.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forTimeZone&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;nx&quot;&gt;timeZone&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;nx&quot;&gt;currentOffset&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;zone&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;60&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;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;adjustedOfffset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentOffset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;utc_total_offset&lt;/span&gt;
                      &lt;span class=&quot;nx&quot;&gt;timeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;utc_total_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentOffset&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                      &lt;span class=&quot;nx&quot;&gt;currentOffset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;utc_total_offset&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;seconds&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;adjustedOfffset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So we let Ruby do all the hard work of telling us what time zones are observing DST without all the bloat to our JavaScript for parsing zone identifiers. Some sample output.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;eastern&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;na&quot;&gt;friendly_identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;America - New York&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;America/New_York&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Eastern Time (US &amp;amp; Canada)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;utc_offset&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;18000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;utc_total_offset&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;14400&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;noonPacific&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1344279600000&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;2012-08-06T12:00:00-07:00&quot;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;MMMM Do, YYYY \\at h:mma&#39;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;noonPacific&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// &quot;August 6th, 2012 at 12:00pm&quot;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;noonPacific&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forTimeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eastern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// &quot;August 6th, 2012 at 3:00pm&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://momentjs.com&quot;&gt;Moment.js - A lightweight JavaScript date library.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 05 Aug 2012 00:00:00 -0400</pubDate>
        <link>/2012/08/05/rails-moment-js-and-time-zones/</link>
        <guid isPermaLink="true">/2012/08/05/rails-moment-js-and-time-zones/</guid>
      </item>
    
      <item>
        <title>View Controller Patterns With Spine.JS &amp;amp; SpacePen</title>
        <description>&lt;h2&gt;The VC in &#39;MVC&#39;&lt;/h2&gt;

&lt;p&gt;
  As Addy Osmani points out in his &lt;a href=&quot;http://speakerdeck.com/u/addyosmani/p/scaling-your-javascript-applications&quot;&gt;Scaling Your JavaScript Applications&lt;/a&gt; presentation, all JavaScript &#39;MVC&#39; frameworks interpret MVC differently. These differences are an academic rabbit hole and if you are really interested about them, I recommend reading some of the resource links at the bottom of this post. One in particular by Jonas Nicklas really outlined how I think client side JavaScript applications should be developed. It is titled &lt;a href=&quot;http://elabs.se/blog/33-why-serenade-js&quot;&gt;Why Serenade.js&lt;/a&gt; and in it, Jonas describes his reasons for yet another JavaScript MVC framework. In doing so, he outlines the responsibilities of the MVC triad as follows:
&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;Views:&lt;/strong&gt; Present data from the model and update it if it changes, notify controllers of user interaction events. &lt;strong&gt;Controllers:&lt;/strong&gt; React to user interaction events by instructing the model to perform certain actions. &lt;strong&gt;Models:&lt;/strong&gt; Handle business logic and persistence, notify the view of any changes to the data.
&lt;/p&gt;

&lt;p&gt;
  &lt;!--&lt;span class=&quot;floatr&quot; style=&quot;margin:0 0 15px 15px; -moz-box-shadow: 5px 5px 5px rgba(0,0,0,0.5); -webkit-box-shadow: 5px 5px 5px rgba(0,0,0,0.5); box-shadow: 5px 5px 5px rgba(0,0,0,0.5); -moz-transform: rotate(-2deg); -webkit-transform: rotate(-2deg); transform: rotate(-2deg);&quot;&gt;
    &lt;img src=&quot;/assets/todomvc.png&quot; alt=&quot;TodoMVC JavaScript Frameworks&quot; width=&quot;354&quot; height=&quot;263&quot; /&gt;
  &lt;/span&gt;--&gt;
  Seems straight forward right? In actuality it is easy to stray from and there is a lot of wiggle room for both the MV* framework authors and their developers to re-interpret one or all of these components. The two that I think are most open for debate are the View and the Controller stacks. For example, how many &lt;a href=&quot;http://addyosmani.github.com/todomvc/&quot;&gt;JavaScript frameworks&lt;/a&gt; do you know allow you to choose your own view framework? How many times have you heard too that views should be &quot;logic-less&quot; and how does each of these play into helping newcomers understand the proper way to code these precious views and controllers together? My answer, ask Apple!
&lt;/p&gt;

&lt;h2&gt;Apple&#39;s View Controller Programming Guide&lt;/h2&gt;

&lt;p&gt;
  Some might be surprised that JavaScript applications for the browser can and should be coded much like modern desktop applications. Having developed iOS applications before, many of the same MVC principals and application structure apply. Apple has tons of documentation about general application design and one of my favorites is their &lt;a href=&quot;http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html&quot;&gt;View Controller Programming Guide&lt;/a&gt;. I highly recommend anyone developing MVC JavaScript applications to read this guide. I&#39;ll paraphrase a few points:
&lt;/p&gt;

&lt;blockquote&gt;
  A view controller manages a discrete portion of your app’s user interface. Often that view is the root view for a more complex hierarchy of other views. View controllers typically fall in one of two categories, either content or container. Content view controllers are great for things like lists and images. Container view controllers coordinate with other view controllers like tab view controllers or navigation controllers.
&lt;/blockquote&gt;

&lt;p&gt;
  It is also worth reading both the &lt;a href=&quot;https://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html&quot;&gt;UIViewController&lt;/a&gt; and &lt;a href=&quot;https://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/UIView/UIView.html&quot;&gt;UIView&lt;/a&gt; class references too. So what should be your major take away from reading those? The first is that every controller in your JavaScript application manages a view. That view is going to be a DOM node that will most likely have a complex hierarchy of other views possibly managed by other controllers which themselves champion a node with a specific application concern. Second is that views are themselves valid objects built by classes with their own methods. It&#39;s best to think of UIViews as an instance of a jQuery object. Views should not be dumb either. They sometimes have handles back to model objects so they can establish bindings for updates. Views can also expose an interface that canonize how controllers should work with them and most often will have helper methods that break up their complexity. All of this is a good thing. If you disagree, stop reading now!
&lt;/p&gt;

&lt;h2&gt;SpacePen - Markup On The Final Frontier&lt;/h2&gt;

&lt;p&gt;
  I found the &lt;a href=&quot;https://github.com/nathansobo/space-pen&quot;&gt;SpacePen project on github&lt;/a&gt; a few months ago and I have never looked at another templating solution since. For the first time my JavaScript application&#39;s view and controller stacks feel natural. No longer do I find myself writing any view related code in my controllers. SpacePen allows me to write view objects that encapsulate their concerns, stay DRY and build Spine.JS web applications that hit the MVC mark. So what is SpacePen? Basically a CoffeeScript subclass of a jQuery object.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpacePort&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;View&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@content&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;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@h1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Space Ships&quot;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@ol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@li&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Apollo&quot;&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@li&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Soyuz&quot;&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@li&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Space Shuttle&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SpacePort&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;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;ol&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;li&amp;gt;Star Destroyer&amp;lt;/li&amp;gt;&#39;&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;nf&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;li&#39;&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;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You clicked on &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;text&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;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This simple example shows how your SpacePen view class defines its markup in a &lt;code&gt;@content&lt;/code&gt; class function. This function yields a builder syntax where you can easily add attributes and values. My advice is to do basic structure only in your &lt;code&gt;@content&lt;/code&gt; function and rarely take advantage of the fact that it also takes the same parameters argument passed to your constructor. I will explain more on that advice later. But first, I did say that views should expose interfaces to controllers and are first class code citizens that champion their own concerns right? Let&#39;s look at a common pattern, views building new nodes within itself.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpacePort&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;View&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@content&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;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@h1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SpacePort&quot;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@ol&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;outlet: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;shipList&#39;&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;addShip: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ship&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;vi&quot;&gt;@shipList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ship&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;/li&amp;gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SpacePort&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;nf&quot;&gt;addShip&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Enterprise&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The example has been changed slightly so that the view now exposes a public function called &lt;code&gt;addShip()&lt;/code&gt; which takes an object to add to the view. It can easily implement this because I have declared the ordered list to be an outlet called &lt;code&gt;shipList&lt;/code&gt; which will automatically be assigned as a property on each view instance. Calling append on that node is possible because like the view object itself, any outlet is a jQuery object as well.
&lt;/p&gt;

&lt;p&gt;
  Though contrived, this example illustrates a powerful technique. If the view was refactored to some other structure besides an ordered list with items, the controller interface would stay the same. Pulling the thread, it is easy to see how a complex view hierarchy could have views building and managing messages to their subviews too. This is the crux of my article, but first, lets talk about controllers.
&lt;/p&gt;

&lt;h2&gt;Spine.JS Controllers&lt;/h2&gt;

&lt;p&gt;
  Spine.JS is my goto JavaScript MVC framework and if you are unfamiliar with it, check out their &lt;a href=&quot;http://spinejs.com/docs/introduction&quot;&gt;introduction&lt;/a&gt; or read &lt;a href=&quot;http://destroytoday.com/blog/reasons-for-spinejs/&quot;&gt;why others&lt;/a&gt; have chosen to use it. The main reasons I love Spine.JS can be summed up like so. First, it is authored in CoffeeScript, which means I can read the code to learn it. Second, all model instances will reflect changes by any other instance. Lastly, the controllers are minimally implemented and nicely abstract managing a view and the way controllers respond to events that bubble up to it.
&lt;/p&gt;

&lt;p&gt;
  A Spine.JS controller always has an element associated to it which can be accessed via the &lt;code&gt;el&lt;/code&gt; property. This element represents the view that controller manages. It will either be created for you or it can be assigned via the constructor. Many patterns in Spine.JS rely on appending elements to a controller and most of the functions for adding these subviews either take an element or an object that has an &lt;code&gt;el&lt;/code&gt; property. This means building complex view/controller hierarchies by stacking Spine.JS controllers is both idiomatic and almost identical to how iOS view controllers work.
&lt;/p&gt;

&lt;h2&gt;Using SpacePen Views With Spine.JS Controllers&lt;/h2&gt;

&lt;p&gt;
  With the overview of these components out of the way, let&#39;s jump right into how they can work together to punch the VC up a notch in your next JavaScript MVC application. These examples below are pared down version of a scheduler application I just completed. The model is similar to an iCal day interface for calendar events. In such, there would be a view controller that manages the presentation of your schedule &quot;by day&quot;. This controller&#39;s view would have a header for the current day and a set of controls for going to the previous day, today and the next day. This controller would act as a navigation controller and correlate to Apple&#39;s notion of a &quot;container&quot; view controller. When needed, it would find or create a day controller and append it to one of its subviews. The code for that container controller and view is out of the scope of this article, but its one of many day &quot;content&quot; controllers and view are perfect examples. Here we go!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In app/assets/javascripts/app/controller/day.js.coffee&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Controllers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Spine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Controller&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;el: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In app/assets/javascripts/app/views/day.js.coffee&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;View&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;day&#39;&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;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;initialize: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@attr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;data-date&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;YYYY-MM-DD&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So rule number one, always create an instance of a SpacePen view and assign that to the &lt;code&gt;@view&lt;/code&gt; property of every Spine.JS controller. That &lt;code&gt;@view&lt;/code&gt; will be assigned to the controller&#39;s &lt;code&gt;@el&lt;/code&gt; property when it supers up.
&lt;/p&gt;

&lt;p&gt;
  Rule number two, keep the &lt;code&gt;@content&lt;/code&gt; function for your views concerned with building the structure only. In my example, I set the date for the event using the &lt;code&gt;initialize&lt;/code&gt; hook provided by SpacePen. This rule is important when you want to bind views to model events and update that view accordingly. All customization of the view to a model object should be done in a set/update helper of that view.
&lt;/p&gt;

&lt;h2&gt;In Greater Detail&lt;/h2&gt;

&lt;p&gt;
  Here is the same controller and view example with a bit more detail. First up, the view. This day view CoffeeScript file has a public &lt;code&gt;App.Views.Day&lt;/code&gt; view and a private &lt;code&gt;EventView&lt;/code&gt; that represents a subview and would be bound to a model instance. This public day view exposes a few public functions for a controller to hook into. The &lt;code&gt;addEvent&lt;/code&gt; function will actually build a new SpacePen views for the passed model and append it as a subview. Notice too the &lt;code&gt;findEvent&lt;/code&gt; helper function which can find the DOM element for a model object and then use the &lt;code&gt;view()&lt;/code&gt; function provided by SpacePen to get to the SpacePen instance for this node.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;View&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;day&#39;&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;c1&quot;&gt;# ...&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;outlet: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;events&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;events&#39;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;initialize: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@attr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;data-date&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;YYYY-MM-DD&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;addEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EventView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;updateEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@findEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;removeEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@findEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Private&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;findEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;n&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.event[data-event-id=&#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;startsAtFormat&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;s2&quot;&gt;&#39;]&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;afterAttach: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@startSpinner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@loadEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EventView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;View&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.event&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;data-event-id&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;outlet: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;description&#39;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;outlet: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;duration&#39;&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;initialize: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@update&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;update: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@attr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;data-starts-at&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;startsAtFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;description&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;duration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Next up, the expanded day controller example that manages the view above. In this example we bind to two of the the Spine.JS &lt;code&gt;CalendarEvent&lt;/code&gt; model events. One for update and one for destroy. These events are then pushed down to the view and will do any work necessary. Just in case this controller is ever discarded for performance reasons, we hook into the &lt;code&gt;release()&lt;/code&gt; function provided by Spine.JS controllers to remove the event listeners.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Controllers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Spine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Controller&lt;/span&gt;

  &lt;span class=&quot;vi&quot;&gt;@events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;click .event&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;selectEvent&#39;&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&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;vi&quot;&gt;@date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;moment&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Day&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;moment: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@date&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;el: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CalendarEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@updateEvent&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CalendarEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;beforeDestroy&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@destroyEvent&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;release:
    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CalendarEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unbind&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@updateEvent&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CalendarEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unbind&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;beforeDestroy&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@removeEvent&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Private&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;selectEvent: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;updateEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;updateEvent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;removeEvent: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;vi&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;removeEvent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Hope you found this mini introduction to SpacePen and Spine.JS controllers useful. There is literally tons of ways you can use these tools together to make your controllers and views fun to build and maintainable. Be excellent and let me know what works for you!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://elabs.se/blog/33-why-serenade-js&quot;&gt;Why Serenade.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://addyosmani.com/blog/understanding-mvvm-a-guide-for-javascript-developers/&quot;&gt;Understanding MVVM - A Guide For JavaScript Developers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://addyosmani.com/blog/understanding-mvc-and-mvp-for-javascript-and-backbone-developers/&quot;&gt;Understanding MVC And MVP (For JavaScript And Backbone Developers)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html&quot;&gt;View Controller Programming Guide for iOS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/nathansobo/space-pen&quot;&gt;SpacePen - Markup On The Final Frontier&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://spinejs.com/docs/introduction&quot;&gt;An Introduction To Spine.JS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://destroytoday.com/blog/reasons-for-spinejs/&quot;&gt;10 Reasons Why I Switched To Spine.JS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;Rails &amp;amp; Spine.JS - Using The CoffeeScript Source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 22 May 2012 00:00:00 -0400</pubDate>
        <link>/2012/05/22/view-controller-patterns-with-spine-js-and-spacepen/</link>
        <guid isPermaLink="true">/2012/05/22/view-controller-patterns-with-spine-js-and-spacepen/</guid>
      </item>
    
      <item>
        <title>StoreConfigurable - A Lesson In Recursion In Ruby</title>
        <description>&lt;p&gt;
  When ActiveRecord 3.2 was released there was a small addition called &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Store.html&quot;&gt;ActiveRecord::Store&lt;/a&gt; which bills itself as a simple key/value store for your models. The code below is pulled right from their example usage.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;n&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;accessors: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:homepage&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;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;color: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;black&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;homepage: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;37signals.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;color&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;black&#39;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &#39;black&#39;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:remember_me&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;kp&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Most people know that I love simple tools. But when I found myself considering &lt;code&gt;ActiveRecord::Store&lt;/code&gt;, I found it seriously lacking for my particular use case. What I wanted was a config for a user class that could do the following:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Interchange property dot notation with indifferent string/symbol lookup.&lt;/li&gt;
  &lt;li&gt;Automatically grow as needed. For namespaces and nested organization.&lt;/li&gt;
  &lt;li&gt;Report state changes to the model from any node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;StoreConfigurable&lt;/h2&gt;

&lt;p&gt;
  &lt;img src=&quot;http://cdn.actionmoniker.com/share/recursive_kitty_small.jpg&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot;&gt;
  The lack of these features is why I set out to build a little gem I call &lt;a href=&quot;https://github.com/metaskills/store_configurable&quot;&gt;StoreConfigurable&lt;/a&gt;. A zero-configuration recursive Hash for storing a tree of options in a serialized ActiveRecord column which includes self-aware hooks that delegate dirty/changed state to your configs owner. Perfect right? Here is a simple example of its usage below. If you want to learn more, checkout the &lt;a href=&quot;https://github.com/metaskills/store_configurable&quot;&gt;project on github&lt;/a&gt; with the full README.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;n&quot;&gt;store_configurable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remember_me&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;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sortable_tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;column&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;created_at&#39;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sortable_tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;asc&#39;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;you&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;need&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;but&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;you&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;could&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;you&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wanted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;deep_value&#39;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config_changed?&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Rather than talking about how StoreConfigurable might be a good fit for you, I would instead like to discuss how my first practical usage of recursion in Ruby is implemented in StoreConfigurable. That along with how to leverage default Hash values is the topic for this post.
&lt;/p&gt;

&lt;h2&gt;Default Hash Values&lt;/h2&gt;

&lt;p&gt;
  So first up, a little known feature of Ruby&#39;s &lt;a href=&quot;http://www.ruby-doc.org/core-1.9.3/Hash.html&quot;&gt;Hash&lt;/a&gt; class is the ability for a default value to be returned when a key is missing. If you stop and think about this, the default is &lt;code&gt;nil&lt;/code&gt;, which is a valid object in Ruby. But you can tell Hash objects to return other values when a key is missing. The first way to do this is to pass the default value as an argument to &lt;code&gt;Hash.new()&lt;/code&gt;. The second is to pass a block to the new method which would return the default value. That block is passed in the current hash object and the key that is missing so you can do some fancy things if needed. Here are some quick examples of both techniques.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Default value passed to new.&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;default&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Default value from new&#39;s block.&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&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;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Missing &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; for hash with id &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;Missing foo for hash with id 283829283.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Recursion&lt;/h2&gt;

&lt;p&gt;
  Recursion in Ruby can take many forms. My solution for StoreConfigurable was to always make the hash returned by the proxy object self replicate itself for key misses. Here is a fundamental example to make your own Hash object return new instances of itself when keys are missing.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RecursiveHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Recursive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&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;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&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;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&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;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Recursive&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;nb&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RecursiveHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; RecursiveHash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; RecursiveHash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {:foo=&amp;gt;{}, :a=&amp;gt;{:b=&amp;gt;{:c=&amp;gt;{}}}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  In this example, I create a &lt;a href=&quot;http://www.ruby-doc.org/core-1.9.3/Proc.html&quot;&gt;Proc&lt;/a&gt; object via the lambda keyword and I use this as the block argument when you create an instance of &lt;code&gt;RecursiveHash&lt;/code&gt; via the super method. Here I am using the &lt;code&gt;&amp;amp;&lt;/code&gt; syntax to pass an existing Proc as a block. Hope I have not lost you so far :)
&lt;/p&gt;

&lt;p&gt;
  So default hashes in Ruby and simple recursion techniques are what make up some of the key points of StoreConfigurable. I also use recursion when loading the hash values from the YAML stored in the database. Here is what that technique looks like.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Hopefully this dive into Ruby or maybe StoreConfigurable is helpful!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/store_configurable&quot;&gt;StoreConfigurable&lt;/a&gt; - A zero-configuration recursive Hash for storing a tree of options in a serialized ActiveRecord column with self-aware hooks that delegate dirty/changed state to your configs owner.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Store.html&quot;&gt;ActiveRecord::Store&lt;/a&gt; - Simple key/value store for your models.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 12 Mar 2012 00:00:00 -0400</pubDate>
        <link>/2012/03/12/store-configurable-a-lesson-in-recursion-in-ruby/</link>
        <guid isPermaLink="true">/2012/03/12/store-configurable-a-lesson-in-recursion-in-ruby/</guid>
      </item>
    
      <item>
        <title>Too LESS? Should You Be Using Sass?</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  Previously I had updated this article to say that this &lt;a href=&quot;http://github.com/cloudhead/less.js/commit/93b23d2c24936d5bd829ba1f725ef442e9475747&quot;&gt;commit&lt;/a&gt; looked like it gives you real variable properties in LESS. I was wrong! So even in LESS v1.3 you are still screwed for doing metaprogramming and working with a real CSS preprocessor. That may change for LESS v1.4 and if you want to help make that happen. I suggst you put your weight behind &lt;a href=&quot;https://github.com/cloudhead/less.js/pull/698&quot;&gt;this github pull request&lt;/a&gt;.
&lt;/aside&gt;

&lt;p&gt;
  First, a little bit of background. A while back ago I took a great deal of my personal time to try out Twitter&#39;s Bootstrap project for a Rails application of mine. This meant that I was willing to throw away some of the work I had done in Sass and rewrite it using LESS. No problem I thought, at first glance LESS and Sass look almost identical in functionality. So after some weeks of improving the toolchain for LESS with Ruby and then Rails, I set out to do just that &amp;ndash; and what a miserable failure it was. My goal is to share my experiences to anyone considering using LESS and why it might be wrong for your Rails project.
&lt;/p&gt;

&lt;h2&gt;Why Should My Opinion Matter?&lt;/h2&gt;

&lt;p&gt;
  For staters, I am the author of &lt;a href=&quot;http://github.com/metaskills/less-rails&quot;&gt;less-rails&lt;/a&gt;, the gem that allows you to effectively use LESS in the Rails asset pipeline. This gem made other gems of mine like &lt;a href=&quot;http://github.com/metaskills/less-rails-bootstrap&quot;&gt;less-rails-bootstrap&lt;/a&gt; possible. So now full LESS frameworks such as Twitter&#39;s Bootstrap could be leverage natively within the Rails ecosystem. Both of these gems greatly reduced the barrier to using LESS for the average Rails developer and I wrote them for one simple reason. I wanted to make sure LESS was as close to par with Sass in the Rails asset pipeline as possible. So before I rewrote one single line of Sass to LESS, it was going to have a fair shake. This was no small feat! Especially considering that LESS is the only JavaScript based CSS language to be extended with Rails&#39; asset helpers like &lt;code&gt;asset-data-url()&lt;/code&gt;. Meaning you can hook into assets from any other place in the pipeline directly from LESS, just as you would with Sass.
&lt;/p&gt;

&lt;p&gt;
  Other qualifications? Well I fancy myself a CSS nut and put my skills slightly above average. Most know me as an ActiveRecord or database nerd. But I am just as comfortable doing client side JavaScript and design implementation, especially using HTML5 and CSS3. Very few people know of my &lt;a href=&quot;/2011/09/11/revisiting-my-design-past/&quot;&gt;design background&lt;/a&gt; nor that I have been writing proper presentation layer CSS for over 14 years. Here in the past few years, I have learned to leverage both Sass and the Compass framework like a pro, &lt;a href=&quot;/2010/12/27/let-it-go-moving-from-mephisto-to-jekyll/&quot;&gt;even for this blog&lt;/a&gt;. Here lately, in the project I intended to move to LESS, my Sass usage has become quite impressive. I have extended Sass&#39; color objects to allow &lt;a href=&quot;http://gist.github.com/1932866&quot;&gt;HSV from RGB&lt;/a&gt; conversions for presentation code parity with similar iOS CoreGraphics drawing code in my native iPhone applications. I have even learned to &lt;a href=&quot;http://gist.github.com/1932882&quot;&gt;write Sass mixins&lt;/a&gt; using custom functions and tricks I picked up while reading the Compass source. All this placed the bar pretty high for me on how LESS could take the place of Sass in my little experiment.
&lt;/p&gt;

&lt;h2&gt;What Went Wrong?&lt;/h2&gt;

&lt;p&gt;
  So my bar was pretty high. I set out to not only rewrite my current Sass to LESS, but I fully expected to duplicate much of the things I learned to love about the Compass framework in LESS as well. And like a good open-source citizen, I even prepared a new project that I dubed &lt;a href=&quot;http://github.com/metaskills/protractor&quot;&gt;protractor&lt;/a&gt; on github to share all my work. So what went wrong? Plenty! Every day, mixin by mixin, line by line, I felt MORE pain. LESS was fighting me and it was winning.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/less_variable_property.png&quot; alt=&quot;Does LESS have property interpolation?&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;&lt;/span&gt;
  Some of the bugs I encountered were fixed, like parsing errors for CSS3 keyframes. Others had horrible workarounds that used more code while at the same time lowering legibility. Finally, I came across the one issue on the hundreds of those that exists on LESS&#39; github page that stopped me cold. It was titled &lt;a href=&quot;http://github.com/cloudhead/less.js/issues/36&quot;&gt;variable property&lt;/a&gt; and after learning about it, I decided to stop using LESS for my Rails projects. What are variable properties anyway. Let me show you a common pattern both I and Compass use in a basic contrived example. You may also want to read my comments in that github issue link too. Imagine I have some global colors that I want to mixin to other classes based on a dynamic property. So given this SCSS below:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myWhite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myGray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;140&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;140&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;140&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myBlack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myColorClasses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.white&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#{$property&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;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myWhite&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.gray&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#{$property&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;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myGray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.black&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#{$property&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;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;myBlack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.box&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;myColorClasses(background-color);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  It would output something like the following. Notice how I use the variable string &lt;code&gt;background-color&lt;/code&gt; and generate dynamic properties?
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.box.white&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f0f0f0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.box.gray&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#8c8c8c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.box.black&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#1e1e1e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Astute observers may point out that you can achieve the same with sub classes and be more efficient in the generated CSS too. You would be correct. I did say this was a contrived example. The point is that LESS is not a CSS preprocessor and without the ability to dynamically define property values you will be limited in the ways your LESS based CSS framework can compete with frameworks like Compass. Simply put, LESS will never stack up to Sass.
&lt;/p&gt;

&lt;h2&gt;In All Fairness&lt;/h2&gt;

&lt;p&gt;
  I have mad respect for Alexis Sellier (&lt;a href=&quot;https://twitter.com/#!/cloudhead&quot;&gt;@cloudhead&lt;/a&gt;). By far his skills and open source contributions well outrank my own. As software developers we need to recognize that there are no absolutes and as such, there is no one tool that is right. You have to weight a ton of other factors and choose the tools that are right for you. I firmly believe that as Ruby and or Rails developers that you should choose to learn Sass and Compass vs. LESS and I am basing my opinion heavily on three criteria.
&lt;/p&gt;

&lt;p&gt;
  First is that from a Ruby perspective, Sass will always be more easy to extend and hook into. Second, that LESS lacks a critical feature that I require to author CSS. Lastly, that LESS is not a CSS preprocessors by design and I believe they are the way forward to a &lt;a href=&quot;https://twitter.com/#!/chriseppstein/status/171697822012416000&quot;&gt;better future via the CSSWG&lt;/a&gt;. This is what Sass does very very well. I want to treat CSS as a language and use features like loops, lists and custom functions.
&lt;/p&gt;

&lt;p&gt;
   Your mileage may vary and please make your own decisions. I would be more than happy to followup with any questions on this topic too, so please ask away in the comments below. Lastly, here are a few other articles that talk about LESS and Sass.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://nittygrittyjs.com/blog/why-less-is-a-pain-in-the-sass/&quot;&gt;Why LESS Is a Pain in the Sass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://coding.smashingmagazine.com/2011/09/09/an-introduction-to-less-and-comparison-to-sass/&quot;&gt;An Introduction To LESS, And Comparison To Sass&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 27 Feb 2012 00:00:00 -0500</pubDate>
        <link>/2012/02/27/too-less-should-you-be-using-sass/</link>
        <guid isPermaLink="true">/2012/02/27/too-less-should-you-be-using-sass/</guid>
      </item>
    
      <item>
        <title>Pretty Console Logging With Guard::Jasmine &amp;amp; Black Coffee</title>
        <description>&lt;p&gt;
  OK I know I promised that we would start the dive into &lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;testing your Spine.JS application using Jasmine(rice) in my last article&lt;/a&gt;, but this is a good diversion. If you are new to my latest series on Spine.JS and Jasmine, scroll on down to the bottom to the related section and read back. However, for those that might be more familiar with Jasmine and specifically &lt;a href=&quot;https://github.com/netzpirat/guard-jasmine&quot;&gt;Guard::Jasmine&lt;/a&gt; and ever felt the pain that debugging from that terminal window was lacking, read on! Even if your new to Guard::Jasmine and &lt;a href=&quot;http://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice&lt;/a&gt; I still suggest you setup these elegant hacks to make your testing go that much smoother.
&lt;/p&gt;

&lt;h2&gt;So What Is The Problem?&lt;/h2&gt;

&lt;p&gt;
  Guard::Jasmine allows you to continuously test your JavaScript right from the terminal window just like your Ruby code. The only drawback is that the console debugging is less than helpful. Guard::Jasmine will not allow you do view a string version of every object nor see line numbers of calling files. Both of these are invaluable when your stuck in a testing hole and just need to inspect a few objects. So if you are tired of seeing &lt;code&gt;[object Object]&lt;/code&gt; in your Guard::Jasmine output, let&#39;s fix it right away.
&lt;/p&gt;

&lt;p&gt;
  The first place we need to patch things up is Guard::Jasmine itself. In my &lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;last article&lt;/a&gt; I covered how to monkey patch Jasminerice in a &lt;code&gt;config/initializers/jasminerice.rb&lt;/code&gt; file. My Guard::Jasmine freedom patch will be placed in that same file. Pasted below, this does two things vs the &lt;a href=&quot;http://github.com/netzpirat/guard-jasmine/blob/master/lib/guard/jasmine/runner.rb&quot;&gt;original&lt;/a&gt;. First it changes the &lt;code&gt;report_specdoc_logs&lt;/code&gt; method to not pass &lt;code&gt;true&lt;/code&gt; to the &lt;code&gt;format_log_message&lt;/code&gt; method. Second, the &lt;code&gt;format_log_message&lt;/code&gt; method itself now has the message regular expression changed to a multi-line scan. It will also look out for a custom prefix tag and allow it to pass through. This is for our pretty objects. Anything else now outputs the message with the file and line number, something previously stripped by Guard::Jasmine.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# coding: utf-8&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Jasminerice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jasminerice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;environments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Other Jasminerice patches from:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# http://metaskills.net/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Patch Guard::Jasmine to use a custom formatter for log messages that&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# allows multi-line objects to be printed with the line numbers.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Guard&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Jasmine&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Runner&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;

          &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;report_specdoc_logs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;logs&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:console&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;ss&quot;&gt;:always&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;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:console&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;ss&quot;&gt;:failure&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;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;passed&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;logs&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
                &lt;span class=&quot;no&quot;&gt;Formatter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;    • &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;format_log_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&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;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&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;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;format_log_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/(.*?) in http.+?assets\/(.*)\?body=\d+\s\((line\s\d+)/m&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;pp_prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;[myLog]&#39;&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;msg&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;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$3&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;starts_with?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pp_prefix&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pp_prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; on &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;message&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;k&quot;&gt;end&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;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;A JavaScript Pretty Print Library&lt;/h2&gt;

&lt;p&gt;
  So now that we have Guard::Jasmine not stripping multi-line console messages to one line and printing file and line numbers, we are ready to hook into it. But first we need a JavaScript library that pretty prints objects for us and wrap this all up behind our own interface to &lt;code&gt;console.log&lt;/code&gt;. During my research I found a library called jsDump and decided to &lt;a href=&quot;https://github.com/NV/jsDump&quot;&gt;use a fork of the project on github&lt;/a&gt;. So go download that file and place it in &lt;code&gt;vendor/assets/javascripts/jsDump.js&lt;/code&gt; of your Rails project. Next you will want to add it to your &lt;code&gt;spec/javascripts/spec.js&lt;/code&gt; manifest like so. My below example is pulled right from my previous article and I have placed jsDump right after my jasmine files.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jasminerice&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jsDump&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jasmine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myapp&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;controllers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Logging Helpers - Using BlackCoffee&lt;/h2&gt;

&lt;p&gt;
  In my last article I mentioned how I would talk more about the &lt;code&gt;jasmine-myapp&lt;/code&gt; file in the manifest above. Now is the time. I recommend that this file is place to write all your top level helpers and functions for Jasmine or any other testing libraries in your JavaScript stack. Think of this file as your Ruby &lt;code&gt;test_helper.rb&lt;/code&gt; or your own extensions to &lt;code&gt;ActiveSupport::TestCase&lt;/code&gt;. My advice is that these functions all be written to pollute the time level namespace as other Jasmine helpers do, like the &lt;code&gt;beforeEach&lt;/code&gt; and &lt;code&gt;clearAjaxRequests&lt;/code&gt;. This makes things easier but be conscious of that decision and write functions keeping that in mind.
&lt;/p&gt;

&lt;p&gt;
  The only thing working against is is Sprockets/Tilt rendering CoffeeScript files in their own closure. Which is something you should really not fight! But in this case I think it is fine to have this particular file avoid that. Which allows us to (a) write our helper code in CoffeeScript and (b) use these functions as helpers in the global space like other Jasmine helpers. So enter my &lt;a href=&quot;http://github.com/metaskills/sprockets-blackcoffee&quot;&gt;Sprockets BlackCoffee&lt;/a&gt; gem. This is a simple gem that exposes a CoffeeScript template that uses the &lt;code&gt;--bare&lt;/code&gt; option to keep your file from being wrapped in a closure. All you have to do is give the file a &lt;code&gt;.js.black_coffee&lt;/code&gt; extension and it will just work. So let&#39;s assume you have a &lt;code&gt;spec/javascripts/jasmine-myapp.js.black_coffee&lt;/code&gt; created and the gem installed like so.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:assets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sprockets-blackcoffee&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Finally, here are examples of my logging helpers in the &lt;code&gt;jasmine-myapp&lt;/code&gt; file. The &lt;code&gt;myLogParser&lt;/code&gt; uses jsDump to get back a pretty formatted string of any object if that object is not already a string. The primary logging helper &lt;code&gt;myLog&lt;/code&gt; will prefix your message with &lt;code&gt;[myLog]&lt;/code&gt; so the Guard::Jasmine recognizes the message and outputs only the object. The last helper &lt;code&gt;myLogLine&lt;/code&gt; will do just like the other, but will allow the file and line number tobe printed too.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;myLog&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;obj&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;n&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[myLog]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myLogParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&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;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;myLogLine&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;obj&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;n&quot;&gt;hmLogParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;myLogParser&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;obj&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;string&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jsDump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;In Practice&lt;/h2&gt;

&lt;p&gt;
  Here is an example of a Jasmine spec where I was using console.log before the patches above and what it would output to the terminal.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#= include spec_helper&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;User&#39;&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;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;has been configured with proper attributes&#39;&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;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;email: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;bob@test.com&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toEqual&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bob@test.com&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;User
  ✘ has been configured with proper attributes
    ➤ Expected &#39;foo@bar.com&#39; to equal &#39;bob@test.com&#39;.
    • [object Object]
ERROR: 1 specs, 1 failures
in 0.653 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  There is the totally helpful &lt;code&gt;[object Object]&lt;/code&gt;. But if we now change our code to leverage out patches and change console.log to &lt;code&gt;hmLog @user.attributes()&lt;/code&gt; to use our helper. We will get this. If you need a pretty object with line numbers. Just use &lt;code&gt;hmLogLine&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;User
  ✘ has been configured with proper attributes
    ➤ Expected &#39;foo@bar.com&#39; to equal &#39;bob@test.com&#39;.
    • {
       &quot;email&quot;: &quot;foo@bar.com&quot;,
       &quot;id&quot;: 2
    }
ERROR: 1 specs, 1 failures
in 0.653 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  I hope this is helpful to anyone using Guard::Jasmine with a desire to see better output. If you continue to follow my series, my next post will be a deeper dive into Jasmine testing of Spine.JS applications.
&lt;/p&gt;

&lt;h2&gt;Related&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;Rails &amp;amp; Spine.JS - Using The CoffeeScript Source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/&quot;&gt;Pretty Console Logging With Guard::Jasmine &amp;amp; BlackCoffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/sprockets-blackcoffee&quot;&gt;Sprockets BlackCoffee Gem&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/netzpirat/guard-jasmine&quot;&gt;Guard::Jasmine - Automatically tests your Jasmine specs on Rails.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice - Pain free CoffeeScript testing under Rails 3.1.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 01 Feb 2012 00:00:00 -0500</pubDate>
        <link>/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/</link>
        <guid isPermaLink="true">/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/</guid>
      </item>
    
      <item>
        <title>Rails &amp;amp; Spine.JS - Jasmine Testing Part 2</title>
        <description>&lt;p&gt;
  So this is the third part to my mini series on Rails and &lt;a href=&quot;http://spinejs.com/&quot;&gt;Spine.JS&lt;/a&gt;. Part one &lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;covers an initial setup&lt;/a&gt; and how to include Spine.JS into your Rails project while part two is actually the &lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;first of a tome on how to test&lt;/a&gt; your Spine.JS application. Assuming you have covered the bases there, lets get right down to business and review some of the elegant hacks &amp;trade; yours truly came up with while testing my own Spine.jS application using &lt;a href=&quot;http://github.com/guard/guard&quot;&gt;Guard&lt;/a&gt; and &lt;a href=&quot;http://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;That Engine Is Gonna Need An Overhaul&lt;/h2&gt;

&lt;p&gt;
  So did I mention that Jasminerice is a Rails engine and that you can run your tests by accessing the &lt;code&gt;/jasmine&lt;/code&gt; URL in your development environment&#39;s browser? Good. As uncool as browser testing is, sometimes that it useful. For instance &lt;code&gt;console.log&lt;/code&gt; statements will not show up in your Guard&#39;s test output. But hopefully that is an edge case and you are really using &lt;a href=&quot;http://github.com/netzpirat/guard-jasmine&quot;&gt;guard-jasmine&lt;/a&gt; and watching your specs run in the terminal window. The question now becomes how can I leverage Jasminerice and its associated engine to really test my Spine.JS application with a full-fledged DOM? The answer is simple, let&#39;s hack the Jasminerice engine to load up our application while running the Jasmine specs.
&lt;/p&gt;

&lt;h2&gt;A Review Of Jasmine And HTML Fixtures&lt;/h2&gt;

&lt;p&gt;
  This might be a bit contraversial (or maybe just wrong) but I would like to examine why we might hack the Jasminerice engine for a few minutes. Jasmine bills itself as behavior-driven development for JavaScript, to which I disagree. I think Jasmine first and foremost is an all-purpose testing framework. Depending on how you use it determines what it becomes. In my case, I have been doing a lot of unit testing of my Spine.JS models and supporting libs as I learn the framework and build my system. So my usage now could be called TDD at both a unit and functional level. Later on, I plan on doing higher level integration testing with Jasmine, at this time it will be my BDD tool. Normally I do not get caught up in symantics but I think it is important to understand a few lexical terms before I start showing off how I use Jasmine to test my Spine.JS application.
&lt;/p&gt;

&lt;p&gt;
  Now that I have set my higher order bit for Jasmine as my unit, functional and itegration testing framework for Spine.JS &amp;ndash; I would like to show how my solution below might differ from other practices. Experienced Jasmine users rave about extensions that allow you to load HTML fixtures to functionally test units of code. In fact, the Jasminerice gem includes a custom version of the &lt;a href=&quot;https://github.com/velesin/jasmine-jquery&quot;&gt;jasmine-jquery&lt;/a&gt; library which among other things allows you to do just that. Let me be clear on this, there is nothing wrong with that! As with all things software, proper solutions depends on what you are doing and need. In my case, I believe that testing your Spine.JS application with Rails only needs to hook into your existing application without the need for fixtures and excessive mocking and stubbing.
&lt;/p&gt;

&lt;p&gt;
  My basis for this argument is founded on a few principas that I believe all rich client side JavaScript applications should follow. Most important, the application is a single page load and all other calls to the server happen from that one page via AJAX. Every other part of your Rails application then becomes an API client to the JavaScript application. All views are client side only, most likely in a &lt;code&gt;JST&lt;/code&gt; namespace.
&lt;/p&gt;

&lt;h2&gt;Hacking Jasminerice&lt;/h2&gt;

&lt;p&gt;
  Turns out this is really easy since Jasminerice is just a simple Rails engine with few moving parts. It has a &lt;code&gt;SpecController&lt;/code&gt; that renders a basic layout which requires your application&#39;s JavaScript assets along with Jasmine. The goal is to tell it to render your single application page that loads up your Spine.JS app with a few additional hacks. When done, we are going to have Jasminerice in your full control. This means we get the same CSS and JavaScript as our real application along with a solid foundation to extend Jasminerice at our whim. This leaves us with a clean canvas suitable for Jasmine unit, functional and integraiton testing all wrapped up into one.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# In: config/initializers/jasminerice.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jasminerice&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyApplication&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Concern&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;included&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;to: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;routes_url_helpers&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;jasminerice?&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;current_user&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@current_user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&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;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;ApplicationHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyApplication&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpecController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jasminerice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;template: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;users/home&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;layout: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;application&#39;&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;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Jasminerice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jasminerice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;environments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  There we go, a simple example pulled from my current project. What we are doing here is freedom-patching that spec controller&#39;s index action to render both a template and layout from your application. I also have a &lt;code&gt;MyApplication&lt;/code&gt; module which I include in the &lt;code&gt;Jasminerice::ApplicationHelper&lt;/code&gt; for a few methods that my application view code would expect. In this case a &lt;code&gt;current_user&lt;/code&gt; method and some delegation of URL helpers to the root Rails application. Do not get hung up on what user is returned there too. It is mostly moot as all AJAX calls will be stubbed. Lastly, I made a &lt;code&gt;jasminerice?&lt;/code&gt; view helper and a matching one that I have in my own &lt;code&gt;ApplicationHelper&lt;/code&gt; which returns false. I will show why and how this all fits together later on.
&lt;/p&gt;

&lt;p&gt;
  Now that we have full control and some reflection for Jasminerice, let&#39;s reviw our appliation&#39;s main layout. Here is an example of my &lt;code&gt;app/views/layouts/application.html.haml&lt;/code&gt; file.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;!!!&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;en&#39;&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;head&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:charset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;utf-8&#39;&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;csrf_meta_tags&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;My&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Application&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jasminerice?&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;spec&#39;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_include_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;spec&#39;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;application&#39;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_include_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;application&#39;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&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;body&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;id: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;app&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;data: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  It is really that simple! It has a single condition that says if Jasminerice is loading this page, use the top level &lt;code&gt;spec&lt;/code&gt; CSS and JavaScript asset manifest. If not, render my main application&#39;s CSS and JavaScript manifests. You will also notice that I decouple my Spine&#39;s application initialization from the main JS files and only initialize the app on page load when not running in Jasminerce. This allows us to stub AJAX calls in specs then initialization the Spine.JS app when we are fully ready. So now, let us take a look at what both the &lt;code&gt;spec/javascripts/spec.css&lt;/code&gt; and &lt;code&gt;spec/javascripts/spec.js&lt;/code&gt; manifests may look like.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/*
 *= require jasmine
 *= require application
 */&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.jasmine_reporter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jasminerice&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jasmine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myapp&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;controllers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require_tree&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;nx&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  These should be self explanatory. The &lt;code&gt;spec.css&lt;/code&gt; manifest requires the jasmine styles, then our application&#39;s styles. It then hides the Jasmine reporter element. The &lt;code&gt;spec.js&lt;/code&gt; manifest does something similiar, It first requires the jasminerice manifest, a Jasmine helper called &lt;a href=&quot;https://github.com/pivotal/jasmine-ajax&quot;&gt;jasmine-ajax&lt;/a&gt; but poorly named mock-ajax, then your application&#39;s JavaScript followed by a personal Jasmine helper that we will discuss later. The last lines include all the spec files in each of the lib, models, controller and views directories located in the parent &lt;code&gt;spec/javascripts&lt;/code&gt; directory.
&lt;/p&gt;

&lt;p&gt;
  Congratulations! You are now in full control of both Spine.JS and Jasmine(rice) and how your specs are executed. You have a fully styled DOM that you can happily ignore as you test your unit code. And when the time comes, you can leverage that and you full Spine.JS application from a high level integration perspective. Tune in for my last part which will give some working examples of how to test your Spine.JS application with Jasmine.
&lt;/p&gt;

&lt;h2&gt;Related&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;Rails &amp;amp; Spine.JS - Using The CoffeeScript Source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/&quot;&gt;Pretty Console Logging With Guard::Jasmine &amp;amp; BlackCoffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://spinejs.com/&quot;&gt;Spine.JS - Build Awesome JavaScript MVC Applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice - Pain free CoffeeScript testing under Rails 3.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/pivotal/jasmine-ajax&quot;&gt;Jasmine AJAX - A library for faking Ajax responses in your Jasmine suite.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 17 Jan 2012 00:00:00 -0500</pubDate>
        <link>/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/</link>
        <guid isPermaLink="true">/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/</guid>
      </item>
    
      <item>
        <title>Rails &amp;amp; Spine.JS - Jasmine Testing Part 1</title>
        <description>&lt;p&gt;
  In my &lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;previous article&lt;/a&gt; I talked a little bit about why I decided to use Spine.JS and how to include the CoffeeScript source into your Rails project using git submodules. Now I would like to talk about testing your brand new Spine.JS application. Afterward, be sure to &lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;read the second part&lt;/a&gt; to this article which covers more advanced aspects of your Spine.JS application specs.
&lt;/p&gt;

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

&lt;p&gt;
  OK, so like any good programmer, you want to test your JavaScript web application, but how? Like most, I kept finding that &lt;a href=&quot;http://pivotal.github.com/jasmine/&quot;&gt;Jasmine&lt;/a&gt; was the de facto testing framework that most Rails developers were using. For the newly aquatinted, Jasmine describes itself as behavior-driven and sports a clean spec style using &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; blocks similar to RSpec or MiniTest::Spec. But maybe you, like me, quickly dismissed Jasmine since you sure as hell were not going to hit refresh or F5 in your browser every time you wanted to run your damn specs. After all, this is 2012 and Rails developers do not test with a browser! So why should I start now?
&lt;/p&gt;

&lt;p&gt;
  Luckily I am a big fan of Ruby&#39;s &lt;a href=&quot;https://github.com/guard/guard&quot;&gt;Guard&lt;/a&gt; gem, a simple library that responds to file system events. The guard project literally has TONS of other guard gems that automate everything from running test files to restarting your development server. Thankfully my search for JavaScript testing with Guard in mind brought me right back to Jasmine. Enter the &lt;a href=&quot;https://github.com/netzpirat/guard-jasmine&quot;&gt;guard-jasmine&lt;/a&gt; gem and the wonderful world of a headless JavaScript testing piped right down to your terminal window!
&lt;/p&gt;

&lt;h2&gt;Guard, Jasmine &amp;amp; Jasminerice&lt;/h2&gt;

&lt;p&gt;
  So this is our holy trinity and to be honest, there are a lot of moving parts under the stack. Things will seem to get complicated quick, but don&#39;t worry. I will give you a brief overview of the moving parts and then get right down to the basics of how you can start using Guard and Jasmine to test your Sine.JS application.
&lt;/p&gt;

&lt;p&gt;
  First, let&#39;s cover Guard. It is a simple gem that uses a &lt;code&gt;Guardfile&lt;/code&gt; at the root of your project to control how other guards are triggered. I&#39;ll give you an example Guardfile later. But for starters, &lt;a href=&quot;https://github.com/guard/guard&quot;&gt;read the documentation&lt;/a&gt; on what special libraries may be needed for file system events or notifications on your specific platform. In my case, I us Mac OS X and purchased the latest Growl 1.3. So my example &lt;code&gt;Gemfile&lt;/code&gt; below will have the &lt;a href=&quot;https://rubygems.org/gems/ruby_gntp&quot;&gt;ruby_gntp&lt;/a&gt; gem included in the spec.
&lt;/p&gt;

&lt;p&gt;
  Next up is the guard-jasmine gem. My instructions assume you are running a Rails 3.1 or 3.2 app and that you are taking full advantage of the asset pipeline and CoffeeScript. Many of these details can be found on the &lt;a href=&quot;https://github.com/netzpirat/guard-jasmine&quot;&gt;guard-jamine&#39;s Rails 3.1 setup&lt;/a&gt; section of their readme page. The underlying components of guard-jasmine are two a libs named &lt;a href=&quot;https://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice&lt;/a&gt; and &lt;a href=&quot;http://www.phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt;. Jasminerice is a simple Rails engine that brings in the Jasmine source files to the asset pipeline while running a rack app mounted to &lt;code&gt;/jasmine&lt;/code&gt; to run your specs from your current application. PhantomJS is yet another headless WebKit based on Qt that has a rich JavaScript API which guard-jasmine delegates to. Is your head spinning? Mine was too.
&lt;/p&gt;

&lt;h2&gt;Put It All Together&lt;/h2&gt;

&lt;p&gt;
  Here is the bullet train to getting this stack up and running. First, you will need to get PhantomJS installed. If Homebrew is your thing, just do &lt;code&gt;$ brew install phantomjs&lt;/code&gt;. Or you can &lt;a href=&quot;http://code.google.com/p/phantomjs/downloads/list&quot;&gt;download one of their precompiled binaries&lt;/a&gt; for your specific platform. This is what I opted to do and I just placed the phantomjs in my &lt;code&gt;PATH&lt;/code&gt; somewhere.
&lt;/p&gt;

&lt;p&gt;
  Next, we need to get the gems in our &lt;code&gt;Gemfile&lt;/code&gt;. Here is how mine are setup. I have them in both the &lt;code&gt;:develpment&lt;/code&gt; and &lt;code&gt;:test&lt;/code&gt; groups since Jasminerice runs in both of those Rails environments. I also have that ruby_gntp dependency since I am using Growl on Mac OS X, YMMV.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:development&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jasminerice&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;guard-jasmine&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;ruby_gntp&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So that was easy, now on to our &lt;code&gt;Guardfile&lt;/code&gt;. Here is mine below. Notice how I put my JavaScript related guards into a &lt;code&gt;js&lt;/code&gt; group? This is a seldom used feature of Guard and it means I can monitor only my jasmine specs by starting guard off using &lt;code&gt;$ guard -g js&lt;/code&gt; and my other guards in my &lt;code&gt;ruby&lt;/code&gt; group, like minitest, will be ignored.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;js&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jasmine&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{app/assets/javascripts/myapp/index&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;coffee$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{app/assets/javascripts/myapp/(.+)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;coffee$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&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;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.js.coffee&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{spec/javascripts/(.+)_spec&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;coffee$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&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;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_spec.js.coffee&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{spec/javascripts/spec&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{spec/javascripts/spec_helper&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r{spec/javascripts/jasmine-myapp.*}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spec/javascripts&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This setup assumes a few things. First that you are only testing your Spine.JS application and that those files are in the &lt;code&gt;app/assets/javascripts/myapp&lt;/code&gt; directory. That myapp directory could just be &lt;code&gt;app&lt;/code&gt; in your case if you used the &lt;a href=&quot;http://github.com/maccman/spine-rails&quot;&gt;spine-rails&lt;/a&gt; gem without the &lt;code&gt;--app&lt;/code&gt; option. In my case, that folder is named &lt;code&gt;homemarks&lt;/code&gt;. This Guardfile also assumes that your JavaScript app and specs are CoffeeScript files and that specs are in the &lt;code&gt;spec/javascripts&lt;/code&gt; folder specified by Jasminerice. You are going to want to follow some file naming convention now too. For example if you have a Spine.JS app file in &lt;code&gt;app/assets/javascripts/myapp/models/post.js.coffee&lt;/code&gt;, then you are going to want the matching spec in &lt;code&gt;spec/javascripts/models/post_spec.js.coffee&lt;/code&gt;. So saving each of those files will trigger that specific spec to run. There are also so some watchers on important root files like your spec.js sprockets manifest and your Spine.JS app index. Changing any of those files will result in your entire spec suite running again.
&lt;/p&gt;

&lt;h2&gt;To Be Continued...&lt;/h2&gt;

&lt;p&gt;
  I will go into more details on the &lt;code&gt;spec_helper.js&lt;/code&gt; and &lt;code&gt;jasmine-myapp&lt;/code&gt; files above in &lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;the second part&lt;/a&gt; of this article. For now you should be set to start writing specs like the one below and seeing them run by either visiting the &lt;code&gt;/jasmine&lt;/code&gt; URL of your running Rails application or by using Guard in your terminal window.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;App&#39;&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;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sets el&#39;&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;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toEqual&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#app&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sets the userId as a property on itself&#39;&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;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toEqual&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  &lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Continue to part two...&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Related&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;Rails &amp;amp; Spine.JS - Using The CoffeeScript Source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/&quot;&gt;Pretty Console Logging With Guard::Jasmine &amp;amp; BlackCoffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://spinejs.com/&quot;&gt;Spine.JS - Build Awesome JavaScript
  MVC Applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pivotal.github.com/jasmine/&quot;&gt;Jasmine - BDD for JavaScript. (I disagree, TDD too!)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/netzpirat/guard-jasmine&quot;&gt;Guard Jasmine - Automated Jasmine tests to your console.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/bradphelan/jasminerice&quot;&gt;Jasminerice - Pain free CoffeeScript testing under Rails 3.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.phantomjs.org/&quot;&gt;PhantomJS - Headless WebKit with JavaScript API.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 16 Jan 2012 00:00:00 -0500</pubDate>
        <link>/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/</link>
        <guid isPermaLink="true">/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/</guid>
      </item>
    
      <item>
        <title>Rails &amp;amp; Spine.JS - Using The CoffeeScript Source</title>
        <description>&lt;p&gt;
  Our &lt;a href=&quot;http://addyosmani.com/blog/short-musings-on-javascript-mv-tech-stacks/&quot;&gt;options for JavaScript MVC frameworks&lt;/a&gt; are numerous these days. While working on the third major rewrite of my personal bookmarking application, &lt;a href=&quot;http://homemarks.com/&quot;&gt;HomeMarks&lt;/a&gt;, I decided to learn &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot;&gt;Backbone.js&lt;/a&gt;. Thankfully a local friend of mine &lt;a href=&quot;https://twitter.com/#!/brennandunn/status/153487553062907905&quot;&gt;recommended&lt;/a&gt; that I try &lt;a href=&quot;http://spinejs.com/&quot;&gt;Spine.JS&lt;/a&gt;. I was immediately hooked!
&lt;/p&gt;

&lt;h2&gt;Why Spine.JS?&lt;/h2&gt;

&lt;p&gt;
  Spine.JS is is authored in &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt; and that is a big deal for me. I will never write raw JavaScript again, which I consider, the deprecated syntax. So a JavaScript MVC framework that is written in CoffeeScript means I can read the source, learn from it and even debug it if necessary. Sure, I can read raw JavaScript or just rely on documentation. But nothing beats reading source code. A practice I think good developers follow. So here is an example of the &lt;a href=&quot;https://github.com/documentcloud/backbone/blob/master/backbone.js#L151&quot;&gt;Backbone.js model source&lt;/a&gt; compared to reading &lt;a href=&quot;https://github.com/maccman/spine/blob/master/src/spine.coffee#L83&quot;&gt;Spine.JS model source&lt;/a&gt; and I think you will see the difference.
&lt;/p&gt;

&lt;p&gt;
  Source code legibilty is not the only reason to use Spine.JS. It is also very lightweight and requires no other JavaScript dependencies. Take for example Backbone.js which requies the use of &lt;a href=&quot;http://documentcloud.github.com/underscore/&quot;&gt;Underscore.js&lt;/a&gt; and think for a moment why. Underscore.js makes mundane tasks in JavaScript like itterators and event binding much more friendly. But this is all moot when you are using CoffeeScipt&#39;s loops and comprehensions. And take my advice, CoffeeScript has so much more to offer. One of my personal favorites is the existential operator!
&lt;/p&gt;

&lt;h2&gt;Coffee Time!&lt;/h2&gt;

&lt;p&gt;
  So, are you with me and want to try out Spine? Great! But do not rush in and use the &lt;a href=&quot;http://github.com/maccman/spine-rails&quot;&gt;spine-rails&lt;/a&gt; gem. Sure it gives you a nice way to require the Spine JavaScript files in the asset pipeline and some fancy generators. But when you break it down, there are better ways to get Spine&#39;s source files and who the hell uses generators? I mean, the only useful one is the initial &lt;code&gt;rails g spine:new&lt;/code&gt; generator. Past the initial project setup, the spine-rails gem really does nothing but lock you down to an explicit version of Spine tied to that gem release.
&lt;/p&gt;

&lt;p&gt;
  I highly advise that new-comers to Spine start off with the spine-rails gem and its new project generator. Then quickly switch to just including the spine source using a git submodule. This will give you the benefit of using the source CoffeeScript files and tracking Spine&#39;s git repo which is getting good active development. So let&#39;s live on the edge and read some source. First uninstall the spine-rails gem if you have it and add the Spine project as a git submodule to your git repo.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ mkdir -p vendor/assets/javascripts
$ git submodule add git://github.com/maccman/spine.git vendor/assets/javascripts/spine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This adds the Spine project to your &lt;code&gt;vendor/assets/javascripts/spine&lt;/code&gt; directory. Which means it can now be leveraged by Rails asset pipeline using Sprockets. So if you had used the spine-rails generator above and had your spine requires in &lt;code&gt;app/assets/javascripts/app/index.js.coffee&lt;/code&gt;, you would now be able to change what should have looked like this:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#= require spine&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/manager&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/ajax&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  To something like the following. Since the &lt;code&gt;spine/src&lt;/code&gt; directory is where the source CoffeeScript files from our submodule above and Sprockets will render these just fine, it all just works!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#= require spine/src/spine&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/src/manager&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/src/ajax&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#= require spine/src/route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So now you can easily update your Spine dependency using a simple git workflow with the added benefit that you can open up any of the source CoffeeScript files and learn Spine from the inside out. You can even change the source or put in console debugging to see what is happening and your application files will recompile via Sprockets on the next request.
&lt;/p&gt;

&lt;h2&gt;Related&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/&quot;&gt;Rails &amp;amp; Spine.JS - Using The CoffeeScript Source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/16/rails-and-spine-js-jasmine-testing-part-1/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/01/17/rails-and-spine-js-jasmine-testing-part-2/&quot;&gt;Rails &amp;amp; Spine.JS - Jasmine Testing Part 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/02/01/pretty-console-logging-with-guardjasmine-black-coffee/&quot;&gt;Pretty Console Logging With Guard::Jasmine &amp;amp; BlackCoffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://spinejs.com/&quot;&gt;Spine.JS - Build Awesome JavaScript
  MVC Applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript - A little language that compiles into JavaScript.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/maccman/spine-rails&quot;&gt;The Spine Rails Gem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 15 Jan 2012 00:00:00 -0500</pubDate>
        <link>/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/</link>
        <guid isPermaLink="true">/2012/01/15/rails-and-spine-js-using-the-coffeescript-source/</guid>
      </item>
    
      <item>
        <title>LESS Is More - Using Twitter&#39;s Bootstrap In The Rails 3.1 Asset Pipeline</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/less.png&quot; alt=&quot;LESS - The Dynamic Stylesheet language&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt;
  This weekend I decided to experiment with &lt;a href=&quot;http://lesscss.org/&quot;&gt;LESS CSS&lt;/a&gt; by replacing the existing &lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; and &lt;a href=&quot;http://compass-style.org/&quot;&gt;Compass&lt;/a&gt; code that had been built thus far a small project. Why? Three basic reasons. First, I wanted to see how LESS stacked up. Second, I was intrigued by some of LESS&#39; features, in particular &lt;a href=&quot;http://lesscss.org/#-namespaces&quot;&gt;their namespace support.&lt;/a&gt; Lastly, I wanted to use &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter&#39;s Bootstrap&lt;/a&gt; project as a baseline for my design. Since Rails 3.1 has been out for some time, I was expecting the move to LESS to go considerably smoother than my &lt;a href=&quot;/2011/07/29/use-compass-sass-framework-files-with-the-rails-3.1.0.rc5-asset-pipeline/&quot;&gt;pre-release attempts with Compass and Sass&lt;/a&gt;. I was wrong.
&lt;/p&gt;

&lt;p&gt;
  So the tilt gem already supported LESS templates and that means that Sprockets and the asset pipeline rendering technically did too. But there was &lt;a href=&quot;https://github.com/cowboyd/less.rb/issues/8&quot;&gt;no official less-rails gem&lt;/a&gt; that setup a standard configuration for other gems to hook into. This meant that libraries that distributed the Twitter Bootstrap assets were often hard to use or had inconsistent results. For example, it was not possible to load the Bootstrap&#39;s assets in such as way that let you build on top of the LESS mixins they had build. Nor were those assets namespaced in such a way that would allow you to have a &lt;code&gt;modal.less&lt;/code&gt; asset as it would have conflicted with Bootstrap&#39;s version. So since I apparently have a bunch of free time and I hate building on top of a bad foundation, I set out to learn both &lt;code&gt;Rails::Railtie&lt;/code&gt; and &lt;code&gt;Rails::Engine&lt;/code&gt; to build the proper tools for LESS and Bootstrap in the Rails 3.1 asset pipeline.
&lt;/p&gt;

&lt;h2&gt;New LESS Gems&lt;/h2&gt;

&lt;p&gt;
  I introduce you to both the new &lt;a href=&quot;http://github.com/metaskills/less-rails&quot;&gt;less-rails&lt;/a&gt; and &lt;a href=&quot;http://github.com/metaskills/less-rails-bootstrap&quot;&gt;less-rails-bootstrap&lt;/a&gt; gems. Take a look at the source code if you ever wanted to learn how to implement a simple Rails::Railtie or Engine. But assuming you want to use Twitter&#39;s Bootstrap, here are a few examples to get you started. First just bundle up to less-rails-bootstrap, it will automatically pull in less-rails and less.rb via their dependencies. BTW, I am going to keep the semantic versioning of the less-rails-bootstrap gem in sync with the major and minor versions of the Bootstrap project.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;less-rails-bootstrap&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 1.3.0&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  From here, the easiest way to use Bootstrap is to require it in your &lt;code&gt;application.css&lt;/code&gt; file. Doing so will compile the complete LESS libraries files for Bootstrap. Note how we namespace the files using a simple directory structure.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/*
 *= require twitter/bootstrap
*/&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;#foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* Your styles... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Alternatively, in a file with the &lt;code&gt;.css.less&lt;/code&gt; extension, you can import the entire Bootstrap LESS framework. This will allow you to use Bootstrap&#39;s variables and mixins in your CSS that follows. Remember, unlike other CSS frameworks, requiring or importing Bootstrap will include all the CSS for building a bootstrapped website. If you only want variables or mixins, you will have to import those discreet files, see next section.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;twitter/bootstrap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;#foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.border-radius(4px);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Maybe all you want to use are the variables and mixins that come with Twitter Bootstrap. No problem, just import them individually from you own &lt;code&gt;.css.less&lt;/code&gt; file. In this case only the &lt;code&gt;#foo&lt;/code&gt; selector is output.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;twitter/bootstrap/variables&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;twitter/bootstrap/mixins&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.myButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.border-radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;#foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.myButton(10px);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Using the &lt;a href=&quot;http://twitter.github.com/bootstrap/#javascript&quot;&gt;Bootstrap JavaScript&lt;/a&gt; files is just as easy. Again, you can include all them with a single directive from your &lt;code&gt;application.js&lt;/code&gt; file. Optionally, you can require only the files you need like &lt;code&gt;require twitter/bootstrap/modal&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;//= require twitter/bootstrap&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The less-rails project has already started getting some good feedback. Soon we hope to implement all the features that you may have used in the sass-rails project, &lt;a href=&quot;https://github.com/metaskills/less-rails/issues/1&quot;&gt;like asset pipeline helpers&lt;/a&gt;. One last thing, I wanted to say thanks to &lt;a href=&quot;https://github.com/nmerouze&quot;&gt;Nicolas Mérouze&lt;/a&gt; for opening up the old less-rails gem space on rubygems.org for the new gem!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://lesscss.org/&quot;&gt;LESS - The Dynamic Stylesheet Language&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/less-rails&quot;&gt;LESS-Rails - Official Support For LESS In Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/less-rails-bootstrap&quot;&gt;LESS-Rails-Bootstrap - CSS toolkit from Twitter For Rails 3.1 Asset Pipeline&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/cowboyd/less.rb&quot;&gt;LESS.rb - LESS CSS Rendering From Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass - Syntactically Awesome Stylesheets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/rails/sass-rails&quot;&gt;Sass-Rails - Official Support For Sass In Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://compass-style.org/&quot;&gt;Compass - An Open-Source CSS Authoring Framework&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap - A Toolkit From Twitter Designed To Kickstart Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 26 Sep 2011 00:00:00 -0400</pubDate>
        <link>/2011/09/26/less-is-more-using-twitter-bootstrap-in-the-rails-3-1-asset-pipeline/</link>
        <guid isPermaLink="true">/2011/09/26/less-is-more-using-twitter-bootstrap-in-the-rails-3-1-asset-pipeline/</guid>
      </item>
    
      <item>
        <title>Keep Trying</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/evilruby.jpg&quot; alt=&quot;Ruby Is Evil!&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  One part of Objective-C that I like is being able to send messages to nil objects safely and more so their &lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html&quot;&gt;KVC&lt;/a&gt; and &lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html&quot;&gt;KVO&lt;/a&gt; patterns. In Ruby I often use the &lt;code&gt;#try&lt;/code&gt; method to safely send messages to objects that may be nil at runtime. But one thing I always wanted was a nice way to send a key path, basically a string of methods signatures, to an object in the same way. I give you my simple &lt;code&gt;#try_keypath&lt;/code&gt; method :)
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;methods&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;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NilClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;try_keypath&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;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;nil&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Yup, it is that simple. Let&#39;s see how this would work. Here are a few basic classes that randomly return nested objects. So staring with the &lt;code&gt;Foo&lt;/code&gt; object, we have the possibility to get to some deeply nested info.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;batz&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;wohoo&#39;&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;deep&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Deep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Deep&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:winning&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Finally, here is how it would look and return different results. Man I love Ruby!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Bar:0x108d7dfd0&amp;gt;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Bar:0x108d7ddf0&amp;gt;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Bar:0x108d7d4b8&amp;gt;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;wohoo&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;wohoo&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.batz&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;wohoo&quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {:winning=&amp;gt;true}&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; {:winning=&amp;gt;true}&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_keypath&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar.deep.info&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sat, 17 Sep 2011 00:00:00 -0400</pubDate>
        <link>/2011/09/17/keep-trying/</link>
        <guid isPermaLink="true">/2011/09/17/keep-trying/</guid>
      </item>
    
      <item>
        <title>Revisiting My Design Past</title>
        <description>&lt;p&gt;
  Not many people know that I used to be a designer back in the mid 90&#39;s. Some of you all may have ventured deep into the colophon section of my site and read &lt;a href=&quot;/pages/resume.html&quot;&gt;my resume&lt;/a&gt; which has visual clues of that history. Either way, this page is dedicated to those that had no idea a programmer like myself could come from a design background. Besides, I think it would be cool to share some of my old portfolio pieces.
&lt;/p&gt;

&lt;h2&gt;Beer Labels&lt;/h2&gt;

&lt;p&gt;
  Every good starving artist needs a watering hole. Mine used to be the &lt;a href=&quot;http://maps.google.com/maps/place?client=safari&amp;rls=en&amp;oe=UTF-8&amp;um=1&amp;ie=UTF-8&amp;q=Taphouse+Grill+Norfolk&amp;fb=1&amp;gl=us&amp;hq=Taphouse+Grill&amp;hnear=0x89ba973a5322ca45:0xab99107fce7a1e0a,Norfolk,+VA&amp;cid=13700420888534827238&quot;&gt;Tap House Grill At Ghent&lt;/a&gt;. Doing menu and beer tap design was a great way to pay for the basic staples of life, food and beer! Most of my friends worked there as well. Even after all these years, The Taphouse Grill still seems to be going strong in the same location. So here are a few of those beer tap designs. The &quot;Sex Ina Canoe&quot; tap was a joke against Yuengling Lager and referenced the joke, What does American beer and sex in canoe have in common?
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/beer_labels.png&quot; alt=&quot;My Beer Label Designs For The Taphouse Grill In Norfolk, Virginia&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Logos&lt;/h2&gt;

&lt;p&gt;
  On top of doing tons of 4-color brochure and package design, I used to love doing logo work. The one for the Virginia Stage Company was never used and the middle was a logo for my old online moniker before MetaSkills. The last logo was for a friend&#39;s Mother&#39;s clothing company with heavy art direction.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/logos.png&quot; alt=&quot;My Misc Logo Work&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Drawing Collaborations&lt;/h2&gt;

&lt;p&gt;
  One thing I really enjoyed doing was working with illustrations by my friend Jeff Stephenson. He sketched tons of different things while making his way thru the day. I believe some of his drawings were purely cathartic or helped him cope in one way or another. Most times I would rescue them from the trash bin and scan them in for artwork. The first below is a t-shirt design for the Taphouse Grill&#39;s Cindo De Micro event. I remember piecing different illustrations together with some heavily inspired artwork I gathered while shopping for frozen burritos to eat that night. The end result was awesome. Lastly, what can I about Superfly Bundt Cackes? I think the wings came out nicely.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/cinco_de_micro.jpg&quot; alt=&quot;The Cinco De Micro Taphouse Grill T-Shirt Collaboration With Jeff Stephenson&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/superfly_bundt_cakes.jpg&quot; alt=&quot;Superfly Bundt Cakes Was Just A Silly Experiment&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Experimental&lt;/h2&gt;

&lt;p&gt;
  Even designers have to perform occupational maintenance. I was always reading design articles (before blogs were invented) and learning the different techniques and power of PhotoShop 4 and its numerous plug-ins. Below is a mixed bag of those results.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/shocking.jpg&quot; alt=&quot;Shocking Design Expierment For Lighting Effect In PhotoShop&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/virus.jpg&quot; alt=&quot;Virus Design Expierment With Text And Backgrounds&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/design/laugh_soup.jpg&quot; alt=&quot;A Laugh Soup CD Design Expierment With Text And Backgrounds&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Design Is Important&lt;/h2&gt;

&lt;p&gt;
  I think it is critical that every designer or programmer have a basic skill in the other field. It adds tons of value and streamlines communication across the disciplines. For me however, I have made a career decision that I will never open a PSD file again or try to facilitate the design role. I can if I have to, but not doing it all the time means that the time I do spend designing is not as efficient as someone else in that role. My place is now spent pushing pixels via code!
&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Sep 2011 00:00:00 -0400</pubDate>
        <link>/2011/09/11/revisiting-my-design-past/</link>
        <guid isPermaLink="true">/2011/09/11/revisiting-my-design-past/</guid>
      </item>
    
      <item>
        <title>How Do You Encapsulate Your JavaScript</title>
        <description>&lt;p&gt;
  I ask this question a lot! To Job candidates, friends, and almost any developer that says they work with JavaScript. I believe how you encapsulate your JavaScript is a good indicator on your level of expertise with the language. I find that most beginners have come to JavaScript via jQuery and often define their functions at the top level namespace in some application.js file. These functions are loosely organized and often have no way of sharing simple object state and behavior. A good object oriented programmer would never write their application code like that. JavaScript should be no different and I think jQuery has a part in the blame of those not knowing this.
&lt;/p&gt;

&lt;p&gt;
  I&#39;ve &lt;a href=&quot;/2008/08/18/in-hell-oo-for-homemarks/&quot;&gt;been writing rich object oriented JavaScript&lt;/a&gt; for the better part of 4 years now using &lt;a href=&quot;http://www.prototypejs.org/&quot;&gt;Prototype.js&lt;/a&gt;. That framework has always championed encapsulating your web application&#39;s behavior using a &lt;a href=&quot;http://prototypejs.org/learn/class-inheritance&quot;&gt;standard class and inheritance notation&lt;/a&gt;. Sam Stephenson, the author of Prototype.js, did a good job trying to educate what real JavaScript Object Notation (JSON) is about and how you can encapsulate behavior using Prototype&#39;s Class structure while paying homage to &lt;a href=&quot;http://dean.edwards.name/weblog/2006/03/base/&quot;&gt;Dean Edward&#39;s Base.js&lt;/a&gt; to which it owes its origins.
&lt;/p&gt;

&lt;p&gt;
  So jQuery is the proper winner and choice for anyone wanting to use a JavaScript framework to make working with the DOM in web sites easier. It has awesome event handling and delegation. So many things that Prototype.js lacked. It even has great documentation. About the only bad thing about jQuery is the widely different interfaces to it&#39;s AJAX functions and the arguments passed to their callbacks. Oh, and they totally screwed new JavaScript developers by not sheperding them into learning some sort of way to encapsulate their object behavior. So this article is for those that are not using &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;CoffeeScript&#39;s class system&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot;&gt;Backbone.js&#39;s class system&lt;/a&gt;, or jQuery&#39;s deeply nested plugin class system that is hidden away. So lets get to fixing that. Here is 32 lines of dirt simple JavaScript inheritance.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/* Simple JavaScript Class
   By John Resig. MIT Licensed. &amp;lt;http://ejohn.org/blog/simple-javascript-inheritance/&amp;gt; */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initializing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fnTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/xyz/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xyz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\b&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;_super&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\b&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/.*/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){};&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;initializing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;initializing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&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;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&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;s2&quot;&gt;&quot;function&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&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;s2&quot;&gt;&quot;function&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fnTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_super&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&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;nx&quot;&gt;initializing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  It is &lt;a href=&quot;http://ejohn.org/blog/simple-javascript-inheritance/&quot;&gt;worth reading the comments&lt;/a&gt; John Resig&#39;s blog post for this piece of work as well as the full documentation. My code example above names this &lt;code&gt;JQClass&lt;/code&gt; to avoid namespace collisions with other frameworks. Here is a simple example of its usage.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Your namespace.&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyApp&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;na&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Simple object example for page flash.&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;aPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;aPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alertDiv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;div.flash.alert&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;noticeDiv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;div.flash.notice&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_doFlashFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alertDiv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;notice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_doFlashFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;noticeDiv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;_doFlashFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;silentScroll&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This code example is pulled from a jQuery mobile project I recently finished. The real usage of the flash objects would be numerous as there would be one per page and I have a top level delegate object that finds the active page and finds or create the flash DOM elements. But this should be a good enough example to show why you might choose a simple class and object inheritance system vs putting all your logic in &lt;code&gt;$(document).ready({})&lt;/code&gt; scopes. There are tons of ways to write good OO JavaScript and I hope some find this useful and explore some other ways.
&lt;/p&gt;
</description>
        <pubDate>Tue, 06 Sep 2011 00:00:00 -0400</pubDate>
        <link>/2011/09/06/how-do-you-encapsulate-your-javascript/</link>
        <guid isPermaLink="true">/2011/09/06/how-do-you-encapsulate-your-javascript/</guid>
      </item>
    
      <item>
        <title>jQuery Mobile &amp;amp; Rails</title>
        <description>&lt;p&gt;
  &lt;img class=&quot;ms-Img ms-Img--responsive&quot; src=&quot;/assets/jquery_mobile_rails.png&quot;/&gt;
  I just finished my first dive into using &lt;a href=&quot;http://jquerymobile.com/&quot;&gt;jQuery Mobile&lt;/a&gt; with a Rails application and wanted to share some techniques that came out along the way. Hopefully these will help you if your are using jQuery Mobile with Rails or want to test your mobile application&#39;s integration layer. This post assumes you are somewhat familiar with jQuery Mobile and its basic concepts. So let&#39;s jump right in with a series of helpful tips.
&lt;/p&gt;

&lt;h2&gt;A Mobile Layout&lt;/h2&gt;

&lt;p&gt;
  In my application, I decided to use use a route namespace of &quot;mobile&quot; vs a sub-domain for all controllers and views to reside in. Do what works for you, but I find that using namespaces both helps keep my code organized and simple to maintain. Either way, you should have a layout specific for your mobile application. Mine is in &lt;code&gt;app/views/layout/mobile.html.haml&lt;/code&gt;. As you can see here, I use HAML, so all view examples will be using it vs ERB. Here is a general layout.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;!!!&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;en&#39;&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;head&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:charset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;utf-8&#39;&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;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;viewport&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;width=device-width, initial-scale=1&#39;&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;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;format-detection&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;telephone=no&#39;&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;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;My Mobile App&#39;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:rel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;stylesheet&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css&#39;&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;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://code.jquery.com/jquery-1.6.2.min.js&#39;&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;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js&#39;&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;body&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  A few key points here. First, the meta tag for the &lt;code&gt;viewport&lt;/code&gt; is recommended as a good base. The other meta tag for &lt;code&gt;format-detection&lt;/code&gt; is to disable automatic detection and linking of phone numbers. Phone number detection is way too aggressive and often just links random numbers with periods and hyphens. This means if you want a phone number to call when touched, you will have to use the &lt;code&gt;tel:&lt;/code&gt; link format with the phone number afterward. I recommend the aid of something like the &lt;a href=&quot;https://github.com/floere/phony&quot;&gt;phony&lt;/a&gt; gem for validating and parsing phone number formats. Lastly, the title attribute in the head is really moot. The jQuery Mobile framework will dynamically change the page title as new page DOM elements are loaded in.
&lt;/p&gt;

&lt;h2&gt;Mobile Page IDs&lt;/h2&gt;

&lt;p&gt;
  A typical jQuery Mobile app will have one full page load. All other pages thereafter are loaded via AJAX and inserted into the DOM. Their docs suggest that every page (and form) have a unique id attribute. These ids can be used to link to the DOM page element when navigating around preloaded pages. Simple apps can get by with a few ids like &quot;#home&quot;, &quot;#contact_us&quot;, &quot;#etc&quot;. But if you have a large application, you need a better system to keep track of things.
&lt;/p&gt;

&lt;p&gt;
  Thankfully if you are building your Rails applications in a RESTful manner, it is easy to leverage the route link helpers to generate your page ids. In the example below, I created a method called &lt;code&gt;mobile_page_id&lt;/code&gt; that I placed into a &lt;a href=&quot;http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord&quot;&gt;shared concerns module directory&lt;/a&gt;. From here I mix this into my test helper, and application&#39;s view helper. It is that damn useful! You are going to want to use this everywhere!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# File: app/concerns/mobile_concerns.rb&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MobileConcerns&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Helpers&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mobile_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\A\/mobile\//&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;_&#39;&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;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Mix into your applications helper.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ApplicationHelper&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MobileConcerns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Mix into your test helper of choice.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MobileStoriesTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;IntegrationTest&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MobileConcerns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The &lt;code&gt;mobile_page_id&lt;/code&gt; method is primarily for views. I will cover its usage in testing further down. When called without an argument, it will take the current request path and translate it to a string suitable for a page id. So if you were rendering a &lt;code&gt;/mobile/users/10/avatar&lt;/code&gt; page, the id would be &lt;code&gt;users_10_avatar&lt;/code&gt;. If your application follows RESTful resources in your routes, this can pay dividends. When needed, you can pass a &lt;code&gt;*_path&lt;/code&gt; helper method to get the same id. In this example the same id would come back for &lt;code&gt;mobile_page_id(mobile_user_avatar_path(@user))&lt;/code&gt;. Remember, I am using a &quot;mobile&quot; namespace in my examples and hence my method above strips that out, flavor this helper to your needs. Here is an example of what you might find in &lt;code&gt;app/views/users/avatar.html.haml&lt;/code&gt; using the mobile_page_id. You can see here that I am also setting a title local that is used in the &lt;code&gt;%h1&lt;/code&gt; tag and the &lt;code&gt;data-title&lt;/code&gt; page element attribute. Doing this will show the same title in the header bar as well as the page title.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;User Profile&quot;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mobile_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&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;:role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;page&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&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;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:data&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;:role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;header&#39;&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;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:data&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;:role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;content&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;edit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:data&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;:role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;footer&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;sr&quot;&gt;/...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Easy Data Attributes&lt;/h2&gt;

&lt;p&gt;
  The jQuery Mobile framework will have you typing a lot of data-* attributes into your elements. It uses these from basic page behavior to UI themes. They are literally needed everywhere. If your typing out raw HTML these data attributes get old pretty quick. Thankfully both HAML and the latest Rails 3.1 tag helpers can keep things clean. Both allow hashes to be passed to the data attribute. Keys are dasherized and values are JSON-encoded except for string and symbols.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# HAML Shorthand For:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;div id=&quot;foo&quot; data-role=&quot;page&quot; data-title=&quot;Title&quot; data-rel=&quot;dialog&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;foo&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&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;:role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;page&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Title&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;dialog&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Rails 3.1 Tag Helpers&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;div data-name=&quot;Stephen&quot; data-city-state=&quot;[&amp;amp;quot;Chicago&amp;amp;quot;,&amp;amp;quot;IL&amp;amp;quot;]&quot; /&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&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;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Stephen&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:city_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(Chicago IL)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Dynamically Setting Layout&lt;/h2&gt;

&lt;p&gt;
  Remember how jQuery Mobile only loads the entire page once and then inserts all following pages using AJAX? This means that views after the initial page load do not need the layout when rendered. Depending on the setup of your mobile application, it could become a chore telling each action to conditionally render the layout or not. Imagine a page refresh or a user bookmarking a deep resource node of your mobile app. Thankfully with a little Rails-fu, we can conditionally set the layout to false if the request is an &lt;code&gt;HTTP GET&lt;/code&gt; from an AJAX request. Below is an example of my base mobile controller that all mobile controllers inherit from. Now every action is able to load the entire mobile layout or not.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mobile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;LAYOUT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;mobile&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;freeze&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LAYOUT&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;around_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dynamically_assign_layout&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;dynamically_assign_layout&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;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xhr?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ensure&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;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LAYOUT&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Integration Testing &amp;amp; Capybara-Webkit&lt;/h2&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: After this article I posted a gist titled &lt;a href=&quot;https://gist.github.com/1172519&quot;&gt;Never sleep() using Capybara!&lt;/a&gt; that details how to deal with CSS animations and AJAX requests using Capybara. Check it out too!
&lt;/aside&gt;

&lt;p&gt;
  Those that know me are familiar that I do not use RSpec or Test::Unit but instead opt for a simple testing framework built into Ruby 1.9, &lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;MiniTest::Spec&lt;/a&gt;. I also use the &lt;a href=&quot;https://github.com/thoughtbot/capybara-webkit&quot;&gt;Capybara-WebKit&lt;/a&gt; driver for my acceptance testing in both &lt;a href=&quot;https://github.com/metaskills/holygrail_rails23&quot;&gt;Rails 2.3&lt;/a&gt; and &lt;a href=&quot;https://github.com/metaskills/holygrail_rails31&quot;&gt;Rails 3.1&lt;/a&gt;&#39;s standard integration test layer. Reference the &lt;code&gt;integration_test_helper.rb&lt;/code&gt; file in each link above to learn how to use Capybara-WebKit with your rails app. Thanks to Wyatt Greene for his &lt;a href=&quot;http://techiferous.com/2010/04/using-capybara-in-rails-3/&quot;&gt;original article&lt;/a&gt; on the matter.
&lt;/p&gt;

&lt;p&gt;
  So why the fuss? Well Capybara-WebKit is a headless WebKit browser that you can direct right from your test suite. What makes it so awesome is that it renders web pages with full JavaScript support and is much faster than selenium based Capybara drivers. Since jQuery Mobile is entirely based on JavaScript with HTML &amp;amp; CSS3 - Capybara-WebKit is a perfect candidate to acceptance test your mobile application. The only gotcha is scoping your Capybara actions to a certain page that is dynamically loaded into the DOM. No problem! This is easily solvable using the page ids from the &lt;code&gt;mobile_page_id&lt;/code&gt; helper method I mentioned above. So whatever your testing framework, here are a few helpers that are critical. Assume these are mixed into your test helper.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MobileConcerns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Mentioned above.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;current_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_path&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;div#&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mobile_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&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;s2&quot;&gt;.ui-page-active&quot;&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;current_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&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;within_current_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;within&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_page_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So let&#39;s go over these. First is the &lt;code&gt;current_page_id&lt;/code&gt; method. Most of the time you are going to pass a path argument to this method, since the Capybara&#39;s &lt;code&gt;current_path&lt;/code&gt; will only work correctly on the first page load, not each following AJAX page load which would change the location hash. See how this is using the &lt;code&gt;mobile_page_id&lt;/code&gt; helper mixed in and described above? Next is the &lt;code&gt;current_page&lt;/code&gt; helper. It finds the passed path/id with Capybara&#39;s find method. The &lt;code&gt;within_current_page&lt;/code&gt; leverages Capybara&#39;s &lt;code&gt;within&lt;/code&gt; helper to scope your action to that particular DOM element. Here is a classic example using these.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;be able to navigate to logged in user page and change email&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;login_as&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mobile_homepage_path&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;click_on&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;My Account&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;user_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mobile_user_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Change email&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;new_email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Forgery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;address&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;within_current_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill_in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;email&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_email&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;click_button&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Save Changes&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;must_equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_email&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Hopefully you can see how this simple page id foundation can help you better test your jQuery Mobile app with Capybara-WebKit. What an awesome tool! I sometimes find it hard to believe we are now at the point where we can easily test this much JavaScript in a headless browser directed by Ruby.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://jquerymobile.com/&quot;&gt;jQuery Mobile&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord&quot;&gt;Concerns Module Pattern&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/thoughtbot/capybara-webkit&quot;&gt;Capybara-WebKit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/holygrail_rails23&quot;&gt;Rails 2.3 App w/Capybara-WebKit Integration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/holygrail_rails31&quot;&gt;Rails 3.1 App w/Capybara-WebKit Integration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://techiferous.com/2010/04/using-capybara-in-rails-3/&quot;&gt;Wyatt Green&#39;s Using Capybara In Rails 3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;Using MiniTest::Spec With Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 24 Aug 2011 00:00:00 -0400</pubDate>
        <link>/2011/08/24/jquery-mobile-and-rails/</link>
        <guid isPermaLink="true">/2011/08/24/jquery-mobile-and-rails/</guid>
      </item>
    
      <item>
        <title>Use Compass Sass Framework Files With The Rails 3.1.0.rc5 Asset Pipeline</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: Now that Rails 3.1 is out, just use the &lt;a href=&quot;http://rubygems.org/gems/compass&quot;&gt;latest compass&lt;/a&gt; or pre-release. No hacks needed!
&lt;/aside&gt;

&lt;p&gt;
  This is a simple update to my &lt;a href=&quot;/2011/05/18/use-compass-sass-framework-files-with-the-rails-3.1-asset-pipeline/&quot;&gt;original article&lt;/a&gt; for using compass&#39;s &lt;code&gt;.scss&lt;/code&gt; files with the asset pipeline. This assumes you had this setup working in Rails 3.1.0.rc4, but should be helpful to anybody. The good news is that most everything is wired up.
&lt;/p&gt;

&lt;p&gt;
  First, you are going to need to update your Gemfile. Follow the latest conventions and make sure you have a &lt;code&gt;:assets&lt;/code&gt; group. Use the example below. With the exception of the compass addition to their &quot;rails31&quot; branch, this is what a Rails 3.1.0.rc5 project would generate. It is a good idea to put all your asset pipeline related gems in this group. As the comment says, these would not be required for production as the assumption is would precompile your static assets on deploys. Note, make sure your bundle for sass-rails installs the matching rc5 too.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Gems used only for assets and not required&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# in production environments by default.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:assets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;sass-rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~&amp;gt; 3.1.0.rc&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;coffee-rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~&amp;gt; 3.1.0.rc&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;uglifier&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;compass&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:git&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;git://github.com/chriseppstein/compass.git&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rails31&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now here is a crazy gotcha. Rails 3.1.0.rc5 has changed the application.rb bundler line a little to account for this new :assets group. Find the bundler line and make sure it looks like this.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:assets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Lastly, we need to get the compass files in the the load path. The sass-rails gem has set us up for this. I choose to hook into it using my &lt;code&gt;config/initializers/sass.rb&lt;/code&gt; like so. I imagine that compass will be doing this on its own at some point in the future too. After this you should be all set!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load_paths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loaded_specs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;compass&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full_gem_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/frameworks/compass/stylesheets&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Fri, 29 Jul 2011 00:00:00 -0400</pubDate>
        <link>/2011/07/29/use-compass-sass-framework-files-with-the-rails-3-1-0-rc5-asset-pipeline/</link>
        <guid isPermaLink="true">/2011/07/29/use-compass-sass-framework-files-with-the-rails-3-1-0-rc5-asset-pipeline/</guid>
      </item>
    
      <item>
        <title>Free The Enterprise With Ruby &amp; Master Your Own Domain</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/ftewr_talk.jpg&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; alt=&quot;Free The Enterprise With Ruby &amp; Master Your Own Domain - Title Slide&quot;/&gt;
  &lt;img src=&quot;/assets/ftewr_time.jpg&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; alt=&quot;Free The Enterprise With Ruby &amp; Master Your Own Domain - Our Time Together&quot;/&gt;
  For anyone that did not attend the first &lt;a href=&quot;http://madexpo.us/&quot;&gt;MADExpo (Mid-Atlantic Developer Expo)&lt;/a&gt; this week, here are &lt;a href=&quot;http://www.slideshare.net/metaskills/free-the-enterprise-with-ruby-master-your-own-domain&quot;&gt;my slides posted on slideshare&lt;/a&gt;. This talk centers around 3 basic sections.
&lt;/p&gt;

&lt;p&gt;
  The first is general Open Source and what it can do for you as a software developer to increase your skills and general knowledge. Second, it covers some key open source projects I have been working on. Specifically for &lt;a href=&quot;https://github.com/rails-sqlserver&quot;&gt;SQL Server and and ActiveRecord&lt;/a&gt; which includes projects like &lt;a href=&quot;https://github.com/rails-sqlserver/tiny_tds&quot;&gt;TinyTDS&lt;/a&gt; and the latest accomplishments the &lt;a href=&quot;http://www.engineyard.com/blog/2011/sql-server-10xs-faster-with-rails-3-1/&quot;&gt;SQL Server adapter had done for prepared statement support in Rails 3.1&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  Lastly, I go over what tools have recently been developed specifically for the Windows community to make using Ruby &amp;amp; Rails an easy experience. One is the great &lt;a href=&quot;http://railsinstaller.org/&quot;&gt;Rails Installer&lt;/a&gt; project by Wayne E. Sequin and Luis Lavena. Basically a one click installer for everything from Git, Ruby, Rails, MySQL, TinyTDS &amp;amp; the SQL Server adapter. I even did a new Rails 3.1 project called &lt;a href=&quot;https://github.com/rails-sqlserver/AdventureWorks.Ruby&quot;&gt;AdventureWorks.Ruby&lt;/a&gt; which shows you how to get up and running with your legacy SQL Server databases. Specifically the hardest point, cloning your legacy schema to a fresh test database via the standard Rails&#39; rake tasks.
&lt;/p&gt;
</description>
        <pubDate>Fri, 01 Jul 2011 00:00:00 -0400</pubDate>
        <link>/2011/07/01/free-the-enterprise-with-ruby-and-master-your-own-domain/</link>
        <guid isPermaLink="true">/2011/07/01/free-the-enterprise-with-ruby-and-master-your-own-domain/</guid>
      </item>
    
      <item>
        <title>Bind jQuery Event Handlers To This Object With CoffeeScript</title>
        <description>&lt;p&gt;
  Friends have told me that rich domain objects are seldom wielded when using jQuery to enhance behavior on web pages. I myself have always loved JavaScript as a rich dynamic language first and something for the DOM second. Hence most of my client-side JavaScript follows a robust object-oriented approach similar to Ruby. This is the main reason I have used Prototype.js for so long.
&lt;/p&gt;

&lt;p&gt;
  Since Rails announced both jQuery and CoffeeScript as the defaults in version 3.1, I decided it was high time I starting learning both. I had always known that jQuery bound the &lt;code&gt;this&lt;/code&gt; keyword in event handlers to the DOM object. Something I found totally confusing and unacceptable to someone dealing with their own objects to encapsulate behavior. Today I found two ways of dealing with my problem, a jQuery way and a CoffeeScript way. First a code example.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyObject&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@myDomElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#myDomElement&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;_initBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;handler: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;n&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&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;ss&quot;&gt;_initBehavior: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;$&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;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;resize&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@handler&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;jQuery&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;myObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here is a simple class using CoffeeScript&#39;s methods. It initializes itself with a static property &lt;code&gt;this.myDomElement&lt;/code&gt; to some DOM element on the page with an id of &quot;myDomElement&quot;. It then attaches an event handler to the window&#39;s resize event and logs &lt;code&gt;this&lt;/code&gt; along the way. Simple stuff, the only problem will be that the object logged will not be an instance of MyObject, but the raw DOM element, in this case the window object. One way of fixing this is to use &lt;a href=&quot;http://api.jquery.com/jQuery.proxy/&quot;&gt;jQuery&#39;s proxy&lt;/a&gt; function like so
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;ss&quot;&gt;_initBehavior: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;$&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;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;resize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This works, but seems a little verbose to me and can clutter up your event initialization code. The other way is to use CoffeeScript&#39;s fat arrow operator. An &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;excerpt from their project page&lt;/a&gt; explains it well.
&lt;/p&gt;

&lt;blockquote&gt;
  The fat arrow =&gt; can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with bind. Functions created with the fat arrow are able to access properties of the this where they&#39;re defined.
&lt;/blockquote&gt;

&lt;p&gt;
  So all we have to do is change &lt;code&gt;-&gt;&lt;/code&gt; to &lt;code&gt;=&gt;&lt;/code&gt; for any of our callbacks or event handlers and now &lt;code&gt;this&lt;/code&gt; is our own object and not the DOM element. Hot damn!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyObject&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@myDomElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#myDomElement&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;_initBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;handler: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;n&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&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;ss&quot;&gt;_initBehavior: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;$&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;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;resize&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@handler&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;jQuery&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;myObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 22 May 2011 00:00:00 -0400</pubDate>
        <link>/2011/05/22/bind-jquery-event-handlers-to-this-object-with-coffeescript/</link>
        <guid isPermaLink="true">/2011/05/22/bind-jquery-event-handlers-to-this-object-with-coffeescript/</guid>
      </item>
    
      <item>
        <title>The Browser Is Dead?</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/the_browser_is_dead.png&quot; alt=&quot;Converstation between DHH And Dave Thomas on Rails 3.1&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  This &lt;a href=&quot;https://twitter.com/#!/pragdave/status/62510978893492224&quot;&gt;twitter post by Dave Thomas&lt;/a&gt; sparked an interesting back and forth with DHH on how Rails 3.1 could be more opinionated towards web development for the browser. A short time before &amp;ndash; it was announced that Rails would include CoffeeScript and Sass as defaults for JavaScript and CSS authoring. FWIW, both of these new defaults are in my opinion the best of the breed fore each task. If you have not done so, I suggest taking a quick read down this thread that I put together with screenshots from my Twitter.app.
&lt;/p&gt;

&lt;p&gt;
  The topic is one I have thought often about over the past 6 years. I started writing Rails applications before 1.0 was released and I have seen the changes and felt each one. Having written both web and native iOS apps for &lt;a href=&quot;http://homemarks.com&quot;&gt;HomeMarks.com&lt;/a&gt; and retooling the whole application for each major Rails version, I think it gives me a good insight into the pain here. For instance when &lt;a href=&quot;http://ajaxian.com/archives/rails-rjs-for-ajax-101&quot;&gt;RJS in Rails&lt;/a&gt; first came out, HomeMarks took extreme advantage of it in very clever ways. Pushing rendered partials out and communicating to the browser&#39;s JavaScript environment was fun and rewarding at the time. It also felt really DRY at times.
&lt;/p&gt;

&lt;p&gt;
  As I started to &lt;a href=&quot;/2008/08/18/in-hell-oo-for-homemarks/&quot;&gt;learn more advanced JavaScript techniques&lt;/a&gt; for organizing my rich client code, I ended up rewriting HomeMarks again under the poorly named moniker &lt;a href=&quot;/2008/05/24/the-ajax-head-design-pattern/&quot;&gt;&quot;The AJAX Head Design Pattern&quot;&lt;/a&gt;. It even caught a little bit of attention by the Ajaxian and &lt;a href=&quot;http://voodootikigod.com/ajax-head-design-pattern&quot;&gt;Chris Williams&lt;/a&gt;. Essentially what I ended up building was my own minimal &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot;&gt;backbone.js&lt;/a&gt; in that I had a rich MVC layer all written in JavaScript. This usage of Rails as an API foundation on top of a rich JavaScript application was in my opinion a few years ahead of the average curve. Though it was very rewarding from a JavaScript as a language first, DOM second development perspective &amp;amp; it yielded a very clean way to leverage the same RESTful controller actions used by JavaScript in the browser with a &lt;a href=&quot;/2010/02/12/synchronizing-core-data-with-rails-3-0-0-pre/&quot;&gt;native iOS app that integrated with Core Data&lt;/a&gt;, it still felt like an over achievement or harder than it had to be.
&lt;/p&gt;

&lt;p&gt;
  So as I embark on my third complete rewrite of HomeMarks, I have to think about my tools and techniques again and what the end goal may look like. I have thrown away thousands of lines of OO-JavaScript written in Prototype.js and &lt;a href=&quot;https://gist.github.com/973483&quot;&gt;started rewriting them in CoffeeScript&lt;/a&gt;. Though there are still some tough decisions to be made on what my complete stack will look like and how HomeMarks v3 will hopefully again push the new web forward, I cant help but to agree with both Dave and DHH. I also share James A Rosen&#39;s opinion summed up in &lt;a href=&quot;http://twitter.com/#!/jamesarosen/status/70544535373086720&quot;&gt;this tweet&lt;/a&gt;.

  &lt;blockquote style=&quot;width:220px;&quot;&gt;
    If I had known that RailsConf would be How-to-Use-Rails-as-a-Backend-for-Javascript-Conf, I would&#39;ve gone!
  &lt;/blockquote&gt;
&lt;/p&gt;
</description>
        <pubDate>Sat, 21 May 2011 00:00:00 -0400</pubDate>
        <link>/2011/05/21/the-browser-is-dead/</link>
        <guid isPermaLink="true">/2011/05/21/the-browser-is-dead/</guid>
      </item>
    
      <item>
        <title>Use Compass Sass Framework Files With The Rails 3.1 Asset Pipeline</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: Now that Rails 3.1 is out, just use the &lt;a href=&quot;http://rubygems.org/gems/compass&quot;&gt;latest compass&lt;/a&gt; or pre-release. No hacks needed!
&lt;/aside&gt;

&lt;p&gt;
  The Sprockets 2 gem along with the Tilt gem make it really easy to write JavaScript or CSS using any templating language you desire. The rails defaults are CoffeeScript and Sass. About the &lt;a href=&quot;https://github.com/chriseppstein/compass/tree/stable/frameworks/compass/stylesheets&quot;&gt;best collection of Sass framework files&lt;/a&gt; for easy cross-browser CSS authoring are packaged in the compass framework. Compass even has &lt;a href=&quot;http://compass-style.org/reference/compass/css3/&quot;&gt;great documentation&lt;/a&gt; for using their Sass framework. But what if you want to use those within the asset pipeline provided by Rails? Easy enough!
&lt;/p&gt;

&lt;p&gt;
  First, bundle up the compass, but do not require it. Add this to your &lt;code&gt;Gemfile&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;compass&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Next, add a Sass initializer in &lt;code&gt;config/initializers/sass.rb&lt;/code&gt; and fill it in with the code below. This will add two more load paths to the Sass engine. The first is your default rails/sprockets asset path for stylesheets. It simply let&#39;s you build a deep folder structure in that directory and use relative paths from each file. The second will put the entire compass Sass framework files into the Sass load path.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Sass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Engine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_OPTIONS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:load_paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_paths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;load_paths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/app/assets/stylesheets&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;load_paths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loaded_specs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;compass&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full_gem_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/frameworks/compass/stylesheets&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now in your rails &lt;code&gt;app/assets/stylesheets/foo.scss&lt;/code&gt; file you can use Sass&#39; &lt;code&gt;@import&lt;/code&gt; with paths to the compass framework.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;compass/css3/opacity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#mylogo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;opacity(0.5);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  That is an example loading up the opacity helpers. Your generated css file will look like this! CSS is never going to be the same again!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nf&quot;&gt;#mylogo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;-ms-filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;progid:DXImageTransform.Microsoft.Alpha(Opacity=50)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;progid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DXImageTransform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Microsoft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Opacity&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Wed, 18 May 2011 00:00:00 -0400</pubDate>
        <link>/2011/05/18/use-compass-sass-framework-files-with-the-rails-3-1-asset-pipeline/</link>
        <guid isPermaLink="true">/2011/05/18/use-compass-sass-framework-files-with-the-rails-3-1-asset-pipeline/</guid>
      </item>
    
      <item>
        <title>Speaking At MADExpo</title>
        <description>&lt;p&gt;
  Over the past few months I have been actively working with both &lt;a href=&quot;http://twitter.com/#!/luislavena&quot;&gt;Luis Lavena&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/#!/wayneeseguin&quot;&gt;Wayne E Seguin&lt;/a&gt; to incorporate both &lt;a href=&quot;https://github.com/rails-sqlserver/tiny_tds&quot;&gt;TinyTDS&lt;/a&gt; and the &lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter&quot;&gt;SQL Server Adapter&lt;/a&gt; into the latest release of the &lt;a href=&quot;http://railsinstaller.org/&quot;&gt;Rails Installer for Windows&lt;/a&gt;. Like them, I firmly believe that Ruby&#39;s success is tightly bound to how well we can bring these tools to the Windows platform. So despite that I have no love for the Windows – I do want to see Ruby succeed and help spread the gospel. To this end, I have been working really hard at making both TinyTDS and the adapter a superb backend for ActiveRecord. In fact today, I just released a 3.1 beta that takes advantage of the new prepared statement support.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/madexpo.png&quot; alt=&quot;MADExpo: Mid Atlantic Developer Expo&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  To go one step further in helping Ruby, I have decided to speak at a local conference called the &lt;a href=&quot;http://madexpo2011-collins.eventbrite.com/&quot;&gt;Mid Atlantic Developer Expo&lt;/a&gt; or just MADExpo. The &lt;a href=&quot;http://madexpo.us/Sessions/84&quot;&gt;details for my talk
&lt;/a&gt; are below and if you find any of the &lt;a href=&quot;http://madexpo.us/agenda&quot;&gt;other talks&lt;/a&gt; interesting, I highly advise you to grab a ticket and help me bring the message of Ruby right to the belly of the beast!
&lt;/p&gt;

&lt;h2&gt;Free The Enterprise With Ruby &amp;amp; Master Your Own Domain&lt;/h2&gt;

&lt;p&gt;On the heals of Luis Lavena&#39;s RailsConf talk &quot;&lt;a href=&quot;http://en.oreilly.com/rails2011/public/schedule/detail/19499&quot;&gt;&lt;em&gt;Infiltrating Ruby Onto The Enterprise Death Star Using Guerilla Tactics&lt;/em&gt;&lt;/a&gt;&quot; comes a local and frank talk about the current state of Open Source Software (OSS) participation from Windows developers. Learn what OSS is, what motivates its contributors, and how OSS can make you a stronger developer. Be prepared to fall in love with writing software again!&lt;/p&gt;

&lt;p&gt;We will start off with a 101 introduction to both the Ruby programming language and the Ruby on Rails web application framework. You will learn about ActiveRecord, a powerful ORM that maps rich objects to your databases, and the latest components to use it with SQL Server. As a Rails core contributor and author of the SQL Server stack, I will give you a modern insight into both that will allow you to leverage your legacy data with Ruby.&lt;/p&gt;

&lt;p&gt;Lastly, I will review the bleeding edge tools being actively created for Windows developers to ease the transition to Ruby, Rails and OSS from a POSIX driven world. Many things have changed. It is time to learn and perform some occupational maintenance.&lt;/p&gt;
</description>
        <pubDate>Fri, 06 May 2011 00:00:00 -0400</pubDate>
        <link>/2011/05/06/speaking-at-madexpo/</link>
        <guid isPermaLink="true">/2011/05/06/speaking-at-madexpo/</guid>
      </item>
    
      <item>
        <title>Using MiniTest::Spec With Rails</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: I have renamed the gem that allows you to switch to MiniTest::Spec in Rails to minitest-spec-rails. It is now considered a single gem install with a drop-in to switch to MiniTest::Spec. This article has been updated to reflect this change.
&lt;/aside&gt;

&lt;p&gt;
  So after a few blog post on the subject of MiniTest::Spec, I finally have a simple solution for Rails 3 that leverages MiniTest&#39;s spec DSL. I introduce to you the &lt;a href=&quot;http://github.com/metaskills/minitest-spec-rails&quot;&gt;minitest-spec-rails&lt;/a&gt; gem. MiniTestSpecRails defines a &lt;code&gt;Test::Unit::TestCase&lt;/code&gt; class that subclasses MiniTest::Spec. It implements only what is needed to make Rails happy.
&lt;/p&gt;

&lt;p&gt;
  Once you bundle the gem in your Rails application, it will satisfy the &lt;code&gt;require &quot;test/unit/testcase&quot;&lt;/code&gt; from ActiveSupport&#39;s test case. Tricking it to use MiniTest::Spec instead of MiniTest::Unit. Here is an example Gemfile that shows the usage of MiniTestSpecRails. That is all you have to do!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;minitest-spec-rails&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Advantages?&lt;/h2&gt;

&lt;p&gt;
  Since MinitTest::Spec is built on top of MiniTest::Unit which is technically a replacement for Test::Unit, there is not a lot that can go wrong. With minitest-spec-rails, we finally have a working solution by replacing MiniTest::Spec as the superclass for ActiveSupport::TestCase. This solution is drop dead simple and does not require you to recreate a new test case in your &lt;code&gt;test_helper.rb&lt;/code&gt; or to use generators supplied by gems like &lt;a href=&quot;https://github.com/blowmage/minitest-rails&quot;&gt;minitest-rails&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  This means two things. First, older Rails applications can switch to MiniTest::Spec now by simply installing this gem. Second, as Rails itself evolves to eventually leverage MiniTest::Spec, your test case code will not have to change. About the only gotcha is a few missing assertions available in Test::Unit that are changed or no longer available in MiniTest. For example, &lt;code&gt;assert_raise&lt;/code&gt; vs &lt;code&gt;assert_raises&lt;/code&gt; and there is no such thing as &lt;code&gt;assert_nothing_raised&lt;/code&gt;. Code you would have had to change eventually anyway.
&lt;/p&gt;

&lt;h2&gt;New Assertion Styles&lt;/h2&gt;

&lt;p&gt;
  One thing that I try to do is to change my test assertions from the old Test::Unit style to the new MiniTest::Spec style. I commonly use this &lt;a href=&quot;http://cheat.errtheblog.com/s/minitest&quot;&gt;cheat sheet&lt;/a&gt; to remember them. For instance:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# This:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_not_nil&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Would Become This:&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wont_be_nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Likewise, MiniTest::Spec is consistently getting new features added. One patch that I advocated for now allows the &lt;code&gt;must_be&lt;/code&gt; and &lt;code&gt;wont_be&lt;/code&gt; low-level assertions to work with a predicate method symbol. Meaning, if the symbol ends in a question mark, then it will implicitly call that mehod on the subject for truthy or falsy matching. For instance:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;must_be&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:valid?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Known Issues&lt;/h2&gt;

&lt;p&gt;
  None that I know of yet. Try it out and &lt;a href=&quot;http://github.com/metaskills/minitest-spec-rails/issues&quot;&gt;report any issues to our github project&lt;/a&gt; page. If you have been using minitest-spec-rails, I would love to hear about it too!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;MiniTest::Spec For Rails - &lt;a href=&quot;http://github.com/metaskills/minitest-spec-rails&quot;&gt;Drop in MiniTest::Spec support for Rails 3.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;MiniBacktrace - &lt;a href=&quot;/2011/03/22/mini-backtrace-for-minitest-and-rails/&quot;&gt;Make the Rails backtrace cleaner work.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;MiniTest Rails - &lt;a href=&quot;http://github.com/blowmage/minitest-rails&quot;&gt;Official minitest project for Rails that uses generators.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 26 Mar 2011 00:00:00 -0400</pubDate>
        <link>/2011/03/26/using-minitest-spec-with-rails/</link>
        <guid isPermaLink="true">/2011/03/26/using-minitest-spec-with-rails/</guid>
      </item>
    
      <item>
        <title>MiniBacktrace - For MiniTest &amp; Rails</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE:
  &lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;Using MiniTest::Spec With Rails&lt;/a&gt;
  &amp;amp;
  &lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;From Test::Unit &amp;amp; Shoulda To MiniTest::Spec &amp;amp; MiniShoulda&lt;/a&gt;
&lt;/aside&gt;

&lt;p&gt;
  &lt;a href=&quot;https://github.com/metaskills/mini_backtrace&quot;&gt;MiniBacktrace&lt;/a&gt; allows you to take advantage of the Rails.backtrace_cleaner when using MiniTest. This includes everyone using Rails 3 with Ruby 1.9.
&lt;/p&gt;

&lt;p&gt;
  Just add &#39;mini_backtrace&#39; to your Gemfile&#39;s :test group and your should automatically see a huge difference. Any additions to the Rails.backtrace_cleaner should now work.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;backtrace_cleaner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_silencer&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;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/my_noisy_library/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 22 Mar 2011 00:00:00 -0400</pubDate>
        <link>/2011/03/22/mini-backtrace-for-minitest-and-rails/</link>
        <guid isPermaLink="true">/2011/03/22/mini-backtrace-for-minitest-and-rails/</guid>
      </item>
    
      <item>
        <title>PDFKit Overview &amp; Advanced Usage</title>
        <description>&lt;p&gt;
  Last week I had the pleasure of rewriting 4 years of legacy PDF::Writer code to &lt;a href=&quot;http://github.com/pdfkit/PDFKit&quot;&gt;PDFKit&lt;/a&gt;. Why? Well drawing pdfs in ruby using libraries like PDF::Writer is like composing a webpage with an Etch A Sketch. In short, its a damn chore that involves a bunch of code that mixes both data and presentation. Sure there are gems like &lt;a href=&quot;http://prawn.majesticseacreature.com/&quot;&gt;Prawn&lt;/a&gt; that make this much easier, but nothing beats drawing your pdf code in native HTML and CSS, and that is where &lt;a href=&quot;http://code.google.com/p/wkhtmltopdf/&quot;&gt;wkhtmltopdf&lt;/a&gt; comes in.
&lt;/p&gt;

&lt;p&gt;
  Wkhtmltopdf is an open source project that uses the &lt;a href=&quot;http://www.webkit.org/&quot;&gt;WebKit&lt;/a&gt; rendering engine to convert HTML to native PDF code. This is the muscle behind the PDFKit gem and other projects like &lt;a href=&quot;https://github.com/mileszs/wicked_pdf&quot;&gt;WickedPdf&lt;/a&gt;. In this article I am only going to focus on PDFKit with Rails. But many topics will apply to both PDFKit and WickedPdf since they use wkhtmltopdf on the backside.
&lt;/p&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;
  Installing the PDFKit gem is a no brainer. The hard part is getting the wkhtmltopdf binaries for you platform installed. Thankfully the google project page hosts a batch of static binaries that work on just about every platform. So &lt;a href=&quot;http://code.google.com/p/wkhtmltopdf/downloads/list&quot;&gt;go to their download page&lt;/a&gt; and pick the statically compiled binary that meets your needs. I highly suggest that you get the latest 0.10.0rc2 since some topics below take advantage of recent bug fixes. I have tested both the OSX and i386 on RHEL with success and the release candidate seems very production ready. I suggest placing wkhtmltopdf in &lt;code&gt;/usr/local/bin/wkhtmltopdf&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ which wkhtmltopdf
/usr/local/bin/wkhtmltopdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;The Basic Requirements&lt;/h2&gt;

&lt;p&gt;
  I knew that HTML to PDF generation has its drawbacks, specifically with common headers/footers and page breaks. I happily found out that wkhtmltopdf has a solution for all these problems and can layout PDF pages with pixel perfect precision. So let&#39;s skip over the &lt;a href=&quot;https://github.com/pdfkit/PDFKit/wiki&quot;&gt;basics&lt;/a&gt; and get right down to using PDFKit like a pro. We are going to build out the Rails HTML/CSS layouts and templates that will solve a series of common problems.
&lt;/p&gt;

&lt;p&gt;
  The major reason to use PDFKit and wkhtmltopdf is that we can use the same templating system in Rails that we use to generate other views. This means that we test our PDF view code just like any other Rails code using its built-in functional or integration test cases. Let me say that again, we can TEST our PDF code! A huge win if you have complex conditional view code. So let&#39;s get to it.
&lt;/p&gt;

&lt;h2&gt;The Main PDF Layout&lt;/h2&gt;

&lt;p&gt;
  Sometimes it is useful to start at the end. So the first thing we need is a new layout for all of our pdf templates to use. Here is a &lt;a href=&quot;http://haml-lang.com/&quot;&gt;HAML&lt;/a&gt; file that I recommend you name &lt;code&gt;app/views/layouts/pdf.html.pdf.haml&lt;/code&gt;. Did you see that name? &lt;strong&gt;This is important!&lt;/strong&gt; because Rails allows us to specify template names that can service more than one mime type format. So in this case, the layout will be found when rendering both HTML and .pdf formats.
&lt;/p&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  Somewhere along the way to Rails 3, dual mime type support was lost. Now to render a template/partial for multiple mime types you must remove them all together from the name. Thereby making the file a catch-all for any mime type. In this case, pdf.haml would work.
&lt;/aside&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;!!!&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;en&#39;&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;head&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:charset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;utf-8&#39;&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;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pdfkit-footer_html&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdf_footer_url&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;stylesheet_link_tag&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;host_with_port&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/stylesheets/pdf.css&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  &lt;strong&gt;I recommend that all PDF layouts, templates, and partials use the dual mime type naming convention.&lt;/strong&gt; This will allow you to test your rendered HTML to PDF view code using common DOM techniques. Like &lt;code&gt;assert_select&lt;/code&gt; in rails or maybe &lt;a href=&quot;https://github.com/jnicklas/capybara&quot;&gt;capybara&#39;s&lt;/a&gt; &lt;code&gt;has_selector?&lt;/code&gt;. So given that you may have a print action for your orders controller, you would use &lt;code&gt;print_orders_path(@order)&lt;/code&gt; for your functional tests with DOM assertions and &lt;code&gt;print_orders_path(@order,:format=&gt;:pdf)&lt;/code&gt; for real world usage and/or integration tests. Both formats will render the same partials, templates and layouts if you use that naming structure.
&lt;/p&gt;

&lt;p&gt;
  So that layout file is a real basic HTML5 doctype (which WebKit handles just fine) plus a few special elements. I&#39;ll cover that &lt;code&gt;pdfkit-footer_html&lt;/code&gt; meta tag later on. For now, let&#39;s focus on that &lt;code&gt;pdf.css&lt;/code&gt; stylesheet.
&lt;/p&gt;

&lt;h2&gt;Your PDF CSS&lt;/h2&gt;

&lt;p&gt;
  You might be tempted to utilize your existing site&#39;s stylesheets for a base and then use media/print techniques to override and customize your printed versions. I am of the opinion that your PDF stylesheets should be very basic and easy to layout. To this end, I highly suggest that you start with an HTML reset CSS. In the example below, I have used &lt;a href=&quot;http://yui.yahooapis.com/3.2.0/build/cssreset/reset-min.css&quot;&gt;Yahoo&#39;s CSS reset&lt;/a&gt;. This makes it so that every bit of layout is under your strict control with a common rendering of no margin or padding to throw you off.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/* Reset CSS. http://yui.yahooapis.com/3.2.0/build/cssreset/reset-min.css  */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;#000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;#FFF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;dt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;dd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;fieldset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;textarea&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;td&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;border-collapse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;collapse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;border-spacing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;fieldset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;caption&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;cite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;dfn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;strong&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;caption&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:before&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;abbr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;acronym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-variant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;text-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;text-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;textarea&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;textarea&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;#000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Your Base Foundation */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;12px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;18px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;16px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;14px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;h4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;12px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;strong&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;900&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;hr&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;#000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;#000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Page Breaks */&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.pb_before&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;page-break-before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.pb_after&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;page-break-after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.pbi_avoid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;page-break-inside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;avoid&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The second section of the CSS above is the place where you can put in a few custom styles that fit your needs. In my example I set a series of header font sizes, a base sans-serif font face and an hr tag that can be used as a simple rule. Feel free to add others here like basic styles for data tables, etc. The last section of the CSS file above are page break helpers. The latest version of wkhtmltopdf never breaks text in the middle of the line anymore. So most of the time the default page break behavior will work fine. But for those situations where you need more control, these 3 CSS declarations will serve most of your needs. Let&#39;s take a look at a few examples of their usage. Full details on &lt;a href=&quot;http://www.w3.org/TR/css3-page/&quot;&gt;CSS paged media&lt;/a&gt; can be found on the W3C&#39;s site.
&lt;/p&gt;

&lt;p&gt;
  Use the &lt;code&gt;.pbi_avoid&lt;/code&gt; class on any block level element that you want to make sure is never broken across multiple pages. A great usage would be on each element of an orders line items. It can also be used on any large page element that will certainly fit on one page, but should never be broken up. This is perfect in places where you might have measured the remaining page space before drawing said element. The &lt;code&gt;.pb_before&lt;/code&gt; class will always break to a new page. I found this very useful when printing composite PDF files that combined multiple other PDF actions. So here is another HAML template that renders 3 other PDF full page partials. Each partial can be 1 to many pages. By enclosing each in a &lt;code&gt;&lt;div&gt;&lt;/code&gt; tag that forces a new page break makes sure that we always start a new page when rendering each document.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pb_before&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pdf/orders/print&#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pb_before&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pdf/orders/invoice&#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pb_before&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pdf/orders/picklist&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Custom Headers/Footers&lt;/h2&gt;

&lt;p&gt;
  PDFKit and specifically wkhtmltopdf handles common page headers and footers just wonderfully, though it did take me some time to figure it out. I&#39;ll try to spare you the same pain by detailing the process for a custom footer on each page. In this example we will expect that our custom footer will be approximately .2 inches tall with a current page number next to a total page count.
&lt;/p&gt;

&lt;p&gt;
  Remember that &lt;code&gt;pdfkit-footer_html&lt;/code&gt; meta tag in the pdf layout above? If not, here it is again.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pdfkit-footer_html&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdf_footer_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So what is going on here? Two things really. The first is a way for PDFKit to customize the command arguments passed down to wkhtmltopdf when the page is converted. PDFKit will take any meta tag with a name prefixed using &quot;pdfkit-&quot; and pass down the content attribute as the value to the suffix of the name attribute. In this case &lt;code&gt;--foter-html http://myapp.com/pdf/footer&lt;/code&gt; will be used as a command argument to wkhtmltopdf when rendering templates using that layout file. Note, it is important to use fully qualified URLs for header and footer arguments.
&lt;/p&gt;

&lt;p&gt;
  When it comes to headers and footers, wkhtmltopdf takes the URL to an HTML page, renders it to native PDF code and embeds it automatically for you below or above your page margin. You can control the placement of these in one of two ways. The first is by adjusting the layout of the header/footer HTML page. The second is by adjusting the margin of the parent document. In my case, since I knew my footer was around .2 inches tall, I gave it&#39;s template an internal top margin of 10 pixels and told PDFKit to increase my global .5 inch page margins by .2 inches for the bottom margin using a rails initializer.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;PDFKit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default_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;ss&quot;&gt;:page_size&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Letter&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:margin_top&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.5in&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:margin_right&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.5in&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:margin_bottom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.7in&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:margin_left&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.5in&#39;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So now I know that whatever content I render in my &lt;code&gt;http://myapp.com/pdf/footer&lt;/code&gt; page will fit just nicely on the bottom of each page. But how to generate that content and the custom page numbers? First, let&#39;s make a single pdf resource in our rails route file with a collection action for #footer. Now here is a controller for that resource with a single footer action.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PdfController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&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;perform_caching&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;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;caches_page&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:footer&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;footer&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&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;perform_caching&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  There is not much here past rendering a basic template file with no layout. All the rest is to achieve an important set of caching rules. Ideally the URL argument to &lt;code&gt;--footer-html&lt;/code&gt; would be a static HTML file. However, if want to use Rails templating to render that file, it is important to cache the results. The parent document will request this URL for each page it renders, so you can see how one process could deadlock another if your were not careful. In my example above, I override ActionController&#39;s perform_caching class and instance methods so that all actions in this controller would cache. I recommend committing a cached footer html page to any source control you have for deployment.
&lt;/p&gt;

&lt;p&gt;
  With that out of the way, what about the content of the footer HTML page? Again, here is a HAML template I used. This is very much like my pdf layout with one important difference, some JavaScript that is used to parse the query parameters that wkhtmltopdf tacks onto each header/footer URL request. In the example below I am only using the current page &lt;code&gt;page&lt;/code&gt; and total page count &lt;code&gt;topage&lt;/code&gt; params and inserting those values into to elements. For a full list of all the query parameters, consult the wkhtmltopdf expanded help page.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;!!!&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;en&#39;&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;head&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:charset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;utf-8&#39;&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;stylesheet_link_tag&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;host_with_port&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/stylesheets/pdf.css&quot;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:javascript&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdfInfo&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;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;substring&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;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&amp;amp;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;=&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdfInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unescape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&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;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getPdfInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdfInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdfInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;topage&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;pdfkit_page_current&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;textContent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;pdfkit_page_count&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;textContent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:onload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;getPdfInfo()&#39;&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;div&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#pdfkit_page_numbers&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Page&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;span&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#pdfkit_page_current&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#pdfkit_page_count&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Hopefully this helps anyone looking to use PDFKit or any system that leverages the wkhtmltopdf project. If I missed anything or can help, please leave me a comment. Thanks!
&lt;/p&gt;
</description>
        <pubDate>Sun, 20 Mar 2011 00:00:00 -0400</pubDate>
        <link>/2011/03/20/pdfkit-overview-and-advanced-usage/</link>
        <guid isPermaLink="true">/2011/03/20/pdfkit-overview-and-advanced-usage/</guid>
      </item>
    
      <item>
        <title>GC Tune Ruby 1.9.2 With RVM</title>
        <description>&lt;p&gt;
  Here is a &lt;a href=&quot;https://gist.github.com/856296&quot;&gt;gist&lt;/a&gt; by Sokolov Yura (funny-falcon) that allows you to GC tune Ruby 1.9.2 just like Ruby Enterprise Edition (REE). So all of us using &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;RVM&lt;/a&gt; have no reason not start using this right away. Here are the steps.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ curl https://gist.github.com/raw/856296/patch-1.9.2-gc.patch &amp;gt; ~/192-gc.patch
$ rvm uninstall 1.9.2
$ rvm install 1.9.2 --patch ~/192-gc.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  I have used this RVM hook below for awhile now. It automatically sets and unsets the proper ENV vars to GC tunes my REE. I have now updated it to apply the same GC settings to my newly patched 1.9.2 as well. I recommend this go into &lt;code&gt;~/.rvm/hooks/after_use&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rvm_ruby_string&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;ree&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;ruby-1.9.2&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_HEAP_MIN_SLOTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000000
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_HEAP_SLOTS_INCREMENT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000000
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_HEAP_SLOTS_GROWTH_FACTOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_GC_MALLOC_LIMIT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000000000
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_HEAP_FREE_MIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;500000
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RUBY_FREE_MIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RUBY_HEAP_FREE_MIN&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;RUBY_HEAP_MIN_SLOTS RUBY_HEAP_SLOTS_INCREMENT RUBY_HEAP_SLOTS_GROWTH_FACTOR RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN RUBY_FREE_MIN
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Wed, 09 Mar 2011 00:00:00 -0500</pubDate>
        <link>/2011/03/09/gc-tune-ruby-1-9-2-with-rvm/</link>
        <guid isPermaLink="true">/2011/03/09/gc-tune-ruby-1-9-2-with-rvm/</guid>
      </item>
    
      <item>
        <title>Code Sharing With XCode 4 - An Alternative To Static Libraries</title>
        <description>&lt;p&gt;
  There are many great techniques for sharing code across XCode projects. If that code is tested and build-able by XCode as a static library, Clint Harris&#39; &lt;em&gt;&lt;a href=&quot;http://www.clintharris.net/2009/iphone-app-shared-libraries/&quot;&gt;Easy, Modular Code Sharing Across iPhone Apps: Static Libraries and Cross-Project References&lt;/a&gt;&lt;/em&gt; is really a solid source on the topic. However, this approach is a bit heavy handed for what I wanted to do. Basically if you just have some common header and implementation files that you want to use across multiple XCode projects, this article is for you. The goals for the common code is simple:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Common code needs to be under distinct version control.&lt;/li&gt;
  &lt;li&gt;Common code files need to be editable by XCode from the referencing project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  In this example I will use a contrived example folder called &quot;MetaSupport&quot; as simple directory of common code to use. It includes some global function, a MyApp namespace with class with accessors and a directory of Additions to core classes.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ tree MetaSupport
├── Additions
│   ├── NSArray+MetaSupport.h
│   └── NSArray+MetaSupport.m
├── MyApp.h
├── MyApp.m
├── MyGlobal.h
└── MyGlobal.m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So let&#39;s get started. Below are the steps for adding shared code to our &quot;KillerApp&quot; iOS project. FIrst, right click on the XCode project in your project navigator. Select &quot;New Group&quot;.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xcs_addgroup.png&quot; alt=&quot;XCode 4 Add New Group&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
  Select the newly created group in your project navigator. Now open up the file inspector. It can be found in View =&gt; Utilities =&gt; File Inspector. In the file inspector, set the &quot;Group Name&quot; to match your shared code folder. In this case I named it &quot;MetaSupport&quot;. This is purely optional and simply helps you organize your code.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xcs_addedgroup.png&quot; alt=&quot;XCode 4 Added New Group&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
  Drag all your shared files and folders from your &quot;MetaSupport&quot; directory to the newly created &quot;MetaSupport&quot; group folder. XCode will ask you to choose some options for adding these files. It is important to add folder references and not copy files. Check any targets that apply.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xcs_addfiles.png&quot; alt=&quot;XCode 4 Added New Files&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
  So not only can you see and edit the files belonging to your shared code. You can also commit changes to those files and they will be committed to the shared code&#39;s repository that they reside in, not the current KillerApp projects repo! Hence you can update your shared code for all projects from any project.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xcs_commitfiles.png&quot; alt=&quot;XCode 4 Commit Files&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 03 Mar 2011 00:00:00 -0500</pubDate>
        <link>/2011/03/03/code-sharing-with-xcode-4-an-alternative-to-static-libraries/</link>
        <guid isPermaLink="true">/2011/03/03/code-sharing-with-xcode-4-an-alternative-to-static-libraries/</guid>
      </item>
    
      <item>
        <title>Modern SQL Server &amp; Ruby/Rails Installer For Windows</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/mss_eyarticle.png&quot; alt=&quot;My Modern SQL Server &amp; Rails Engine Yard Article&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  If you have not done so, please go read my article &lt;em&gt;&lt;a href=&quot;http://www.engineyard.com/blog/2011/modern-sql-server-rails/&quot;&gt;Modern SQL Server &amp; Rails&lt;/a&gt;&lt;/em&gt; on the Engine Yard blog. I want to thank Wayne E Seguin for inviting me to write the article. This article details many exciting things that have been happening for those using the SQL Server Adapter for Rails, most notably TinyTDS. The article outlines why everyone still using the ODBC connection mode should really switch over to TinyTDS.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/mss_railsinstaller.png&quot; alt=&quot;Ruby Rails Installer For Windows&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  Many exciting things are happening thanks to Wayne&#39;s new pet project, a &lt;a href=&quot;http://railsinstaller.org/&quot;&gt;ruby and rails installer for Windows&lt;/a&gt;. The adapter and TinyTDS will hopefully dove tail into that. The plan is to include components in the one click installer that will allow Windows users to access their legacy databases using TinyTDS and the SQL Server Adapter. We had even talked on the mailing list about including a demo rails app with the ruby windows installer that would access the northwind database much the same way .Net demos would.
&lt;/p&gt;
</description>
        <pubDate>Thu, 10 Feb 2011 00:00:00 -0500</pubDate>
        <link>/2011/02/10/modern-sql-server-rails/</link>
        <guid isPermaLink="true">/2011/02/10/modern-sql-server-rails/</guid>
      </item>
    
      <item>
        <title>Simple Memcached Reports In Rails</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/memcd.jpg&quot; alt=&quot;Time Machine Exclude Window&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  The Pragmatic Bookshelf&#39;s &lt;a href=&quot;http://www.pragprog.com/titles/memcd/using-memcached&quot;&gt;&lt;em&gt;Using memcached: How to scale your website easily&lt;/em&gt;&lt;/a&gt; is way old. But then again, memcached is still very useful. One of the things I remember reading a long time ago was the stats for your process and how to pull out meaningful reports like a hit ratio, memory and a get to set ration.
&lt;/p&gt;

&lt;p&gt;
  I whipped these up today as a simple way of getting a report using &lt;code&gt;Rails.cache.report&lt;/code&gt;, assuming your cache strategy is set to memcached. Hope others find it useful. BTW, I do not recommend the book, it is too low level for any useful meaning to the average Rails developer.
&lt;/p&gt;

&lt;div class=&quot;h20&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveSupport&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cache&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemCacheStore&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Store&lt;/span&gt;

      &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DateHelper&lt;/span&gt;
      &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NumberHelper&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Higher percentages, above 90%, are good.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hit_ratio&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stat&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;value&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;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;get_hits&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;cmd_get&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&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;100&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;number_to_percentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:precision&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&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;c1&quot;&gt;# Another good statistic to look at is percentage of gets to sets. For a well-tuned application,&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# there should be more gets than sets. High percents are bad, negatives are great.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;gets_to_sets&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stat&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;sets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;cmd_set&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;cmd_get&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_f&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;more_sets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;value&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;more_sets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&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;100&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;number_to_percentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:precision&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;uptime&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stat&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;started_on&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;uptime&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ago&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;utime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance_of_time_in_words&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;started_on&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:started_on&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;started_on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:uptime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;memory&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stat&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;memory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_to_human_size&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;limit_maxbytes&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_to_human_size&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;bytes&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:memory_total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:memory_used&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;rpt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uptime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;rpt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:hit_ratio&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;hit_ratio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;rpt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:gets_to_sets&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;gets_to_sets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;rpt&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;memo&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;k&quot;&gt;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Thu, 27 Jan 2011 00:00:00 -0500</pubDate>
        <link>/2011/01/27/simple-memcached-reports-in-rails/</link>
        <guid isPermaLink="true">/2011/01/27/simple-memcached-reports-in-rails/</guid>
      </item>
    
      <item>
        <title>From Test::Unit &amp; Shoulda To MiniTest::Spec &amp; MiniShoulda</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: If you want to use MiniTest::Spec with Rails please read my &lt;a href=&quot;/2011/03/26/using-minitest-spec-with-rails/&quot;&gt;updated post&lt;/a&gt; and how to use the minitest-spec-rails gem.
&lt;/aside&gt;

&lt;p&gt;
  It seems the MiniTest replacement for Test::Unit in Ruby 1.9 has been presenting itself more and more in my daily readings. Recently was Jamis Buck&#39;s article titled &lt;a href=&quot;http://37signals.com/svn/posts/2742-the-road-to-faster-tests&quot;&gt;The road to faster tests&lt;/a&gt; where he talks about optimizing basecamp&#39;s suite to run faster. And there again, some of the comments below mentioned MiniTest as a solution. That got me thinking on what would it take for me to switch from Test::Unit to MiniTest.
&lt;/p&gt;

&lt;p&gt;
  I love testing! But I am not nuts about large libraries. Looking at you RSpec! &lt;a href=&quot;http://evan.tiggerpalace.com/articles/2010/12/18/ruby-test-unit-sucks-and-why-i-still-use-it/&quot;&gt;Like others&lt;/a&gt;, I believe that you do not need a bloated test framework to get good coverage with a lean and succinct style. A handful of assertions and a simple context structure provided by libraries like &lt;a href=&quot;https://github.com/thoughtbot/shoulda&quot;&gt;Shoulda&lt;/a&gt; is really all I need for both unit and a certain level of functional testing. It is my firm believe that large libraries and semi-magical test code based on things like RSpec will wane in the coming years. Those that base very large test suites on them will suffer the penalty for when an upgrade or test refactor is needed. I could be wrong, time will tell. For now let&#39;s cover how to move to MiniTest for those that like simple Test::Unit and or Shoulda.
&lt;/p&gt;

&lt;p&gt;
  MiniTest provides a drop in replacement for Test::Unit, so I wont cover the details of those basics. What most do not know is that MiniTest comes with a simple MiniTest::Spec DSL that uses &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; blocks much like Shoulda&#39;s &lt;code&gt;context&lt;/code&gt; and &lt;code&gt;should&lt;/code&gt; methods. The similarities were so close that I set out to move all my projects to MiniTest::Spec. The goal would be that none of my exiting suites context/should/before/after code would require a change. The result...
&lt;/p&gt;

&lt;h2&gt;MiniShoulda&lt;/h2&gt;

&lt;p&gt;
  &lt;a href=&quot;https://github.com/metaskills/mini_shoulda&quot;&gt;MiniShoulda&lt;/a&gt; is a small ruby gem that puts a Shoulda DSL on top of MiniTest::Spec. All it really does it alias a few key methods. Here is the core of it now.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MiniTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Spec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MiniTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt;    &lt;span class=&quot;ss&quot;&gt;:before&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:teardown&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:after&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:should&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:it&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:context&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:describe&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;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;should_eventually&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;should eventually &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Should eventually &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  For now, MiniShoulda performs only one monkey patch to MiniTest. There is a critical bug in MiniTest that does not allow the describe/context blocks to use the existing scope of the parent class. I have a &lt;a href=&quot;https://github.com/seattlerb/minitest/pull/9&quot;&gt;pull request&lt;/a&gt; in for the project. Please help out and add a thoughtful comment based on the &lt;a href=&quot;https://github.com/metaskills/minitest/commit/e7cde5bd9e61bc1ac13c7326ef4de23382e3467b&quot;&gt;merits of the patch&lt;/a&gt; and the &lt;a href=&quot;https://gist.github.com/793330&quot;&gt;description of the problem&lt;/a&gt;. No author likes to see simple +1 comments.
&lt;/p&gt;

&lt;h2&gt;The MiniTest Switch&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ gem install mini_shoulda
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Our gem spec will automatically pull in MiniTest version 2.0.2 or greater. Assuming you have a test helper file, the top requires will looks something like this. MiniTest needs that autorun file required or none of your tests will run.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;mini_shoulda&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;minitest/autorun&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  What should I expect? For starters, expect a few of your tests to fail. Especially ones that were happenstantially running linearly and not exercised in isolation. I think there is a technical term for this? Anyways, MiniTest mixes up the test suite each run trough it using a random seed. So it is highly like to expose a few poorly written tests that depended on state leftover from a previous test. Also the MiniTest::Unit underneath MiniTest::Spec does not have a few assertions you may have used. One is &lt;code&gt;assert_raise&lt;/code&gt; which is now the standard convention &lt;code&gt;assert_raises&lt;/code&gt; with an &quot;s&quot;. And finally &lt;code&gt;assert_nothing_raised&lt;/code&gt; has been pulled completely since Test::Unit&#39;s documentation alluded to its uselessness for a long time.
&lt;/p&gt;

&lt;p&gt;
  What does MiniTest::Spec give you besides clean and powerful describe/it organization with before/after setups and teardowns? I highly recommend the &lt;a href=&quot;http://cheat.errtheblog.com/s/minitest&quot;&gt;MiniTest cheat sheet&lt;/a&gt; to find out. See the spec and mock methods at the bottom? As much as I have always like the basic unit testing assertions, I am looking forward to using the must/wont object assertions.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/mini_shoulda&quot;&gt;MiniShoulda Github Project&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/seattlerb/minitest/pull/9&quot;&gt;The MiniTest Describe Pull Resuest&lt;/a&gt; - HELP OUT! COMMENT!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://cheat.errtheblog.com/s/minitest&quot;&gt;MiniTest Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 25 Jan 2011 00:00:00 -0500</pubDate>
        <link>/2011/01/25/from-test-unit-shoulda-to-minitest-spec-minishoulda/</link>
        <guid isPermaLink="true">/2011/01/25/from-test-unit-shoulda-to-minitest-spec-minishoulda/</guid>
      </item>
    
      <item>
        <title>Automating Heroku PG Backups</title>
        <description>&lt;p&gt;
  On December 1st, Heroku &lt;a href=&quot;http://blog.heroku.com/archives/2010/12/1/bundles-deprecation/&quot;&gt;deprecated their bundles add-on&lt;/a&gt; in favor of &lt;a href=&quot;http://blog.heroku.com/archives/2010/11/16/pgbackups/&quot;&gt;their new PG Backups&lt;/a&gt;. Even though there are &lt;a href=&quot;http://groups.google.com/group/heroku/browse_thread/thread/25402694098d393a&quot;&gt;other solutions&lt;/a&gt; for automating backups using this new add-on, none of them met my needs. I like to have a daily DB backup history, just in case you find something bad that happened &quot;n&quot; days earlier. Below is a simple rake task suitable to place in your rails &lt;code&gt;lib/tasks/heroku.task&lt;/code&gt; file. I&#39;ll explain some things I learned below when writing this.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;heroku&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;heroku/command&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;HEROKU_BACKUP_BUCKET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Heroku&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Command&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;selected_application&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-backups&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:heroku&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Use the `heroku pgbackups` with my S3 bucket.&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:backup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:connect_to_s3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capture_heroku_command&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pgbackups&#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heroku_existing_backup?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;last_backup_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; | &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;last_backup_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last_backup_info&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;n&quot;&gt;last_backup_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last_backup_info&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;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Deleting last backup - ID: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_backup_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; BackupTime: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_backup_time&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;heroku_command&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pgbackups:destroy&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last_backup_id&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;heroku_command&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pgbackups:capture&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;backup_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capture_heroku_command&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pgbackups:url&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;backup_filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Heroku&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Command&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;selected_application&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xmlschema&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.dump&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;backup_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backup_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backup_filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backup_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HEROKU_BACKUP_BUCKET&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:connect_to_s3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;establish_connection!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;:access_key_id&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;AMAZON_ACCESS_KEY_ID&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;:secret_access_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;AMAZON_SECRET_ACCESS_KEY&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HEROKU_BACKUP_BUCKET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NoSuchBucket&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HEROKU_BACKUP_BUCKET&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;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;heroku_command&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;cmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Heroku&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Command&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;command&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;cmds&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;capture_heroku_command&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;cmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STDOUT&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flush&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;vg&quot;&gt;$stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;heroku_command&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;cmds&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chomp&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;vg&quot;&gt;$stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&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;heroku_existing_backup?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/no backups/i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Once installed you can run something like &lt;code&gt;bundle exec rake heroku:backup&lt;/code&gt; or if you are not using bundler, &lt;code&gt;rake heroku:backup&lt;/code&gt;. Assuming you have your S3 credentials setup in the ENV variables, it will find or create a private bucket on your S3 account and upload an app-named and time-stamped dump file to that new bucket. If necessary, it &lt;strong&gt;will delete your latest backup&lt;/strong&gt; on Heroku to make room for this new one. The code should be easy to change, so flavor to taste.
&lt;/p&gt;

&lt;p&gt;
  I tried to use the Heroku commands built into their plugin without resorting to command interpolation. The only problem was that the Heroku gem always wants to print to standard out and flush the buffer. So I created a few private helper methods that temporarily shim in a &lt;code&gt;$stdout&lt;/code&gt; replacement that does not flush. This let&#39;s me run the Heroku commands from code and capture what would have been printed to standard out.
&lt;/p&gt;

&lt;p&gt;
  Lastly, since I could not find a way to automate this on Heroku via their cron add-on, I simply added a &lt;code&gt;launchd&lt;/code&gt; plist to my desktop Mac that hit a shell script in my project folder to run the rake task. It is way past my skills to try and get RVM to work in the &lt;code&gt;launchd.plist&lt;/code&gt; system since it is not a true shell. This is why the shell script uses my system ruby (installed via MacPorts). Here is the shell script below and the launchd plist which I placed in &lt;code&gt;~/Library/LaunchAgents&lt;/code&gt; with a name like &lt;code&gt;com.actionmoniker.backupMyApp.plist&lt;/code&gt;. Just run &lt;code&gt;launchctl load ~/Library/LaunchAgents/com.actionmoniker.backupMyApp.plist&lt;/code&gt; and this will run at 4am every morning. If any one finds out how to automate the execution of this rake task on Heroku, please drop me a line!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#! /bin/zsh&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; /Users/kencollins/.zshenv
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /Users/kencollins/repos/myapp &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; /opt/local/bin/rake heroku:backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;plist&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.actionmoniker.backupMyApp&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/Users/kencollins/repos/myapp/lib/bin/backup.sh&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StartCalendarInterval&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;4&lt;span class=&quot;nt&quot;&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Mon, 03 Jan 2011 00:00:00 -0500</pubDate>
        <link>/2011/01/03/automating-heroku-pg-backups/</link>
        <guid isPermaLink="true">/2011/01/03/automating-heroku-pg-backups/</guid>
      </item>
    
      <item>
        <title>Pyr Pressure</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/sasha.png&quot; alt=&quot;Sasha - Our Great Pyrenees&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  It&#39;s a shame I do not do lifestyle posts more often, but with the &lt;a href=&quot;/2010/12/27/let-it-go-moving-from-mephisto-to-jekyll/&quot;&gt;new blog&lt;/a&gt; I hope to change that. To that end, this article is dedicated to our Great Pyrenees Sasha who passed away from bone cancer last month. She was just 7 years old and we only had 3 weeks of good times from the point she was diagnosed with osteosarcoma, a form of bone cancer. I am sure everyone loves their pet(s), we even have another dog and 3 cats. But there is something about a large breed, perhaps more so a Great Pyrenees, that made our loss really painful. It was also the first time I heard about the rainbow bridge, total tear buster.
&lt;/p&gt;

&lt;p&gt;
  Luckily for us, we have a personal friend that breeds Great Pyrenees show dogs in Smithfield, VA and she just so happens to have had a new litter. Determined to turn a bad situation into something positive, we just up&#39;ed our family by two more puppy dogs. You could say I RAID-1&#39;ed my pyr puppies. So we now have a little boy and girl from the same litter. His name is Remy LeBeau and is on the left and her name is Sonya, pictured on the right.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/pyrpups.png&quot; alt=&quot;Remy LeBeau &amp; Sonya - Our New Pyr Puppies&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  They are getting tons of love, attention, and good food. Raising two puppy dogs is so much fun, but it takes a lot of time and patience, especially when training them to go out doors with all the snow we have gotten lately. In the future Kelly and I will enjoy walking these guys around Colonial Williamsburg. Since they look like sheep, our Border Collie will corral them indoors for us as he did for Sasha. We can already tell that Remy will be the protector of the household and probably weigh in around 150 pounds when he grows up.
&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Dec 2010 00:00:00 -0500</pubDate>
        <link>/2010/12/29/pyr-pressure/</link>
        <guid isPermaLink="true">/2010/12/29/pyr-pressure/</guid>
      </item>
    
      <item>
        <title>Let It Go - Moving From Mephisto To Jekyll</title>
        <description>&lt;p&gt;
  Welcome to the new MetaSkills.net! I have moved from Mephisto to &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; and done a complete rewrite of the presentation layer to the latest web standards as a way of staying somewhat sharp with the latest HTML5/CSS3 hotness. In this article, I would like to cover all the gory details of what I learned about moving to Jekyll and the various techniques I have used for the site&#39;s CSS. But first a small history lesson.
&lt;/p&gt;

&lt;p&gt;
  If you are somewhat new to rails, Mephisto was one of the greatest open source blog engines a &lt;a href=&quot;/2008/03/22/metaskills-net-reborn-on-mephisto/&quot;&gt;ruby developer could work with&lt;/a&gt;. But ruby, and especially rails, is a fast paced landscape, making it hard to keep any CMS project up to date. Options like file storage, comment moderation, templating languages, hosting locations and more are all very hard to embody in one project. I think that is why Mephisto&#39;s creator, &lt;a href=&quot;http://twitter.com/#!/technoweenie&quot;&gt;Rick Olson&lt;/a&gt; (@technoweenie), &lt;a href=&quot;http://techno-weenie.net/2010/6/23/you-can-let-go-now/&quot;&gt;announced that he was dropping the project&lt;/a&gt;. Good for him and many thanks for his hard work on all the open source projects he has contributed to! So let&#39;s talk about Jekyll et al.
&lt;/p&gt;

&lt;h2&gt;Migrating Mephisto Data&lt;/h2&gt;

&lt;p&gt;
  So maybe you have an old Mephisto install that you would like to migrate to Jekyll? If so, I have &lt;a href=&quot;https://gist.github.com/756111&quot;&gt;posted a gist&lt;/a&gt; of some rails 3 models that I used to export my data from MySQL to static files following the format required by Jekyll. Simply populate a new rails 3 project with these, fire up a console and do &lt;code&gt;Site.export_jekyll&lt;/code&gt;. This will create a folder in &lt;code&gt;tmp/jekyll_posts&lt;/code&gt; and write a file for each Mephisto article. The posts will contain the YAML front matter for jekyll and hopefully a good starting point of the categories you had assigned to that post. As a bonus, the export will create a &lt;code&gt;tmp/jekyll_posts/rewrites.txt&lt;/code&gt; file that will be very useful to include in a .htaccess file of your jekyll project. An example below.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-apache&quot; data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;nl&quot;&gt;RewriteRule&lt;/span&gt; ^2010/8/19/how-to-clean-a-campfire-room-of-uploads$ /2010/08/19/how-to-clean-a-campfire-room-of-uploads/ [L]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Also included in the gist is a &lt;code&gt;Site.export_jskit&lt;/code&gt; method that will generate an XML file of  your comments to import into Disqus. Though I was able to import my Mephisto comments into Disqus and see them linked from the admin interface, I have yet to get them to show up on the new site. I have a support request open with Disqus and will update this article and the gist with any new information.
&lt;/p&gt;

&lt;h2&gt;Using Jekyll&lt;/h2&gt;

&lt;p&gt;
  The best way you can learn how to use Jekyll is to &lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Sites&quot;&gt;review code of the sites&lt;/a&gt; that use it. If you want to learn more about how I have implemented jekyll, you could &lt;a href=&quot;https://github.com/metaskills/metaskills.net&quot;&gt;browse my source&lt;/a&gt; on github.
&lt;/p&gt;

&lt;p&gt;
  Like many others, I have created a tasks directory in my project root with some executable scripts that help me author, publish and deploy my site. Here are some examples.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env zsh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# File: tasks/scss&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Handy to watch for scss file changes while designing.&lt;/span&gt;
sass --scss --watch _sass:_site/resource --style compact --no-cache

&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env zsh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# File: tasks/jekyll&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Create the site and tidy it.&lt;/span&gt;
setopt rmstarsilent
rm -rf _site/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  sass --style compressed _sass/site.scss:resource/site.css &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;jekyll &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  find _site -name &lt;span class=&quot;s2&quot;&gt;&quot;*.html&quot;&lt;/span&gt; -exec tidy -config &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;/tidy.conf &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env zsh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# File: tasks/deploy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Build and deploy to mini.&lt;/span&gt;
./tasks/jekyll &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  rsync -avz --delete _site/ mini:/Library/WebServer/hosts/metaskills.net &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  mini sudo apachectl restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The first one, &lt;code&gt;task/scss&lt;/code&gt; allowed me to author my site&#39;s CSS using &lt;a href=&quot;http://sass-lang.com/&quot;&gt;SASS&lt;/a&gt; and its newer SCSS syntax, more on that later. This task simply let me publish my site and then style it later by easily saving the source SCSS file and avoiding a long running jekyll command. The second &lt;code&gt;task/jekyll&lt;/code&gt; is my own long winded jekyll command. Basically it will compile my SCSS file, execute my bundled jekyll binary, then post process all my HTML files with tidy. I spent a long time coming up with &lt;a href=&quot;https://github.com/metaskills/metaskills.net/blob/master/tidy.conf&quot;&gt;an appropriate tidy.conf compatible with HTML5 standards.&lt;/a&gt; Perhaps you may find it useful. Lastly, the &lt;code&gt;task/deploy&lt;/code&gt; is just a simple wrapper to my own jekyll command and a final rsync command to my Mac Mini web server. I restart the web server just in case I have made changes to my &lt;code&gt;.htaccess&lt;/code&gt; file.
&lt;/p&gt;

&lt;h2&gt;HTML5&lt;/h2&gt;

&lt;p&gt;
  A personal tech blog is a great platform to try out new things, including the semantic goodness that HTML5 offers. Frankly, it was way past time for me to learn and I found &lt;a href=&quot;http://diveintohtml5.org/&quot;&gt;Mark Pilgrim&#39;s - Dive Into HTML5&lt;/a&gt; really helpful on the topic. The final structure of the blog came out nicely. A post is contained in its own &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element with &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; elements in between. A great way to organize comments and new elements like the &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; so you can associate a machine readable publication date to your post.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;time&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pubdate&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;datetime=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2010-12-27T00:00:00-05:00&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;day&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;27&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;month&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Dec&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;2010&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/time&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Let It Go - Moving From Mephisto To Jekyll&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  ...
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;footer&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;disqus_thread&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    ...
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Presentation - SASS&lt;/h2&gt;

&lt;p&gt;
  This was the second time I have used SASS from the start of a project. The first time was almost a year ago and I must say, it has gotten much nicer with the newer SCSS format. While writing &lt;a href=&quot;https://github.com/metaskills/metaskills.net/blob/master/_sass/site.scss&quot;&gt;my lengthy SCSS file&lt;/a&gt;, I found the following linear organization method very helpful. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Font Declarations&lt;/strong&gt; - With Mixins For Usage.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Global Variables&lt;/strong&gt; - Grids, Colors...&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Vendor Mixins&lt;/strong&gt; - Gradients, Shadows, Transformations...&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Component Mixins&lt;/strong&gt; - Links, Navigation, Fancy Images, Comments...&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Layout Mixins&lt;/strong&gt; - Posts, Footer, Excerpts, Etc&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Final Layout&lt;/strong&gt; - Site Structure (using mixins)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  I think this is important, because it outlines a radical shift from writing raw CSS and really flexes SASS&#39;s &lt;code&gt;@mixin&lt;/code&gt; and &lt;code&gt;@include&lt;/code&gt; features. First it is important to point out that CSS falls into two categories, layout &amp;amp; presentation. Layout CSS is akin to using &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; tags in the old days. It is CSS that controls the structure of your site. After that, all CSS is presentation oriented. It is there to make things look pretty.
&lt;/p&gt;

&lt;p&gt;
  Back in the day, I would put my layout styles at the beginning of my stylesheet, then finish with abstract presentation classes. This works, but sometimes you find yourself deep into a CSS corner and having to whip out &lt;code&gt;!important&lt;/code&gt; declarations to bail yourself out. When writing with SASS, the layout styles are now my last declarations. Why? Because you can include your earlier coded design components as a last step within the structure declarations, thereby ensuring their scope is locked down to the explicit node of your choosing. This helps you keep your layout and presentation CSS in separate and manageable chunks that have logical names while keeping your SASS file from looking like one big long procedural function. It&#39;s OO-CSS at its best!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;...
section#page {
  width: $pagewidth;
  margin: 0px auto;
  min-height: 800px;
  @include cmpnt-links;
  section#content {
    float: right;
    width: $c8width;
    padding-top: $hdrheight + 20px;
    padding-bottom: 20px;
    @include layout-excerpt;
    @include layout-post;
    @include cmpnt-flash;
    @include cmpnt-blockquote;
  }
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Presentation - Simple Grid&lt;/h2&gt;

&lt;p&gt;
  I have previously used CSS grids like &lt;a href=&quot;http://960.gs/&quot;&gt;960.gs&lt;/a&gt; and the &lt;a href=&quot;http://www.1kbgrid.com/&quot;&gt;1Kb Grid&lt;/a&gt;. However, for this project, I decided to flex SASS and my previous CSS knowledge of positioning and clearing for a leaner layout structure. These SCSS variables were enough to let me build out the new layout.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vg&quot;&gt;$cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c1width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&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;vg&quot;&gt;$c2width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&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;vg&quot;&gt;$c3width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c4width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c5width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c6width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c7width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c8width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c9width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$c10width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$pagewidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$colwidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$cols&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$gutterwidth&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;vg&quot;&gt;$cols&lt;/span&gt; &lt;span class=&quot;o&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Presentation - Pseudo Generated Content&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;photobounding&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tr&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;br&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;photoborder&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;photo&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/files/yourpicture.jpg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  &lt;img src=&quot;/assets/jack.png&quot; alt=&quot;Jack Has Many Things&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  We have all seen code like this! It is called divitis, the overuse of span or div elements to structure and style content. I am guilty of doing this too, in fact, that code is from my old blog&#39;s CSS convention page to make a fancy border around a photo. The new MetaSkills.net takes advantage of a pseudo generated content to style complex elements and avoid this. I would like to show you a few examples, but first, learn from the master &lt;a href=&quot;http://twitter.com/#!/necolas&quot;&gt;Nicolas Gallagher&lt;/a&gt; (@necolas) in a series of articles he published for &lt;a href=&quot;http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/&quot;&gt;backgrounds/borders&lt;/a&gt;, &lt;a href=&quot;http://nicolasgallagher.com/pure-css-speech-bubbles/&quot;&gt;speach bubbles&lt;/a&gt;, and &lt;a href=&quot;http://nicolasgallagher.com/pure-css-gui-icons/&quot;&gt;GUI icons&lt;/a&gt; all using pseudo generated content with CSS.
&lt;/p&gt;

&lt;p&gt;
  Using these techniques, I was able to accomplish all the complex styles like my Apple TV navigation and photo fancy borders with simple semantic elements. The image to the right is only surrounded by one &lt;code&gt;&amp;lt;span class=&quot;photofancy&quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;/code&gt; element since you can not generate pseudo content from a &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag. I also used pseudo generated content to remove excessive layout elements too. My complex headers use them to add multiple backgrounds where only one element resides in the code. Learn this technique, it keeps things very clean.
&lt;/p&gt;

&lt;h2&gt;Zepto.js - Something You Need To Watch For&lt;/h2&gt;

&lt;p&gt;
  Lastly, if you have not seen the &lt;a href=&quot;https://github.com/madrobby/zepto&quot;&gt;zepto.js&lt;/a&gt; project, go check it out. It bills itself as the aerogel-weight mobile javascript framework. Besides being incredibly small, I think zepto has some incredible potential when used with backbone.js. I have never used jQuery and always looked at JavaScript thru the eye&#39;s of prototype since most of my JavaScript needs require rich objects first, and access to the DOM second. I&#39;ll make another post on Zepto and why I think it is so bad ass. I use it on the new MetaSkills.net to shim up my custom pygmentize theme.
&lt;/p&gt;

&lt;h2&gt;In Closing&lt;/h2&gt;

&lt;p&gt;
  I am really happy with the new layout and using Jekyll to publish my static blog. I even think the old content carried over well once I tweaked it to the new CSS conventions. One particular old article that embodies all the design aspects of the new layout is &lt;a href=&quot;/2008/9/28/jack-has_many-things&quot;&gt;Jack has_many :things&lt;/a&gt;. It is about a plugin I wrote on grouping ActiveRecord has_many associations. Hope you find some time to try out Jekyll too and let me know what you think of my new site!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://techno-weenie.net/2010/6/23/you-can-let-go-now/&quot;&gt;You Can Let Go Now&lt;/a&gt; - Mephisto ends&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll Project&lt;/a&gt; - A static blog/site generator&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/756111&quot;&gt;Migrate Mephisto Data&lt;/a&gt; - A gist of rails 3 model files&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metaskills/metaskills.net&quot;&gt;MetaSkills.net Source&lt;/a&gt; - On Github.com&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://diveintohtml5.org/&quot;&gt;Dive Into HTML5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/&quot;&gt;Multiple Backgrounds &amp;amp; Borders With CSS2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nicolasgallagher.com/pure-css-speech-bubbles/&quot;&gt;Pure CSS speech bubbles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nicolasgallagher.com/pure-css-gui-icons/&quot;&gt;Pure CSS GUI Icons &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/madrobby/zepto&quot;&gt;Zepto.js&lt;/a&gt; - The aerogel-weight mobile javascript framework&lt;/li&gt;

&lt;/ul&gt;
</description>
        <pubDate>Mon, 27 Dec 2010 00:00:00 -0500</pubDate>
        <link>/2010/12/27/let-it-go-moving-from-mephisto-to-jekyll/</link>
        <guid isPermaLink="true">/2010/12/27/let-it-go-moving-from-mephisto-to-jekyll/</guid>
      </item>
    
      <item>
        <title>TinyTds - A modern, simple and fast FreeTDS library for Ruby using DB-Library</title>
        <description>&lt;p&gt;I just finished the first cut of learning C extensions for ruby and I &lt;a href=&quot;http://github.com/rails-sqlserver/tiny_tds&quot;&gt;present The TinyTds gem&lt;/a&gt;. It is meant to serve the extremely common use-case of connecting, querying and iterating over results to Microsoft SQL Server databases from ruby. Even though it uses FreeTDS&#39;s DB-Library, it is NOT meant to serve as direct 1:1 mapping of that complex C API&lt;/p&gt;

&lt;p&gt;The benefits are speed, automatic casting to ruby primitives, and proper encoding support. It converts all SQL Server datatypes to native ruby objects supporting :utc or :local time zones for time-like types. To date it is the only ruby client library that allows client encoding options, defaulting to UTF-8, while connecting to SQL Server. It also properly encodes all string and binary data. The motivation for TinyTds is to become the de-facto low level connection mode for the SQL Server adapter for ActiveRecord. For further details see the special thanks to Erik Bryn for his help, the authors/contributors of the Mysql2 gem for inspiration, and Yehuda Katz for articulating ruby&#39;s need for proper encoding support. Please read up on it here.&lt;/p&gt;
</description>
        <pubDate>Mon, 18 Oct 2010 00:00:00 -0400</pubDate>
        <link>/2010/10/18/tinytds-a-modern-simple-and-fast-freetds-library-for-ruby-using-db-library/</link>
        <guid isPermaLink="true">/2010/10/18/tinytds-a-modern-simple-and-fast-freetds-library-for-ruby-using-db-library/</guid>
      </item>
    
      <item>
        <title>How To Clean A Campfire Room Of Uploads_redirect</title>
        <description></description>
        <pubDate>Thu, 19 Aug 2010 00:00:00 -0400</pubDate>
        <link>/2010/8/19/how-to-clean-a-campfire-room-of-uploads</link>
        <guid isPermaLink="true">/2010/8/19/how-to-clean-a-campfire-room-of-uploads</guid>
      </item>
    
      <item>
        <title>How To Clean A Campfire Room Of Uploads</title>
        <description>&lt;p&gt;For us at work, our uploads to campfire are really transitory. Most of the time they are simple screenshots around a current topic. Every now and then vacation photos or even movies, at the end of the day, none of it has value after a certain amount of time. To us as the real value of campfire is our textual transcripts.&lt;/p&gt;

&lt;p&gt;This morning after 4 years of campfire, we were real close to our 1GB limit of uploads. Time for a clean up. I found no easy way of automating this, so I turned to the Tinder gem. It has a nice interface to the campfire API using HTTParty as the backend. I found out that there was no easy way to delete uploads too. So after some good ole fashion DOM inspection and knowing rails application conventions, I found my own interface. Below is a little script I used to clean up our room this morning. It basically loops thru a rooms uploads, 5 at a time, and deletes them. Pausing for a quarter of a second between each so I don&#39;t freak out the new 37signals administrator :)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rubygems&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;tinder&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CampfireUploadCleaner&lt;/span&gt;

  &lt;span class=&quot;nc&quot;&gt;CF_DOMAIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;mydomain&#39;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;CF_ROOM&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;My Room Name&#39;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;CF_TOKEN&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;MY_CF_TOKEN&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&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;vi&quot;&gt;@campfire&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Tinder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Campfire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CF_DOMAIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CF_TOKEN&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;room&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@room&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@campfire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_room_by_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CF_ROOM&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;connection&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:connection&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;delete_uploads&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uploads&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:uploads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;uploads&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uploads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;id&#39;&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;upload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;name&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/uploads/delete/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;?n=0&quot;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Deleted: [&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;] &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;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;sleep&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sweep_uploads&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;delete_uploads&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;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cleaner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CampfireUploadCleaner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cleaner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delete_uploads&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Deletes the top 5 uploads.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cleaner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sweep_uploads&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Deletes all uploads.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The upload hash actually contains much more than just the id and name of the upload. There is a timestamp, filetype and other attributes. So if you wanted to extend this script, you could. I did not spent a lot of time with it, but I never figured out how to get more than the top 5 uploads too. I&#39;m sure some param hacking would yield some good results.&lt;/p&gt;
</description>
        <pubDate>Thu, 19 Aug 2010 00:00:00 -0400</pubDate>
        <link>/2010/08/19/how-to-clean-a-campfire-room-of-uploads/</link>
        <guid isPermaLink="true">/2010/08/19/how-to-clean-a-campfire-room-of-uploads/</guid>
      </item>
    
      <item>
        <title>Protip Exclude Your Rvm Install From Timemachine Backups_redirect</title>
        <description></description>
        <pubDate>Fri, 06 Aug 2010 00:00:00 -0400</pubDate>
        <link>/2010/8/6/protip-exclude-your-rvm-install-from-timemachine-backups</link>
        <guid isPermaLink="true">/2010/8/6/protip-exclude-your-rvm-install-from-timemachine-backups</guid>
      </item>
    
      <item>
        <title>Protip: Exclude Your RVM Install From Time Machine Backups</title>
        <description>&lt;p&gt;
  You may not realize it, but that &lt;code&gt;~/.rvm&lt;/code&gt; directory is getting big and may be hurting your Time Machine backups. Especially if you are doing a lot of development. I just checked mine today.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ du -skh ~/.rvm/gems
1012M   /Users/kencollins/.rvm/gems
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Ouch! That&#39;s around 1gig of stuff that is pointless to backup just in the gems directory. I frequently blow away certain rubies and install them again using &lt;a href=&quot;/2010/7/30/the-rvm-ruby-api&quot;&gt;various rake tasks&lt;/a&gt; and just found out today that you have to pass the --gems option to rvm remove to clean those old gemsets out. Either way, that whole rvm directory can just be ignored from Time Machine backups. Here is how, there is really only one tricky part.
&lt;/p&gt;

&lt;p&gt;
  First, open up your System Preferences, then open up the Time Machine pref pane. From here click on the &quot;Options...&quot;. Within this window you will be able to add a folder to be excluded from backup. Hit the &quot;+&quot; button to add a directory. Now here is the tricky part, your rvm directory is prefixed with a period and hence is invisible to the normal finder windows. Thankfully all Mac file windows can use a keyboard shortcut. Hit &lt;code&gt;Command+Shift G&lt;/code&gt;. That will blind down a &quot;Go to the folder:&quot; window. Simply type in &lt;code&gt;~/.rvm&lt;/code&gt; here and hit &quot;Go&quot;. Now choose &quot;Exclude&quot; from the main file window. Your done!
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/exclude_from_timemachine.gif&quot; alt=&quot;Time Machine Exclude Window&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 06 Aug 2010 00:00:00 -0400</pubDate>
        <link>/2010/08/06/protip-exclude-your-rvm-install-from-timemachine-backups/</link>
        <guid isPermaLink="true">/2010/08/06/protip-exclude-your-rvm-install-from-timemachine-backups/</guid>
      </item>
    
      <item>
        <title>The Rvm Ruby Api_redirect</title>
        <description></description>
        <pubDate>Fri, 30 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/7/30/the-rvm-ruby-api</link>
        <guid isPermaLink="true">/2010/7/30/the-rvm-ruby-api</guid>
      </item>
    
      <item>
        <title>The RVM Ruby API - Setting Up A CI System For The SQL Server Adapter</title>
        <description>&lt;p&gt;
  A few weeks ago I started looking into the &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;Ruby Version Manager (RVM)&lt;/a&gt; project to help me build a better testing setup for both my day job and the &lt;a href=&quot;http://github.com/rails-sqlserver/activerecord-sqlserver-adapter&quot;&gt;ActiveRecord SQL Server Adapter&lt;/a&gt;. In a &lt;a href=&quot;/2009/9/5/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more&quot;&gt;previous article&lt;/a&gt; I covered details of how to get a development stack up and running for Rails with SQL Server using MacPort&#39;s. This article will cover some new additions to that goal, but first and primarily, I wanted to talk about the wonders of RVM and it&#39;s new ruby API.
&lt;/p&gt;

&lt;p&gt;
  So like any good agile software gardner tasked with building a continuous integration system, I wanted to do it in such a way that was completely automated using rake. My first cut at said rake task used ruby&#39;s Kernel.system to issue &lt;code&gt;rvm&lt;/code&gt; commands down to the shell. This failed horribly! Basically no matter how hard I tried, I could not hit the rvm shell function from ruby&#39;s system command. It kept using the rvm binary which can not change the local shell environment and hence do very little magic that RVM allows. Thankfully &lt;a href=&quot;http://twitter.com/wayneeseguin&quot;&gt;@wayneeseguin&lt;/a&gt; pointed me to the new RVM ruby API and &lt;a href=&quot;http://blog.ninjahideout.com/posts/the-path-to-better-rvm-and-passenger-integration&quot;&gt;this article on how to use it for passenger&lt;/a&gt;. I immediately started to switch my rvm rake tasks to use the new RVM API and was just floored with how well it did. Below is a copy of that rake task. Take a look over it and read below for details and how I have used this with the SQL Server stack.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;MYPROJECT_RUBIES&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;s1&quot;&gt;&#39;ruby-1.8.6-p388&#39;&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;:alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;myprj186&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.99991&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;ruby-1.8.7-p299&#39;&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;:alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;myprj187&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.99991&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;ruby-1.9.1-p378&#39;&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;:alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;myprj191&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.99991&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;ruby-1.9.2-head&#39;&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;:alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;myprj192&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.99992pre3&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&#39;ree-1.8.7-2010.02&#39;&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;:alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;myprjree&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;0.99991&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rvm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@rvm_setup&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rvm_lib_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`echo $rvm_path`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/lib&quot;&lt;/span&gt;
      &lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_lib_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_lib_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rvm&#39;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;tmpdir&#39;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@rvm_setup&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;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:install&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:all&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;:setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:rubies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:gems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rubies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;installed_rubies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;list_strings&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;MYPROJECT_RUBIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;installed_rubies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Rubie &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; already installed.&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;with_my_environment_vars&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;good_msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Rubie &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; installed.&quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;bad_msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Failed &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; install! Check RVM logs here: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/log/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Rubie &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; installation inprogress. This could take awhile...&quot;&lt;/span&gt;
            &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_install_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;good_msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bad_msg&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;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alias_create&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MYPROJECT_RUBIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:alias&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@myproject&quot;&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;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rvm_each_rubie&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ruby-odbc-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myproject_current_rubie_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:odbc&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;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rm -rf &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*&quot;&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: RubyODBC downloading &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;curl -O http://www.ch-werner.de/rubyodbc/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&quot;&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: RubyODBC extracting clean work directory...&quot;&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;tar -xf &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&quot;&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;odbc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ext&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: RubyODBC configuring...&quot;&lt;/span&gt;
            &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ruby&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;extconf.rb&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--with-odbc-dir=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_odbc_dir&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: RubyODBC make and installing for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_current_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;
            &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;make &amp;amp;&amp;amp; make install&quot;&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;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:gems&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Installing our app gems.&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rvm_each_rubie&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;myproject_gem_specs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;spec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rvm_install_gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remove&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;myproject_rubies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;rubie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myproject_rubies&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;MYPROJECT_RUBIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&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;rubie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@myproject&quot;&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;myproject_current_rubie_info&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;MYPROJECT_RUBIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_current_rubie_name&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;myproject_gem_specs&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;rails&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2.3.8&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;activerecord-sqlserver-adapter&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2.3.8&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;erubis&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2.6.6&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;haml&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;3.0.13&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;mocha&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;0.9.8&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&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;rvm_each_rubie&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;myproject_rubies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reset_current!&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;rvm_current_rubie_name&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rvm_current_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;@myproject&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&#39;&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;rvm_current_name&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expanded_name&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;rvm_gem_available?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ruby_eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;require &#39;rubygems&#39; ; print Gem.available?(&#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;true&#39;&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;rvm_install_gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rvm_gem_available?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Gem &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; already installed in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_current_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;info: Installing gem &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_current_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;perform_set_operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;install&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;-v&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stdout&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;for_macports?&lt;/span&gt;
  &lt;span class=&quot;sb&quot;&gt;`uname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Darwin&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`which port`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present?&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;rvm_install_options&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;my_environment_vars&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;for_macports?&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;CC&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/usr/bin/gcc-4.2&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&#39;CFLAGS&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;-O2 -arch x86_64&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&#39;LDFLAGS&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;-L/opt/local/lib -arch x86_64&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&#39;CPPFLAGS&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;-I/opt/local/include&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rvm_odbc_dir&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;for_macports?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/opt/local&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/usr/local&#39;&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;set_environment_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&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;v&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;with_my_environment_vars&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;my_vars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_environment_vars&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;current_vars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&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;cvars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&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;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_environment_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_environment_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_vars&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;RVM Rake Task Breakdown&lt;/h2&gt;

&lt;p&gt;
  This is the fun part - lets start from top to bottom. I&#39;ll focus only on the parts that are centric to why the RVM ruby API is so bad ass and the rake task in general. The following section is dedicated to RVM with the SQL Server Adapter stack. First, the :setup task, this is called before every other task. It simply sets up the load path so that the RVM API file can be required. That api file is located in your rvm repo path, typically in your ~/.rvm directory. Now every other task can use the &lt;code&gt;RVM&lt;/code&gt; module which implements method missing for many commands.
&lt;/p&gt;

&lt;p&gt;
  Past this my rvm namespace is broken up into three main install tasks. The primary concerns are &lt;code&gt;rvm:install:rubies&lt;/code&gt; and &lt;code&gt;rvm:install:gems&lt;/code&gt; each invoked by the rake task. Starting with the :rubies task, this iterates over a collection of ruby version strings first checking if RVM knows its installed then installing it otherwise.
&lt;/p&gt;

&lt;p&gt;
  In the :gems task, things get a little interesting. I am using a few methods (seen toward the bottom) that give this a nice little DSL of my own around RVM. The first is a block method called &lt;code&gt;rvm_each_rubie&lt;/code&gt;. This iterates over each of my project&#39;s ruby strings, tells RVM to use that ruby, hence dynamically switching to that ruby/gemset then yielding to the block. That means that each go around I will be in an completely different ruby/gem environment, each specific to my project using RVM gemsets. This allows the inner method for iterating over the required gems for my project and asking to install them with &lt;code&gt;rvm_install_gem&lt;/code&gt;. This method uses &lt;code&gt;RVM.ruby_eval&lt;/code&gt; to execute a string of ruby in the context of the current ruby version and gemset. In this case, finding out if a gem is installed already. If not, I use the &lt;code&gt;RVM.perform_set_operation&lt;/code&gt; to install the gem, again in current context. I use perform_set_operation so I can read the STDOUT back to the rake task so a user sees exactly what is going of for the gem install.
&lt;/p&gt;

&lt;p&gt;
  Past that there are a few other details. Most can be picked up by reading the helper methods toward the bottom. Using the RVM ruby API is a bit of a chore if you rely on documentation. Sure it has some, but nothing beats reading the code to see what is available to you. Remember you can find the API library by opening up the &lt;code&gt;~/.rvm/lib&lt;/code&gt; directory. I&#39;m sure you can also find help on the &lt;a href=&quot;http://rvm.beginrescueend.com/support/irc/&quot;&gt;RVM IRC channel&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  Though it is not specific to general RVM API goodness, the :odbc task does show some great interfaces that RVM exposes for doing standard file system directory changing and running commands to the system.
&lt;/p&gt;

&lt;h2&gt;Notes On RVM With The SQL Server Adapter Stack&lt;/h2&gt;

&lt;p&gt;
  So you use the ActiveRecord SQLServerAdapter? That means you have some underlying components installed - namely FreeTDS, unixODBC, and RubyODBC right. If your like me and believe that MacPorts is the way to go and risking a Homebrew interleaved dependency with Apple&#39;s libraries is risky, this section is for you! So you have a MacPort base and you want to compile your RVM rubies in such a way that other dependencies such as Nokogiri and RubyODBC use your /opt/local installs. By default this does not happen because unless ruby was compiled the right way, it wont be able to allow built gems to know about your /opt/local directory. So this is what I came up with.
&lt;/p&gt;

&lt;p&gt;
  Take a look at the &lt;code&gt;my_environment_vars&lt;/code&gt; method. This works in-conjunction with the &lt;code&gt;with_my_environment_vars&lt;/code&gt; block method. Basically it temporarily set&#39;s MacPort specific environment variables before installing a ruby version via RVM. The ones shown are what I have found work best for my system. I think the most important are &lt;code&gt;LDFLAGS=-L/opt/local/lib -arch x86_64&lt;/code&gt; and &lt;code&gt;CPPFLAGS=-I/opt/local/include&lt;/code&gt;. Once ruby is built with those, it can easily reflect with standard 3rd party install methods that use &lt;code&gt;RbConfig&lt;/code&gt;. To date any gem that I have had to compile, most importantly RubyODBC, does so perfectly against my /opt/local ports. This includes MySQL, Nokogiri, everything! I love it. I totally encourage anyone to use RVM and to get to know it&#39;s great ruby API for automating all sorts of things.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;Ruby Version Manager (RVM)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/rails-sqlserver/activerecord-sqlserver-adapter&quot;&gt;ActiveRecord SQL Server Adapter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2009/9/5/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more&quot;&gt;The Ultimate OS X Snow Leopard Stack For Rails Development - x86_64, MacPorts, Ruby 1.8/1.9, SQL Server, SQLite3, MySQL &amp; More&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.github.com/rails-sqlserver/activerecord-sqlserver-adapter/&quot;&gt;SQL Server Adapter Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 30 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/07/30/the-rvm-ruby-api/</link>
        <guid isPermaLink="true">/2010/07/30/the-rvm-ruby-api/</guid>
      </item>
    
      <item>
        <title>A Macport Rubyodbc Update_redirect</title>
        <description></description>
        <pubDate>Mon, 19 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/7/19/a-macport-rubyodbc-update</link>
        <guid isPermaLink="true">/2010/7/19/a-macport-rubyodbc-update</guid>
      </item>
    
      <item>
        <title>A MacPort/RubyODBC Update</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  &lt;a href=&quot;https://github.com/rails-sqlserver/tiny_tds&quot;&gt;TinyTDS&lt;/a&gt; is the upcoming de facto raw connection method for the SQL Server adapter. Please read the &lt;em&gt;&lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/wiki/Using-TinyTds&quot;&gt;Using TinyTDS&lt;/a&gt;&lt;/em&gt; wiki page on the adapter for switching. No longer do you have to worry about compiling ODBC layers!
&lt;/aside&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  I have changed my mind about the UTF-8 version of RubyODBC. Please &lt;a href=&quot;http://groups.google.com/group/rails-sqlserver-adapter/browse_thread/thread/367cf70b2b48d4a0?hl=en&quot;&gt;read that section&lt;/a&gt; in the the rails 3 announcements for the SQL Server adapter.
&lt;/aside&gt;

&lt;p&gt;
  Quite a while ago I wrote a &lt;a href=&quot;/2009/9/5/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more&quot;&gt;soup to nuts article on getting the full multi-ruby development stack installed&lt;/a&gt; for those using the SQL Server adapter. The base package management system used there was MacPorts. In it I described how to edit the outdated Portfile for the rb-odbc package and exclaimed how important it was to use the +utf8 variant. I was totally wrong about that part.
&lt;/p&gt;

&lt;p&gt;
  This past week I started heavily exploring &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;RVM&lt;/a&gt; at the advice of friend while we visited the Boston.rb user grooup. As an aside, I finally feel my unix-fu is strong enough to cover the edge cases needed to get the SQL Server stack happy with RVM. Good news, but that&#39;s next weeks blog post. Anyways I found that while updating my core MacPort&#39;s rb-odbc package that +utf8 was blowing up. I am currently using MacPorts 1.9.1 and was targeting 0.99991 of RubyODBC. Here is the updated port file. To edit your current port file run &lt;code&gt;mate $(port file rb-odbc)&lt;/code&gt; and paste this new one in. Details afterward.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;# $Id: Portfile 30250 2010-07-18 02:16:17Z ken@metaskills.net $
PortSystem    1.0
PortGroup     ruby 1.0

ruby.setup          {odbc ruby-odbc} 0.99991 extconf.rb {README doc test}
maintainers         nomaintainer
description         An extension library for ODBC from ruby.
long_description    Extension library to use ODBC data sources from Ruby. \
                    Supports Ruby 1.6.x and 1.8 on Win32 OSes and UN*X
checksums           md5 64eaf6089e7ca17eeff54c4fe052ac96
homepage            http://www.ch-werner.de/rubyodbc
master_sites        http://www.ch-werner.de/rubyodbc
categories-append   databases
platforms           darwin

configure.cmd             ${ruby.bin} -rvendor-specific -Cext extconf.rb
build.pre_args-append     -C ext
destroot.pre_args-append  -C ext

variant utf8 {
  configure.cmd             ${ruby.bin} -rvendor-specific -Cext/utf8 extconf.rb
  build.pre_args-delete     -C ext
  build.pre_args-append     -C ext/utf8
  destroot.pre_args-delete  -C ext
  destroot.pre_args-append  -C ext/utf8
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So where did I go wrong on my old article? My first big mistake was thinking that the &lt;code&gt;+utf8&lt;/code&gt; port variant was needed. Not only is it &lt;strong&gt;NOT NEEDED&lt;/strong&gt;, it may not work right at all. In fact, the old Portfile in MacPorts trunk technically did not even configure/make/install the utf8 version either! Honestly â€“ I spent all day learning the MacPort&#39;s Portfile syntax and tested this. Installing that variant just breaks with an error like &lt;code&gt;LoadError: dlsym(0x1010cd3b0, Init_odbc): symbol not found&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
  So, even though my updated Portfile above now fixes that issue and supports actually building a utf8 version of RubyODBC, &lt;strong&gt;YOU DO NOT NEED IT!&lt;/strong&gt; In fact the entire SQL Server stack is tested with the plain non-utf8 package and passes with flying colors. This includes passing tests where unicode columns return correctly utf8-encoded strings, among others. Though I have not tested it, I believe the utf8 version would do more damage than good. The RubyODBC documentation says it would make every string utf8 encoded. Not good for an adapter that has mixed data types. For my own personal notes, here is a diff of the Makefile below. I think the Init_odbc error was a result of a missing flag in the Makefile.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;# My notes
# +CPPFLAGS = -DHAVE_LONG_LONG
# +CPPFLAGS = -DHAVE_VERSION_H
# +CPPFLAGS = -DHAVE_TYPE_SQLBIGINT
# -CPPFLAGS = -DHAVE_SQLCONFIGDATASOURCEW
# -CPPFLAGS = -DHAVE_SQLINSTALLERERRORW
# -CPPFLAGS = -DHAVE_SQLWRITEFILEDSNW
# -CPPFLAGS = -DHAVE_SQLREADFILEDSNW
&lt;span class=&quot;gd&quot;&gt;--- Makefile(+utf8)  2010-07-18 12:00:24.000000000 -0400
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ Makefile(-utf8)  2010-07-18 12:49:32.000000000 -0400
&lt;/span&gt;&lt;span class=&quot;gu&quot;&gt;@@ -47,7 +47,7 @@
&lt;/span&gt; CFLAGS   =  -fno-common -O2 -arch x86_64  -fno-common -pipe -fno-common $(cflags) -arch x86_64
 INCFLAGS = -I. -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I.
 DEFS     =
&lt;span class=&quot;gd&quot;&gt;-CPPFLAGS = -DHAVE_SQL_H -DHAVE_SQLEXT_H -DHAVE_TYPE_SQLTCHAR -DHAVE_TYPE_SQLLEN -DHAVE_TYPE_SQLULEN -DHAVE_ODBCINST_H -DHAVE_SQLCONFIGDATASOURCEW -DHAVE_SQLWRITEFILEDSNW -DHAVE_SQLREADFILEDSNW -DHAVE_SQLINSTALLERERROR -DHAVE_SQLINSTALLERERRORW -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE  -I/opt/local/include
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+CPPFLAGS = -DHAVE_VERSION_H -DHAVE_SQL_H -DHAVE_SQLEXT_H -DHAVE_TYPE_SQLTCHAR -DHAVE_TYPE_SQLLEN -DHAVE_TYPE_SQLULEN -DHAVE_ODBCINST_H -DHAVE_SQLINSTALLERERROR -DHAVE_TYPE_SQLBIGINT -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE  -I/opt/local/include -DHAVE_LONG_LONG
&lt;/span&gt; CXXFLAGS = $(CFLAGS)
 ldflags  = -L. -L/opt/local/lib -arch x86_64
 dldflags =
&lt;span class=&quot;gu&quot;&gt;@@ -89,7 +89,7 @@
&lt;/span&gt; LIBS = $(LIBRUBYARG_SHARED) -lodbcinst -lodbc  -lpthread -ldl -lobjc
 SRCS = init.c odbc.c
 OBJS = init.o odbc.o
&lt;span class=&quot;gd&quot;&gt;-TARGET = odbc_utf8
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+TARGET = odbc
&lt;/span&gt; DLLIB = $(TARGET).bundle
 EXTSTATIC =
 STATIC_LIB =
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Mon, 19 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/07/19/a-macport-rubyodbc-update/</link>
        <guid isPermaLink="true">/2010/07/19/a-macport-rubyodbc-update/</guid>
      </item>
    
      <item>
        <title>Interactive Javascript Console With Textmate_redirect</title>
        <description></description>
        <pubDate>Fri, 09 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/7/9/interactive-javascript-console-with-textmate</link>
        <guid isPermaLink="true">/2010/7/9/interactive-javascript-console-with-textmate</guid>
      </item>
    
      <item>
        <title>Interactive JavaScript Console With TextMate</title>
        <description>&lt;p&gt;
  Last week I started reading &lt;a href=&quot;http://oreilly.com/catalog/9780596517748&quot;&gt;&lt;em&gt;JavaScript: The Good Parts&lt;/em&gt;&lt;/a&gt; by Douglas Crockford. It was on my list of long overdue things to do. While reading it, I wanted to be able to kick some simple JavaScript examples around. As rubyist we have it good, &lt;code&gt;irb&lt;/code&gt; let&#39;s us fire up an interactive console anytime we want. But with JavaScript, options are limited. Sure you could install Johnson/EnvJS, Rhino or some other JavaScript engine. Maybe even load up firebug or the web inspector. But who wants to load a browser to play with JS?
&lt;/p&gt;

&lt;p&gt;
  Luckily if your are on a Mac, you do not have to worry about any of that. You already have a JavaScript engine installed. Where? Thanks to Safari&#39;s &lt;a href=&quot;http://webkit.org/blog/214/introducing-squirrelfish-extreme/&quot;&gt;SquirrelFish Extreme (SFX)&lt;/a&gt;, it is right in your system&#39;s library at this full path &lt;code&gt;/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc&lt;/code&gt;. Instead of adding that to my path, I created a symlink to in my opt&#39;s bin directory (seeing how I have MacPorts). For instance.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;sudo ln -s /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc /opt/local/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Assuming you just did that command in your own bin path of choice, you can now just type &lt;code&gt;jsc&lt;/code&gt; and start typing JavaScript just as you easily as if you were in an irb prompt. Fun, but we can do better.
&lt;/p&gt;

&lt;h2&gt;Creating A TextMate Bundle To Run JavaScript&lt;/h2&gt;

&lt;p&gt;
  So I was inspired by this article that explained how easy it is to make a &lt;a href=&quot;http://www.phpied.com/jslint-on-mac-textmate/&quot;&gt;TextMate bundle to run JavaScript thru JSLint&lt;/a&gt; and decided to make one to run the same JavaScript in an the interactive console for SFX. I wont go thru the details of how to add a simple TextMate bundle command, but the following picture and code sample shows the &lt;code&gt;Run JSConsole&lt;/code&gt; command I made. The command resides in my own bundle namespace.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/jsc_tmbundle.gif&quot; alt=&quot;TextMate Bundle Window&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TM_SUPPORT_PATH&#39;&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;s1&quot;&gt;&#39;/lib/escape.rb&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;terminal_script_filepath&lt;/span&gt;
  &lt;span class=&quot;sx&quot;&gt;%|tell application &quot;Terminal&quot;
      activate
      do script &quot;jsc -i #{e_as(e_sh(ENV[&#39;TM_FILEPATH&#39;]))}&quot;
    end tell|&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;|osascript&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;terminal_script_filepath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  With that simple bundle command done, you can now use the &lt;code&gt;Command-R&lt;/code&gt; keyboard shortcut to load the windows JavaScript file into a newly opened terminal window running in the SFX console. Pictures below.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/jsc_textmate.gif&quot; alt=&quot;TextMate Windows With JavaScript&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/jsc_terminal.gif&quot; alt=&quot;Mac OS Terminal App Lauanched From TextMate JavaScript&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Great, Now What?&lt;/h2&gt;

&lt;p&gt;
  My simple script just loads the whole file, it does not take into account TM&#39;s selected text. Nor does it do anything with selected files. I would love to see someone write a TextMate bundle that could preload up jQuery/Prototype or a set of files. The ultimate would be a bundle command that executed and updated markers like the Ruby bundle can do. Sadly, I do not have that much time on my hands :)
&lt;/p&gt;
</description>
        <pubDate>Fri, 09 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/07/09/interactive-javascript-console-with-textmate/</link>
        <guid isPermaLink="true">/2010/07/09/interactive-javascript-console-with-textmate/</guid>
      </item>
    
      <item>
        <title>Bit Fat Legacy Schema Inspection_redirect</title>
        <description></description>
        <pubDate>Wed, 07 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/7/7/bit-fat-legacy-schema-inspection</link>
        <guid isPermaLink="true">/2010/7/7/bit-fat-legacy-schema-inspection</guid>
      </item>
    
      <item>
        <title>Bit Fat Legacy Schema Inspection</title>
        <description>&lt;p&gt;
  Sometime in rails 2.x the #inspect method for an ActiveRecord class was changed to show you all the column names (attributes) of that class. This is fine when things are small but if your working on a big legacy schema and you want clean terse debugging, all those column names can be noisy. I just set this initializer up today to kill it. Now the class just shows the number of columns.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveRecord&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Base&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&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;no&quot;&gt;Base&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abstract_class?&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(abstract)&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_exists?&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; columns)&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(Table doesn&#39;t exist)&quot;&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;k&quot;&gt;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Wed, 07 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/07/07/bit-fat-legacy-schema-inspection/</link>
        <guid isPermaLink="true">/2010/07/07/bit-fat-legacy-schema-inspection/</guid>
      </item>
    
      <item>
        <title>Custom Webrat Session Formatted_error For Rails With Nokogiri_redirect</title>
        <description></description>
        <pubDate>Tue, 06 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/7/6/custom-webrat-session-formatted_error-for-rails-with-nokogiri</link>
        <guid isPermaLink="true">/2010/7/6/custom-webrat-session-formatted_error-for-rails-with-nokogiri</guid>
      </item>
    
      <item>
        <title>Custom Webrat::Session formatted_error For Rails With Nokogiri</title>
        <description>&lt;p&gt;
  I never liked how Webrat shows the complete response body for exceptions when integration testing rails applications. For the longest time I redefined the formatted_error method to simple do nothing. Today I used Nokogiri to parse out the good bits from that page. Here is the result. Not pretty, but it&#39;s working fine so far. Got a better example? Please share!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Webrat&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Session&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;formatted_error&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;exception_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;head title&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inner_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;squish&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;exception_msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;body h1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inner_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;squish&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;exception_detail1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;body p&#39;&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;n&quot;&gt;detail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;detail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;next_sibling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;squish&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;exception_detail2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;body p&#39;&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;n&quot;&gt;detail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;detail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;next_sibling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;code&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;app_trace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#Application-Trace pre code&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inner_html&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception_msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception_detail1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception_detail2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;Could not format page exception. Perhaps try to use Nokogiri on this: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_body&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 06 Jul 2010 00:00:00 -0400</pubDate>
        <link>/2010/07/06/custom-webrat-session-formatted-error-for-rails-with-nokogiri/</link>
        <guid isPermaLink="true">/2010/07/06/custom-webrat-session-formatted-error-for-rails-with-nokogiri/</guid>
      </item>
    
      <item>
        <title>The Alias_method_chain Of Rake Override Rake Task_redirect</title>
        <description></description>
        <pubDate>Wed, 26 May 2010 00:00:00 -0400</pubDate>
        <link>/2010/5/26/the-alias_method_chain-of-rake-override-rake-task</link>
        <guid isPermaLink="true">/2010/5/26/the-alias_method_chain-of-rake-override-rake-task</guid>
      </item>
    
      <item>
        <title>The alias_method_chain of Rake - Override Rake Task</title>
        <description>&lt;p&gt;
  Rake is cool. It is built so that multiple tasks with the same name run in a reverse defined series. This is great, but sometimes you want to override a task with your own behavior and conditionally call the earlier task. Especially if that task is defined deep somewhere else, like in a rails gem. I have had to solve this problem before in Rake. Awhile back I hacked something up that would totally trump a predefined rake task and allow you to replace it with a new one. Lately while &lt;a href=&quot;http://wiki.github.com/rails-sqlserver/2000-2005-adapter/rails-db-rake-tasks&quot;&gt;working on the SQL Server adapter&lt;/a&gt;, I had a need to method chain some core rails :db namespaced tasks. So once again I googled others work and again resorted to hacking Rake. Below is what I was left with.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TaskManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alias_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;new_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:original&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_name&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;vi&quot;&gt;@tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alias_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alias_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&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;override_task&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;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;resolve_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fq_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_variable_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:@scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;push&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;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;alias_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fq_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define_task&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;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  It&#39;s easy to use, just require it in your Rakefile. In the example below, I was able to programmatically method chain the core rails db:test:purge and only call the original if I needed to. Very cool!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:db&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;override_task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:purge&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# To invoke the original task add &quot;:original&quot; to its name&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;db:test:purge:original&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Lastly, thanks to &lt;a href=&quot;http://www.taknado.com/&quot;&gt;Eugene Bolshakov&lt;/a&gt;, &lt;a href=&quot;http://github.com/jwood&quot;&gt;John Wood&lt;/a&gt;, and &lt;a href=&quot;http://github.com/markwfoster&quot;&gt;Mark Foster&lt;/a&gt; whom have tackled this rake problem before. My version above was based on their work, but correctly works with namespaces which was critical for my needs.
&lt;/p&gt;
</description>
        <pubDate>Wed, 26 May 2010 00:00:00 -0400</pubDate>
        <link>/2010/05/26/the-alias-method-chain-of-rake-override-rake-task/</link>
        <guid isPermaLink="true">/2010/05/26/the-alias-method-chain-of-rake-override-rake-task/</guid>
      </item>
    
      <item>
        <title>Restful Ajax With Forgery Protection With Rails 3_redirect</title>
        <description></description>
        <pubDate>Tue, 13 Apr 2010 00:00:00 -0400</pubDate>
        <link>/2010/4/13/restful-ajax-with-forgery-protection-with-rails-3</link>
        <guid isPermaLink="true">/2010/4/13/restful-ajax-with-forgery-protection-with-rails-3</guid>
      </item>
    
      <item>
        <title>RESTful AJAX with Forgery Protection (In Rails 3)</title>
        <description>&lt;p&gt;
  A &lt;a href=&quot;/2008/6/18/restful-ajax-with-forgery-protection&quot;&gt;while back ago&lt;/a&gt; I wrote an article about how to use Rails built-in forgery protection in your RESTful AJAX calls. Normally AJAX requests, those responding true to &lt;code&gt;request.xhr?&lt;/code&gt; in rails, are forgery whitelisted. But sometimes, and under what conditions I am not sure, AJAX methods are subjected to forgery protection. Maybe you have the &lt;code&gt;ActionDispatch::Request#forgery_whitelisted?&lt;/code&gt; overridden to not include AJAX requests? Either way and for whatever reason â€“ if you like to use forgery protection in your RESTful AJAX calls to rails, then here is the new implementation under Rails 3 beta2.
&lt;/p&gt;

&lt;h2&gt;Forgery Protection In Rails 3&lt;/h2&gt;

&lt;p&gt;
  In a pre Rails 3 application all form tag helpers automatically create a hidden form field that contain the authentication token. These are passed when the form is serialized and if you viewed source, you could see them. However, Rails 3 is unobtrusive, which means you can count on them not polluting your markup with this kind of framework data. So where do the authentication params come from in a Rails 3 application? The answer is two places. First there is a new &lt;code&gt;ActionView::Helpers::CsrfHelper&lt;/code&gt; module that allows you to use the #csrf_meta_tag helper in the head of your layout files. This helper will generate two meta tags, one for the authentication parameter name and the other for the value. The second place is in the new rails.js which reads these two meta tags for further interpolation into some generated form tags for all sorts of :remote links, buttons, etc. If your interested in reading more about these, look into the source, but I thought you might like to see some places where these are used by the framework now.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;http-equiv=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html; charset=utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;%= csrf_meta_tag %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dom:loaded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;meta[name=csrf-token]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;content&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;authParam&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;meta[name=csrf-param]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;content&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;formTemplate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;form method=&quot;#{method}&quot; action=&quot;#{action}&quot;&amp;gt;\
      #{realmethod}&amp;lt;input name=&quot;#{param}&quot; value=&quot;#{token}&quot; type=&quot;hidden&quot;&amp;gt;\
      &amp;lt;/form&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;realmethodTemplate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;input name=&quot;_method&quot; value=&quot;#{method}&quot; type=&quot;hidden&quot;&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//... etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Now Our RESTful AJAX with Forgery Protection&lt;/h2&gt;

&lt;p&gt;
  OK, now that bit of background information is out of the way, lets look into how we can use this for ourselves. Since Rails 3 has provided us with a good convention, we can hook into this pretty easily. This prototype example below is pretty simple and follows my OOJS approach. I have a base JS object that is basically a module with a function called authParams. I then mixin this base JS object into all my Prototype classes. We are reading the same meta tags that rails now uses and create a Prototype Hash object with the name/value of the authentication token. Then in ever AJAX request I merge these parameters in with what ever I am serializing for that request. Pretty simple eh? Did I miss anything?
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// A base JS object.&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyBase&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;na&quot;&gt;authParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authParam&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;meta[name=csrf-param]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;content&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;meta[name=csrf-token]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;content&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authParam&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;nx&quot;&gt;authToken&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Mixed Into Other Classes.&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SomeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MyBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;doAjaxRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elmnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 13 Apr 2010 00:00:00 -0400</pubDate>
        <link>/2010/04/13/restful-ajax-with-forgery-protection-with-rails-3/</link>
        <guid isPermaLink="true">/2010/04/13/restful-ajax-with-forgery-protection-with-rails-3/</guid>
      </item>
    
      <item>
        <title>Textmate Theme Key Bindings For Xcode_redirect</title>
        <description></description>
        <pubDate>Fri, 19 Mar 2010 00:00:00 -0400</pubDate>
        <link>/2010/3/19/textmate-theme-key-bindings-for-xcode</link>
        <guid isPermaLink="true">/2010/3/19/textmate-theme-key-bindings-for-xcode</guid>
      </item>
    
      <item>
        <title>TextMate Theme &amp; Key Bindings For Xcode</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/textmate_xcode_theme2.gif&quot; alt=&quot;Xcode TextMate Theme&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; I&#39;ve been using Xcode for about 8 hard core months now and for all this time I have been using a theme I made that mimics the All Hallow&#39;s Eve TextMate theme with a bunch of custom key bindings that make Xcode more TextMate compatible. Here are links to download both below and a few notes I have put together. As I remember more of what I have actually done, this post will get updated. I do remember the first thing I did with Xcode for almost 3 days was just to customize the heck out of it and these files are the results.
&lt;/p&gt;

&lt;p&gt;
  To use these download and unzip them. Please the theme in &lt;code&gt;~/Library/Application Support/Xcode/Color Themes&lt;/code&gt; and place the bindings in &lt;code&gt;~/Library/Application Support/Xcode/Key Bindings&lt;/code&gt;. That should be it. Hare are my notes for now on what the key bindings do.
&lt;/p&gt;

&lt;h2&gt;Misc Key Bindings&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Command-W - Works on a file! Not the whole project window!&lt;/li&gt;
  &lt;li&gt;Command-1 - Open File List&lt;/li&gt;
  &lt;li&gt;Command-2 - Method List&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;TextMate Style Key Bindings&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Command-T - for Open Quickly&lt;/li&gt;
  &lt;li&gt;I&#39;ll update this as I find more, it has honestly been so long I forget all the work I&#39;ve done and just use this now as if it were TextMate.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 19 Mar 2010 00:00:00 -0400</pubDate>
        <link>/2010/03/19/textmate-theme-key-bindings-for-xcode/</link>
        <guid isPermaLink="true">/2010/03/19/textmate-theme-key-bindings-for-xcode/</guid>
      </item>
    
      <item>
        <title>Git Init Xcode Projects_redirect</title>
        <description></description>
        <pubDate>Tue, 23 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/2/23/git-init-xcode-projects</link>
        <guid isPermaLink="true">/2010/2/23/git-init-xcode-projects</guid>
      </item>
    
      <item>
        <title>Git Init XCode Projects</title>
        <description>&lt;p&gt;
  Here is a little ZSH function I have been using for quickly setting up new XCode apps I call tire kickers, little play and learn apps. Being able to track your learning as you go with git.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; -x &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;which git&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then

    function &lt;/span&gt;ginit_xcode &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      git init
      &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;# XCode&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.mode1v3&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.mode2v3&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.nib&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.swp&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
*.pbxuser&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.perspective&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.perspectivev3&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;# OSX&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.DS_Store&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
# TextMate&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.tm_build_errors&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &amp;gt;&amp;gt; .gitignore
      git add .gitignore
      git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;Ignore Xcode stuff.&quot;&lt;/span&gt;
      git add .
      git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;Initial Xcode project.&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The echo lines puts out a .gitignore file that will look something like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;# XCode
build
*.mode1v3
*.mode2v3
*.nib
*.swp
*.pbxuser
*.perspective
*.perspectivev3

# OSX
.DS_Store

# TextMate
*.tm_build_errors
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 23 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/02/23/git-init-xcode-projects/</link>
        <guid isPermaLink="true">/2010/02/23/git-init-xcode-projects/</guid>
      </item>
    
      <item>
        <title>Synchronizing Core Data With Rails 3 0 0 Pre_redirect</title>
        <description></description>
        <pubDate>Fri, 12 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/2/12/synchronizing-core-data-with-rails-3-0-0-pre</link>
        <guid isPermaLink="true">/2010/2/12/synchronizing-core-data-with-rails-3-0-0-pre</guid>
      </item>
    
      <item>
        <title>Synchronizing Core Data With Rails (3.0.0.pre)</title>
        <description>&lt;p&gt;
  &lt;a href=&quot;http://homemarks.com/&quot;&gt;&lt;img src=&quot;/assets/57x57_w_shadow.png&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt;&lt;/a&gt; This is my presentation to our local @757rb/@757objc users group this past Tuesday. Hope some find it useful. Lessons learned from building HomeMarks native iPhone application to synchronize Core Data with a RESTful backend built using rails 3.0.0.pre. This covers a previous design methodology called the AJAX head pattern which decouples rails applications from the views they present which allowed an easy API foundation for the iPhone application and data sync methods.
&lt;/p&gt;

&lt;p&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=synchronizingcoredatawithrailswebapplications-100211204432-phpapp01&amp;stripped_title=synchronizing-core-data-with-rails&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=synchronizingcoredatawithrailswebapplications-100211204432-phpapp01&amp;stripped_title=synchronizing-core-data-with-rails&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://homemarks.com/&quot;&gt;HomeMarks (buy it, try it, review it)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/metaskills/synchronizing-core-data-with-rails&quot; title=&quot;Synchronizing Core Data With Rails&quot;&gt;Synchronizing Core Data With Rails (slideshare)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/05/24/the-ajax-head-design-pattern/&quot;&gt;AJAX Head Design Pattern&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/6/18/restful-ajax-with-forgery-protection&quot;&gt;RESTful AJAX With Forgery Protection&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/8/18/in-hell-oo-for-homemarks&quot;&gt;In HELL-OO For HomeMarks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://code.google.com/p/json-framework/&quot;&gt;The json-framework Project&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://allseeing-i.com/ASIHTTPRequest/&quot;&gt;The ASIHTTPRequest Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 12 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/02/12/synchronizing-core-data-with-rails-3-0-0-pre/</link>
        <guid isPermaLink="true">/2010/02/12/synchronizing-core-data-with-rails-3-0-0-pre/</guid>
      </item>
    
      <item>
        <title>Simple Script Console Function_redirect</title>
        <description></description>
        <pubDate>Sat, 06 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/2/6/simple-script-console-function</link>
        <guid isPermaLink="true">/2010/2/6/simple-script-console-function</guid>
      </item>
    
      <item>
        <title>Simple Script/Console Function</title>
        <description>&lt;p&gt;
  This is something simple I worked up today for my ZSH profile that let&#39;s me keep my simple &lt;code&gt;sc&lt;/code&gt; alias and have it work with all versions of rails. If you did not know, all the script files in rails 3 are gone and the new all-in-one &lt;code&gt;rails&lt;/code&gt; executable does all the heavy lifting. This little function even passes down all the arguments too.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sc &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -f ./script/rails &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;rails console &lt;span class=&quot;nv&quot;&gt;$argv&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    ./script/console &lt;span class=&quot;nv&quot;&gt;$argv&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  One other thing, the way rails uses IRB is different now. I had to change my &lt;code&gt;~/.irbrc&lt;/code&gt; file to look like this below to get my simple prompt and history back. IMPORTANT NOTE: In order for this to work, you &lt;a href=&quot;http://redmine.ruby-lang.org/issues/show/1556&quot;&gt;have to apply this 2 line patch to your save-history.rb file&lt;/a&gt;. Worked like a champ for me.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# IRB history patch &amp;lt;http://redmine.ruby-lang.org/issues/show/1556&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;irb/completion&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;irb/ext/save-history&#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;IRB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:USE_READLINE&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;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;IRB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:SAVE_HISTORY&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;500&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;IRB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:HISTORY_FILE&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;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;HOME&#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;s2&quot;&gt;/.irb.hist&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;IRB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:PROMPT_MODE&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;ss&quot;&gt;:SIMPLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sat, 06 Feb 2010 00:00:00 -0500</pubDate>
        <link>/2010/02/06/simple-script-console-function/</link>
        <guid isPermaLink="true">/2010/02/06/simple-script-console-function/</guid>
      </item>
    
      <item>
        <title>Unobtrusive Js In Rails 3 With Prototype_redirect</title>
        <description></description>
        <pubDate>Fri, 29 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/1/29/unobtrusive-js-in-rails-3-with-prototype</link>
        <guid isPermaLink="true">/2010/1/29/unobtrusive-js-in-rails-3-with-prototype</guid>
      </item>
    
      <item>
        <title>Unobtrusive JS In Rails 3 With Prototype</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  An updated version of UJS and forgery protection in Rails3 &lt;a href=&quot;/2010/4/13/restful-ajax-with-forgery-protection-with-rails-3&quot;&gt;here&lt;/a&gt;.
&lt;/aside&gt;

&lt;p&gt;
  Are you bleeding on the edge of rails 3 and need to shim up some unobtrusive JavaScript to work with your &lt;code&gt;link_to&lt;/code&gt; code that uses a destructive :method option? I did today and here is what I did to solve it. If you are unfamiliar with the problem, and what has been happening in rails 3 with UJS, check out &lt;a href=&quot;http://blog.solnic.eu/2009/09/08/unobtrusive-javascript-helpers-in-rails-3&quot;&gt;Piotr Solnica&#39;s&lt;/a&gt; blog for a good run down. Or you can check out the simple code block below.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# This Ruby&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link_to&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Logout&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:delete&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Will out put this HTML in Rails 3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;a href=&quot;/session&quot; data-method=&quot;delete&quot; data-url &quot;/session&quot; rel=&quot;nofollow&quot;&amp;gt;Logoout&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So no more tag soup. Yea! There was much rejoicing, but I could not find any illustrated examples of what type of JavaScript to use to back this up. There are two problems at play here. First, simple link &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags are not forms and hence methods like post/put/delete are not going to be solved with simple query params. Second, because link tags are not forms, there is no authenticity_token hidden in the generated form, like a &lt;code&gt;button_to&lt;/code&gt; would generate. Let&#39;s ignore the second problem for a bit and see what I came up with for using with Prototype.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyJsObject&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;na&quot;&gt;linkToDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;href&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;up&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FORM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;post&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},[&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;INPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hidden&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;_method&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;delete&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;INPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hidden&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;authenticity_token&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;authenticity_token&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)})]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;dom:loaded&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;a[data-method=delete]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyJsObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;linkToDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  In this example I am only covering the DELETE action. This code could be abstracted to take a &quot;method&quot; argument and use it. As you can see, it&#39;s just a simple iteration over the links with custom &quot;data-method&quot; attributes and attaching a function to it. For brevity, I am using the Builder.js methods for building DOM objects. See anything odd up there? The authentication token? You got it, destructive actions like POST/DELETE/PUT will need that token. I wrote up a great article a year or so ago that still works today titled &lt;a href=&quot;/2010/4/13/restful-ajax-with-forgery-protection-with-rails-3&quot;&gt;RESTful AJAX with Forgery Protection (In Rails3)&lt;/a&gt; that gives me that nice global var. Check it out for the last piece to this puzzle and have fun working on the edge!
&lt;/p&gt;
</description>
        <pubDate>Fri, 29 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/01/29/unobtrusive-js-in-rails-3-with-prototype/</link>
        <guid isPermaLink="true">/2010/01/29/unobtrusive-js-in-rails-3-with-prototype/</guid>
      </item>
    
      <item>
        <title>Quickie Js Prototype Wrapper For Quicktime_redirect</title>
        <description></description>
        <pubDate>Mon, 25 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/1/25/quickie-js-prototype-wrapper-for-quicktime</link>
        <guid isPermaLink="true">/2010/1/25/quickie-js-prototype-wrapper-for-quicktime</guid>
      </item>
    
      <item>
        <title>Quickie.js - Prototype wrapper for QuickTime</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: May 15th, 2011 - Today I decided to to re-write this class as my first dive into both CoffeeScript and jQuery. You can find an &lt;a href=&quot;https://gist.github.com/973483&quot;&gt;updated version in this gist on github&lt;/a&gt;.
&lt;/aside&gt;

&lt;p&gt;
  As some of you know, I am in the last steps of announcing my first iPhone application. We all know that every good iPhone application has a great marketing website with a screen cast. I myself was heavily inspired by the &lt;a href=&quot;http://tapbots.com/convertbot&quot;&gt;Tapbots Convertbot&lt;/a&gt; website while building my own and wanted a good way of embedding the screen cast. I think the last time I did an object/embed tag was god... around 2003 or something, seriously.
&lt;/p&gt;

&lt;p&gt;
  So after looking at the source of the Convertbot website, I was happy to find a nice little JavaScript wrapper for QuickTime called Quickie.js. This is a MooTools class created by Jose Prado that helps generate an object or embed tag appropriate for the requesting browser in an abstract way. Here is the link to the &lt;a href=&quot;http://pradador.com/code/quickiejs/&quot;&gt;original Quickie.js&lt;/a&gt;. If you use MooTools, fine, it is real close to Prototype and has my respect, but if you use Prototype, here is my rewrite of the class.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*

Author:
  Ken Collins &amp;lt;metaskills.net&amp;gt;

Options:
  id - (string: defaults to &#39;Quickie_&#39; + unique id) The id of the Quickie object.
  width - (number: defaults to 1) The width of the Quickie object.
  height - (number: defaults to 1) The height of the Quickie object.
  container - (element) The container into which the Quickie object will be injected.
  attributes - (object) QuickTime attributes for the element. See http://www.apple.com/quicktime/tutorials/embed.html for possible attributes.

Returns:
  - (element) A new HTML object Element with browser appropriate QuickTime embed code.

Example:
  var myQuickie = new Quickie(&#39;myMovie.mov&#39;, {
    id: &#39;myQuicktimeMovie&#39;,
    width: 640,
    height: 480,
    container: &#39;qtmovie&#39;,
    attributes: {
      controller: &#39;true&#39;,
      autoplay: &#39;false&#39;
    }
  });

Credits:
    Mootools Implementaiton: http://pradador.com/code/quickiejs/

License:
    MIT-Style License

*/&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Quickie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;these&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;defaultOptions&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;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;height&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;na&quot;&gt;width&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;na&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Quickie_&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaultOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&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;p&quot;&gt;{});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;true&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_assignElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;toElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;_assignElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;build&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;nx&quot;&gt;Prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Browser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_buildObjectTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_buildEmbedTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;div&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;down&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;_buildObjectTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;object classid=&quot;clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B&quot; codebase=&quot;http://www.apple.com/qtactivex/qtplugin.cab&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; id=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; width=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; height=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;param name=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot; value=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attribute&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;s1&quot;&gt;&#39;&quot; /&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;/object&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;_buildEmbedTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&amp;lt;embed &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; id=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; width=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; height=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attribute&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attribute&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;s1&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; pluginspage=&quot;http://www.apple.com/quicktime/download/&quot;&amp;gt;&amp;lt;/embed&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  If you ask me this is far cleaner than the original. It encapsulates factory methods and all the initialize does is just setup vars, not do ALL the work in one big procedural way. So what does this class do? It&#39;s simple, it allows you to create JavaScript objects that will represent DOM objects for QuickTime movies. This object can be passed to any method that takes expects and element to Prototype since it has a toElement method. Here is the way I am using it in my upcoming project. Just like the Tapbots website, I am creating &lt;code&gt;&lt;div&gt;&lt;/code&gt; tags that have all the attributes I need and are the container elements. On page load, I update all those containers with generate QuickTime source code. See the example below.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
Example Container
&amp;lt;div id=&quot;mymovie_container&quot; class=&quot;quicktime_video&quot; rel=&quot;src=/video/mymovie.mov|width=280|height=393|loop=true|autoplay=true|video_id=mymovie&quot;&amp;gt;&amp;lt;/div&amp;gt;
*/&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;dom:loaded&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.quicktime_video&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attributes&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;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;false&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoplay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;true&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;false&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enablejavascript&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;false&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;rel&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;|&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;=&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pair&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pair&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;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;qt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Quickie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;src&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;video_id&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;width&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;height&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;qt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/quickie.js&quot;&gt;Quickie.js on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 25 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/01/25/quickie-js-prototype-wrapper-for-quicktime/</link>
        <guid isPermaLink="true">/2010/01/25/quickie-js-prototype-wrapper-for-quicktime/</guid>
      </item>
    
      <item>
        <title>Rails Button Links In Embedded Forms_redirect</title>
        <description></description>
        <pubDate>Tue, 05 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/1/5/rails-button-links-in-embedded-forms</link>
        <guid isPermaLink="true">/2010/1/5/rails-button-links-in-embedded-forms</guid>
      </item>
    
      <item>
        <title>Rails Button Links In Embedded Forms</title>
        <description>&lt;p&gt;
  This is one I have had sitting around for almost 3 years now in my toolbox and thought I would share. Have you ever had complicated rails forms and needed simple form buttons that just took you to a simple link? Were you bitten by the &lt;code&gt;button_to&lt;/code&gt; helper code because it generates another form inside of a form? If so, here is a simple rails view helper I made that creates simple button links for embedded forms by making an input with a javascript function. Tag soup you ask, hell yeah, but worth if if you need it.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;button_to_link&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link&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;n&quot;&gt;confirm_option&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:confirm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;popup_option&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;link_function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;popup_option&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new_window&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;link_function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;if (confirm(&#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;escape_javascript&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;confirm_option&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;s2&quot;&gt;&#39;)) { &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link_function&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; }&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confirm_option&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;button_to_function&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_function&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;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;redirect_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&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;n&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:new_window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;sx&quot;&gt;%|window.open(&#39;#{location}&#39;)|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;sx&quot;&gt;%|{window.location.href=&#39;#{location}&#39;}|&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 05 Jan 2010 00:00:00 -0500</pubDate>
        <link>/2010/01/05/rails-button-links-in-embedded-forms/</link>
        <guid isPermaLink="true">/2010/01/05/rails-button-links-in-embedded-forms/</guid>
      </item>
    
      <item>
        <title>Authenticated S3 GETs For Private Objects Using Paperclip</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: [10/18/2011] I now use Fog vs AWS::S3 with Paperclip. I have included a Fog specific example below.
&lt;/aside&gt;

&lt;p&gt;
  Yea I know, I am probably the last person on earth that is just getting around to using &lt;a href=&quot;http://github.com/thoughtbot/paperclip&quot;&gt;Paperclip&lt;/a&gt;. To be honest, most of my file upload code was written way before Paperclip or even AttachementFu was ever conceived. And frankly, I do not do much social app coding on the side - so the need never came up. But that changed recently and I wanted a really really good way of leveraging AWS::S3 storage with the best local app security while maintaining tight control over the files.
&lt;/p&gt;

&lt;p&gt;
  So the Paperclip wiki has a few links that already dealt with some ways of protecting your app&#39;s attachments. One mentions a method I totally love called security through obscurity. It uses a secure random token as part of the filename which combined with the original filename and the id partition makes for great random URLs. The other is a great walk thru on how to use the :url option of paperclip to point access control back to your own application for your normal biz logic.
&lt;/p&gt;

&lt;p&gt;
  The problem I see with both of these methods is that they do not allow you to maintain app control past the final URL handoff/redirect. It also requires that your S3 bucket is public. For instance, if you were to use the &lt;code&gt;s3_permissions =&gt; :private&lt;/code&gt; option of Paperclip, then that URL given to you by Paperclip is pretty much worthless. I knew AWS::S3 had authenticated GETs that generated an automatically expiring URL, but saw no way of accessing its features using the abstract &lt;code&gt;Paperclip::Attachment&lt;/code&gt; object. So this is what I did.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyDownload&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;has_attached_file&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:storage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;mybucket&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:s3_credentials&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;nf&quot;&gt;.&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;ss&quot;&gt;:s3_protocol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;https&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:s3_permissions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:private&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&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;attachment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;:id_partition/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random_secret&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/:filename&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:processors&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;:noop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;before_validation_on_create&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:set_random_secret&lt;/span&gt;


  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;attachment_url&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&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;nf&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tableize&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attachment_file_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&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;authenticated_s3_get_url&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;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reverse_merge!&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:expires_in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:use_ssl&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;no&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S3Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url_for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bucket&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;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;set_random_secret&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;nf&quot;&gt;random_secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SecureRandom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Let me walk you thru some of the highlights of that class, the general concept following is that we are going to use the best of both examples in security mentioned above. First, the secure token, that is what #set_random_secret will generate for each instance. The &lt;code&gt;:path&lt;/code&gt; option for Paperclip uses a proc to make sure each instance uses that attribute in the string that will be later interpolated further down. You can also see how I use the id partition too. Next, I have added two public instance methods. The first is #attachment_url and it will need a bit of explaining.
&lt;/p&gt;

&lt;p&gt;
  Currently in Paperclip, if you use the :url option and your :storage is set to :s3, then it is ignored. This could totally be intentional. So in a typical setup where you want the file download running through your own access control, you wold have a :url option like this &lt;code&gt;:url =&gt; &#39;/:class/:id/:filename&#39;&lt;/code&gt;. So this is what #attachment_url mimics, it simply gets around that shortcoming and points the download action back to your own controller. How that controller would work is beyond the scope of this article, see the resources section below for those links.
&lt;/p&gt;

&lt;p&gt;
  The last example method is #authenticated_s3_get_url which dips right on down to the AWS::S3 library to get the URL for the object in the bucket. AWS::S3&#39;s doc mention that it will automatically generate a secure GET url that expires in 5 minutes. However in my example, you can see where I am changing that to 10 minutes and forcing the HTTPS protocol. This would be the URL that your own controller would do the final redirect to. This URL is for your private objects in your S3 bucket and will only work for the amount of time you want it too! Meaning your app stays in complete control. Putting it all together one more time...
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# A MyDownload instance.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyDownload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# This is totally useless for private buckets/objects.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://s3.amazonaws.com/mybucket/000/000/004/147681c16fddc1e5/private.pdf?1258989107&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# This is what you use in your own views.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;attachment_url&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;my_downloads/4/private.pdf&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Your controller would redirect to this secure GET.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;authenticated_s3_get_url&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://s3.amazonaws.com/mybucket/000/000/004/147681c16fddc1e5/private.pdf?AWSAccessKeyId=0HJD3NS9CVWN2JV89K02&amp;amp;Expires=1258990967&amp;amp;Signature=8aWsq4o5gXfpIrRZyeETddnOeFw%3D&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;What Is That Noop Processor&lt;/h2&gt;

&lt;p&gt;
  Good eye! Did you see that I have a processor called Noop in the has_attached_file declaration? The default processor in Paperclip is the Thumbnail processor, which no matter what calls the ImageMagick identify command to see if it can do something to the file. I did not want that or any processing, just simple attachments. So I created this simple processor that just straight returns the file object. I made a &lt;a href=&quot;http://github.com/thoughtbot/paperclip/issues/#issue/118&quot;&gt;ticket on the Paperclip&#39;s issue page&lt;/a&gt; that hopefully would allow a &lt;code&gt;:processors =&gt; false&lt;/code&gt; option one day that would do this as well. So maybe one day it&#39;ll be a feature.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Paperclip&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Noop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Processor&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;file&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;UPDATE: Fog Example&lt;/h2&gt;

&lt;p&gt;
  Here is an updated &lt;code&gt;#authenticated_s3_get_url&lt;/code&gt; that I use with Fog as the backend storage for S3. This example illustrates 2 things. First that the bucket is named as your CNAME record which is also enforced in the &lt;code&gt;:fog_host&lt;/code&gt;. I do this so that I can generate URLs via Paperclip or Fog and always have my custom domain in place. When I gsub the &quot;s3.amazonaws.com&quot; out, I am left with just my CNAME domain/bucket name. Lastly, if you want to generate &quot;https&quot; URLs, use the &lt;code&gt;#get_https_url&lt;/code&gt; method.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyDownload&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;has_attached_file&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:storage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:fog_credentials&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;nf&quot;&gt;.&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;ss&quot;&gt;:fog_directory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;mybucket.domain.net&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:fog_public&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;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;ss&quot;&gt;:fog_host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://mybucket.domain.net&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&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;attachment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;:id_partition/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random_secret&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/:filename&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;authenticated_s3_get_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_now&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_http_url&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attachment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expires&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;nf&quot;&gt;gsub!&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/s3.amazonaws.com\//&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://almosteffortless.com/2009/03/22/randomize-filename-in-paperclip/&quot;&gt;Security Through Obscurity: Randomize Filename in Paperclip&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://thewebfellas.com/blog/2009/8/29/protecting-your-paperclip-downloads&quot;&gt;Your Access Control: Protecting Your Paperclip Downloads&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/thoughtbot/paperclip/issues/#issue/118&quot;&gt;Allow False Option For Processors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 23 Nov 2009 00:00:00 -0500</pubDate>
        <link>/2009/11/23/authenticated-s3-gets-for-private-objects-using-paperclip/</link>
        <guid isPermaLink="true">/2009/11/23/authenticated-s3-gets-for-private-objects-using-paperclip/</guid>
      </item>
    
      <item>
        <title>Meta Programming In...</title>
        <description>&lt;p&gt;
  Last nights &lt;a href=&quot;http://757rb.org/&quot;&gt;757.rb&lt;/a&gt; meeting was a great success. We did a talk titled &lt;em&gt;Introduction To Ruby &amp; Rails&lt;/em&gt; for all the new comers that might have been interested in learning more about both - from the ground up. Since Ruby was my first language and my toolbelt only extends to JavaScript and Objective-C, I&#39;m always interested in how other languages do the things that I love so much in Ruby. One of the biggest pluses for Ruby, to me, is the support for meta programming. In a typical rails model, you might see something like this.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&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;n&quot;&gt;has_many&lt;/span&gt;                &lt;span class=&quot;ss&quot;&gt;:articles&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;named_scope&lt;/span&gt;             &lt;span class=&quot;ss&quot;&gt;:active&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;:active&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;n&quot;&gt;validates_uniqueness_of&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates_presence_of&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:twitter_handle&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  For the untrained, those are class level methods writing code for an model that persists objects to a database. It looks like you are typing a spec or some declaration. In fact this is code writing other code. For newcomers to the language this is voodoo magic, but if you write programs and interfaces for others, meta programming is what it is all about. In fact, I use this technique all the time instead of writing the same code over and over again.
&lt;/p&gt;

&lt;p&gt;
  This concept is built into the core of Ruby. In fact here is an example from my talk on the class method built into Ruby called &lt;code&gt;attr_accessor&lt;/code&gt; which wraps a common paradigm of generating getter/setter methods for an instance variable. No magic here, the two class definitions below are equal and the interface of the object is the same. One is you do not have to write code over an over again in an vanilla class you care to have getter/setter methods for.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Same as writing&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@foo&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;foo&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;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;c1&quot;&gt;# Same results&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar&#39;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;bar&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;MyClass:0x100172b80 @foo=&quot;bar&quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So here is where I want to learn. I know how to write Ruby well enough that I can show one way below of how to write &lt;code&gt;attr_accessor&lt;/code&gt; if it did not exist in core Ruby. In my example below I made the method named &lt;code&gt;attribute_accessor&lt;/code&gt; to avoid the name conflict. Can anyone show me how this would be done in PHP, Java, Anything? What is meta programming like in those languages? How about posting a code example on &lt;a href=&quot;http://pastie.org/&quot;&gt;pastie.org&lt;/a&gt; and school me. I really am interested in knowing. BTW, my example only shows how the &lt;code&gt;attribute_accessor&lt;/code&gt; takes on argument. In actuality in Ruby, the built in &lt;code&gt;attr_accessor&lt;/code&gt; method takes multiple args and generates methods for each. For simplicity I narrowed down my examples and code to only take one argument so we can all stay focused.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MetaSkills&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;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassMethods&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;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;attribute_accessor&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attribute_reader&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attribute_writer&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;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;attribute_reader&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;define_method&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;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;instance_variable_get&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@&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;s2&quot;&gt;&quot;&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;attribute_writer&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&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;s2&quot;&gt;=&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;instance_variable_set&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@&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;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;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;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MetaSkills&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attribute_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bar&#39;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;bar&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;MyClass:0x100171c80 @foo=&quot;bar&quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Update: A friend was asking me about the namespaces you see in the module. It is technically possible to just open up the Class object and add my example additions. Typically in Ruby you are encouraged to create your own namespaced module and inject class/instance modules into the included class via the module&#39;s hook method &lt;code&gt;self.included&lt;/code&gt;. The pattern is like so &lt;a href=&quot;http://pastie.org/694019&quot;&gt;http://pastie.org/694019&lt;/a&gt;. So for instance, I could have done this &lt;a href=&quot;http://pastie.org/694038&quot;&gt;http://pastie.org/694038&lt;/a&gt; without taking advantages of the modules hook method.
&lt;/p&gt;
</description>
        <pubDate>Wed, 11 Nov 2009 00:00:00 -0500</pubDate>
        <link>/2009/11/11/meta-programming-in/</link>
        <guid isPermaLink="true">/2009/11/11/meta-programming-in/</guid>
      </item>
    
      <item>
        <title>Installing REE With The Snow Leopard SQL Server Stack</title>
        <description>&lt;p&gt;
  Today I noticed that Ruby Enterprise Edition 2009.10 was released and I have really been wanting to see if I could get the &lt;a href=&quot;http://github.com/rails-sqlserver&quot;&gt;SQL Server adapter&lt;/a&gt; tested and running under it. I am really curious how the speed improvements might look and will share my results below. This article assumes that you read my previous guide titled &lt;a href=&quot;/2009/09/05/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more/&quot;&gt;The Ultimate OS X Snow Leopard Stack For Rails Development - x86_64, MacPorts, Ruby 1.8/1.9, SQL Server, SQLite3, MySQL &amp; More&lt;/a&gt; as I will be building on top of it and referencing certain steps. So let&#39;s get down to business.
&lt;/p&gt;

&lt;h2&gt;Installing REE&lt;/h2&gt;

&lt;p&gt;
  The guys at Phusion have done a rock solid job. My previous attempts to install REE were a bomb, but it worked perfectly this time around. Simply &lt;a href=&quot;http://www.rubyenterpriseedition.com/download.html&quot;&gt;follow their directions&lt;/a&gt; and all will be OK. A snippet of my output is below. I liked how they picked a new default install directory of &lt;code&gt;/opt/ruby-enterprise-1.8.7-2009.10&lt;/code&gt;. Wicked cool! By the way, the only issue I had during install was when they were trying to install the pg gem for me. I ignored that error for now.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo ./ruby-enterprise-1.8.7-2009.10/installer

Where would you like to install Ruby Enterprise Edition to?
(All Ruby Enterprise Edition files will be put inside that directory.)
[/opt/ruby-enterprise-1.8.7-2009.10] :
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Configuring For REE&lt;/h2&gt;

&lt;p&gt;
  This is actually really easy. In my previous article, I talked about installing MacPorts and configure your profile. All I did this time around was add the REE path extensions after my MacPort extensions in my ZSH kit. So my path file now looks this below. If I ever want to just go back to my normal 1.8/1.9 toggle in &lt;code&gt;/opt/local/bin&lt;/code&gt;, I just comment out the REE path extensions, source my profile and I&#39;m back to my MacPort basics.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# MacPorts&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/bin /opt/local/sbin /opt/local/apache2/bin ~/.zshkit/bin &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/share/man &lt;span class=&quot;nv&quot;&gt;$manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/share/info &lt;span class=&quot;nv&quot;&gt;$infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# REE&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/ruby-enterprise-1.8.7-2009.10/bin &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/ruby-enterprise-1.8.7-2009.10/share/man &lt;span class=&quot;nv&quot;&gt;$manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/ruby-enterprise-1.8.7-2009.10/share/info &lt;span class=&quot;nv&quot;&gt;$infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  In the last guide, I mentioned how to switch between ruby 1.8/1.9 installed by MacPorts using a simple ZSH function. You can find this in my article title &lt;a href=&quot;/2009/01/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9/&quot;&gt;MultiRuby The MacPorts Way. Testing Your Rails Apps With Ruby 1.9&lt;/a&gt;. I have updated this to include a condition that will noop the function if you are running REE. So to recap. I use my &lt;code&gt;chruby&lt;/code&gt; function to switch between 1.8/1.9 installed by MacPorts and I use my profile extension to use REE. So what that profile change done... reload and/or open a new terminal window and test it out.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ which ruby
/opt/ruby-enterprise-1.8.7-2009.10/bin/ruby
$ which gem
/opt/ruby-enterprise-1.8.7-2009.10/bin/gem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Using REE With SQL Server&lt;/h2&gt;

&lt;p&gt;
  Let&#39;s get the easy stuff out of the way and install the needed gems for the adapter to work. Again, always &lt;a href=&quot;http://github.com/rails-sqlserver&quot;&gt;follow the TODO on the adapter page&lt;/a&gt; for the latest blessed versions of DBI and low level connectivity stuff. But just to recap the current needs.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo gem install dbi -v 0.4.1
$ sudo gem install dbd-odbc -v 0.2.4
$ sudo gem install activerecord-sqlserver-adapter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now the hard part, but I have an easy solution. You can do this the hard way and recompile the UTF8 version of ruby odbc by hand or you can type one command. I tried compiling it by hand and found that I had a few bugs, even after following &lt;a href=&quot;http://digitaljacob.riff.dk/2009/10/26/using-ruby-odbc-with-unixodbc-on-snow-leopard/&quot;&gt;Jacob Riff&#39;s notes&lt;/a&gt; when he had a similar issue when trying to hook ruby ODBC to use unixODBC in his &lt;code&gt;/usr/local&lt;/code&gt; . My solution was much simpler. I just coped my ruby 1.8.7 ruby odbc to the REE&#39;s vendor ruby directory. Hence:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo cp /opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin10/odbc.bundle /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/vendor_ruby/1.8/i686-darwin10.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here are my notes below on where I failed on installing ruby odbc by hand under REE. Feedback welcome, but good to know that the above simple copy worked just fine.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# Installing Ruby ODBC By Hand Notes

$ ruby -Cutf8 extconf.rb
$ make -C utf8
$ sudo make -C utf8 install
  /usr/bin/install -c -m 0755 odbc_utf8.bundle /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/i686-darwin10.0.0
$ sudo mv /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/i686-darwin10.0.0/odbc_utf8.bundle /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/i686-darwin10.0.0/odbc.bundle

Loading development environment (Rails 2.3.4)
dlsym(0x102c6e330, Init_odbc): symbol not found - /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/i686-darwin10.0.0/odbc.bundle
/opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/i686-darwin10.0.0/odbc.bundle
/opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Benchmarking REE vs MacPorts&lt;/h2&gt;

&lt;p&gt;
  Here is the good news, the above hacks and REE work! I have even tested the adapter and all is looking good from my end!!! Now how about those benchmarks? Here are the speed differences for running the full adapter test suite under 1.8.7 installed in MacPorts and the latest REE. Note, this is really non-scientific benchmarks, but I think they fun facts.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;Ruby 1.8.7 MacPorts (patchlevel 174)
Finished in 158.574243 seconds.
2190 tests, 7395 assertions, 0 failures, 0 errors

REE 1.8.7 (2009.10)
Finished in 146.834762 seconds.
2190 tests, 7636 assertions, 0 failures, 0 errors
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Installing Passenger&lt;/h2&gt;

&lt;p&gt;
  Since passenger was installed as part of the REE installation, all I had to do was run the apache2 installer again and paste in the new code into my httpd.conf file.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ which passenger-install-apache2-module
/opt/ruby-enterprise-1.8.7-2009.10/bin/passenger-install-apache2-module
$ sudo passenger-install-apache2-module
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 27 Oct 2009 00:00:00 -0400</pubDate>
        <link>/2009/10/27/installing-ree-with-the-snow-leopard-sql-server-stack/</link>
        <guid isPermaLink="true">/2009/10/27/installing-ree-with-the-snow-leopard-sql-server-stack/</guid>
      </item>
    
      <item>
        <title>The Zombie Shotgun Revisited</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/zombie_shotgun.jpg&quot; alt=&quot;Resident Evil Zombie Shotgun&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; My how time flies. Over a year ago &lt;a href=&quot;/2008/07/06/stop-exception-notifications-with-the-zombieshotgun/&quot;&gt;I created a simple bit of code&lt;/a&gt; that was useful for stopping ActionController routing errors from common Microsoft attacks from sending exception notification emails. Well now most people do not use exception notifications emails in favor of apps like Hoptoad. And hey, most code like this has moved to Rack middlewares.
&lt;/p&gt;

&lt;p&gt;
  Yesterday I noticed a &lt;a href=&quot;http://coderack.org&quot;&gt;rack code competition&lt;/a&gt; that encouraged &quot;most useful and top quality Rack middlewares&quot;. Well the Zombie Shotgun is pretty useful to me, but I&#39;m sure it&#39;s not top quality. That said, I did take the time to finally pick up on the rack internals and learn how to use &lt;a href=&quot;http://github.com/brynary/rack-test&quot;&gt;rack-test&lt;/a&gt;. If you want to check out the new tested Zombie Shotgun middleware and how I tested it using Shoulda, &lt;a href=&quot;http://github.com/metaskills/rack-zombieshotgun&quot;&gt;go see the project on my github page&lt;/a&gt;. Also, here is my &lt;a href=&quot;http://coderack.org/users/MetaSkills/entries/15-zombie-shotgun&quot;&gt;CodeRack entry&lt;/a&gt;.
&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Oct 2009 00:00:00 -0400</pubDate>
        <link>/2009/10/11/the-zombie-shotgun-revisited/</link>
        <guid isPermaLink="true">/2009/10/11/the-zombie-shotgun-revisited/</guid>
      </item>
    
      <item>
        <title>757 Studio_redirect</title>
        <description></description>
        <pubDate>Sun, 04 Oct 2009 00:00:00 -0400</pubDate>
        <link>/2009/10/4/757-studio</link>
        <guid isPermaLink="true">/2009/10/4/757-studio</guid>
      </item>
    
      <item>
        <title>757 Studio</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/757_studio_conference.png&quot; alt=&quot;757 Studio Website&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; Well it took up quite a bit of my free time and a good 2 weeks of no iPhone development, but I am very very happy that the organization of my first event has been a success so far. Check out &lt;a href=&quot;http://757studio.org/&quot;&gt; 757studio.org&lt;/a&gt; for full details. Andy Hunt is headlining the event with a talk on Pragmatic Thinking and Learning. Clinton Nixon and Jamie Pinkham will be following with talks on Ruby/Rails and iPhone/Cocoa. So even though I can not make it to the West Coast for RubyConf this year, it is not so bad with a local event like this.
&lt;/p&gt;

&lt;p&gt;
  Thanks so much to the &lt;a href=&quot;http://pragmaticstudio.com/&quot;&gt;Pragmatic Studio&lt;/a&gt; and the &lt;a href=&quot;http://www.pragprog.com/&quot;&gt;Pragmatic Bookshelf&lt;/a&gt; for sponsoring the event and most important to the speakers who are giving the talks. It is my sincere hopes that the Hampton Roads area can support more talks like this and hopefully the advocacy of Ruby/Objective-C to local software developers and business will pay off, for everyone!
&lt;/p&gt;

&lt;h2&gt;Some Background&lt;/h2&gt;

&lt;p&gt;
  I myself designed and developed the 757 Studio site. Yes, I used to be a designer back in the day, not a good one, but enough to get by. It took me a few days to get to something in PhotoShop that looked right to me. I&#39;m digging the brick and wood masthead. I think it gives the site both a modern &quot;.com&quot; office look, even though some say it feels dated. On the technical side, this was my first experience using &lt;a href=&quot;http://haml-lang.com/&quot;&gt;HAML&lt;/a&gt; and &lt;a href=&quot;http://sass-lang.com/&quot;&gt;SASS&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  I loved HAML so much, I doubt I&#39;ll ever go back to ERB templates in Rails again. The forced indentation and not having to manage closing tags was wonderful, it kept my views clean and forces you to use helpers like they should vs inlining a bunch of control structures. SASS, the companion to HAML is for generating your CSS. It too forces you to write a strict indentation for you CSS which works wonders. Not only will it generate deep selectors that maintain good scope, but the the layout helps you really understand where in the DOM tree you are.
&lt;/p&gt;

&lt;p&gt;
  If you want to see how all this came together and how I quickly hashed up a battle tested rails app for the studio&#39;s RSVP/Reservation system, &lt;a href=&quot;http://github.com/metaskills/757studio&quot;&gt;the project is on my Github page&lt;/a&gt;. Check out the &lt;code&gt;app/stylesheets/site.sass&lt;/code&gt; for the SASS CSS template and all the other views use HAML. Oh yea... I should also say that this was my first time playing with some webkit animations and effects. You may be able to spot them if you are on Safari/WebKit/Chrome.
&lt;/p&gt;
</description>
        <pubDate>Sun, 04 Oct 2009 00:00:00 -0400</pubDate>
        <link>/2009/10/04/757-studio/</link>
        <guid isPermaLink="true">/2009/10/04/757-studio/</guid>
      </item>
    
      <item>
        <title>Perform Occupational Maintenance_redirect</title>
        <description></description>
        <pubDate>Mon, 21 Sep 2009 00:00:00 -0400</pubDate>
        <link>/2009/9/21/perform-occupational-maintenance</link>
        <guid isPermaLink="true">/2009/9/21/perform-occupational-maintenance</guid>
      </item>
    
      <item>
        <title>Perform Occupational Maintenance!</title>
        <description>&lt;p&gt;
  One of the things that bugs me about some people in the technology field is that they do not perform enough occupational maintenance. Today I just purchased &lt;a href=&quot;http://www.pragprog.com/titles/sdcoach/agile-coaching&quot;&gt;&lt;em&gt;Agile Coaching&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;http://www.pragprog.com/titles/tibmac/beginning-mac-programming&quot;&gt;&lt;em&gt;Beginning Mac Programming: Develop with Objective-C and Cocoa&lt;/em&gt;&lt;/a&gt;. Both from the &lt;a href=&quot;http://www.pragprog.com/&quot;&gt;Pragmatic Bookshelf&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  If you have not done so already, do yourself a favor and go to the Pragmatic Bookstore, check yo self, and get better at what you do! Here is my bookshelf to date.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/occupational_maintenance.png&quot; alt=&quot;Prag Books&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 21 Sep 2009 00:00:00 -0400</pubDate>
        <link>/2009/09/21/perform-occupational-maintenance/</link>
        <guid isPermaLink="true">/2009/09/21/perform-occupational-maintenance/</guid>
      </item>
    
      <item>
        <title>The Ultimate Os X Snow Leopard Stack For Rails Development X86_64 Macports Ruby 1 8 1 9 Sql Server More_redirect</title>
        <description></description>
        <pubDate>Sat, 05 Sep 2009 00:00:00 -0400</pubDate>
        <link>/2009/9/5/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more</link>
        <guid isPermaLink="true">/2009/9/5/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86_64-macports-ruby-1-8-1-9-sql-server-more</guid>
      </item>
    
      <item>
        <title>The Ultimate OS X Snow Leopard Stack For Rails Development - x86_64, MacPorts, Ruby 1.8/1.9, SQL Server, SQLite3, MySQL &amp; More</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  If you are interested in &lt;a href=&quot;/2010/07/30/the-rvm-ruby-api/&quot;&gt;using RVM with a MacPort base for the SQL Server stack&lt;/a&gt;, check out this article.
&lt;/aside&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  &lt;a href=&quot;https://github.com/rails-sqlserver/tiny_tds&quot;&gt;TinyTDS&lt;/a&gt; is the upcoming de facto raw connection method for the SQL Server adapter. Please read the &lt;em&gt;&lt;a href=&quot;https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/wiki/Using-TinyTds&quot;&gt;Using TinyTDS&lt;/a&gt;&lt;/em&gt; wiki page on the adapter for switching. No longer do you have to worry about compiling ODBC layers!
&lt;/aside&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  I have written &lt;a href=&quot;/2010/07/19/a-macport-rubyodbc-update/&quot;&gt;an updated article on the MacPorts installation of the latest RubyODBC&lt;/a&gt;. It includes information pertaining to utf8 support.
&lt;/aside&gt;

&lt;p&gt;
  This guide is all encompassing but primarily focuses on the benefits of MacPorts, second the development stack for SQL Server and lastly on anything else a rails developer might need on OS X. If you are on a Mac, possibly running Snow Leopard and x86_64 is near and dear to your heart, this article is for you. &lt;strong&gt;If you do not &quot;have&quot; to use SQL Server, you can safely skip those sections and get to the Ruby1.9/Apache2/SQLite3/MySQL stuff.&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
  A small forward. If you are developing rails applications on a modern OS such as Snow Leopard and your needs never make it out of the shallow end of the default Ruby and SQLite3, then this how-to might not be for you. However if you find yourself needing more and you want it to be easy and optimized for your architecture, then I highly suggest MacPorts.
&lt;/p&gt;

&lt;p&gt;
  Even though this tutorial is based on MacPorts, there are alternatives if you have the guts. One is called &lt;a href=&quot;http://github.com/mxcl/homebrew/tree/masterbrew&quot;&gt;Homebrew&lt;/a&gt; by Max Howell, which offers a very easy package management system that is closely knit to OS X&#39;s own libraries. If your smart enough to manage the sheer amount of dependencies and different ways OS X wants to pull you when using their libraries, then have at it. I failed horribly and I consider myself somewhat smart. This article also focuses on running multiple versions of ruby, specifically 1.8.7 and a flavor of 1.9.x. Again to this end there are other solutions. One recent one is called &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;Ruby Version Manager (rvm)&lt;/a&gt; by Wayne Seguin. An incredible library, but something I could not use with my level of compiling source due to the fact that all the dependencies needed for SQL Server to ODBC are hard enough to get in place for one ruby installation. RVM has it&#39;s use, but if you just need two versions of ruby with a full 64-bit stack to SQL Server, read on.
&lt;/p&gt;

&lt;h2&gt;Install MacPorts&lt;/h2&gt;

&lt;p&gt;
  If you have not done so already, go &lt;a href=&quot;http://www.macports.org/install.php&quot;&gt;download MacPorts&lt;/a&gt; and run the installer and follow &lt;a href=&quot;http://guide.macports.org/&quot;&gt;their installation instructions&lt;/a&gt;. At the time of this writing, the current version is 1.8 and has tons of new stuff for Snow Leopard. If you use bash, the default shell on OS X, then add this to your ~/.profile.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;MANPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/share/man:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$MANPATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INFOPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/share/info:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INFOPATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  However, if you have &lt;a href=&quot;http://books.google.com/books?id=jKY-rDoJx3wC&amp;pg=PA115&amp;lpg=PA115&amp;dq=system+preferences+account+right+click+os+x+switch+to+zsh+default+shell&amp;source=bl&amp;ots=J0eyfcuH37&amp;sig=F4MrA0-NmqeprnqEneAhAdqJBPg&amp;hl=en&amp;ei=FFigSs73GMqc8QaAzoDeDw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=2#v=onepage&amp;q=system%20preferences%20account%20right%20click%20os%20x%20switch%20to%20zsh%20default%20shell&amp;f=false&quot;&gt;changed your default shell to ZSH&lt;/a&gt;, then put this in your ~/.zshenv file. I highly recommend switching your default shell to ZSH.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/bin /opt/local/sbin /opt/local/apache2/bin &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/share/man &lt;span class=&quot;nv&quot;&gt;$manpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/opt/local/share/info &lt;span class=&quot;nv&quot;&gt;$infopath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Important x86_64 Arch Notice&lt;/h3&gt;

&lt;p&gt;
  If you are running Snow Leopard and if your processor supports 64-bit, say a Core 2 Duo (consult your manual), then I highly suggest you set the MacPorts build_arch to force it to x86_64 for all installed ports. Remember, even if you have a unibody MacBook that can not boot the 64-bit kernel yet, that does not mean you are not running 64-bit apps. If your chip supports it and your on Snow Leopard, turn it on. Here is how.
&lt;/p&gt;

&lt;p&gt;
  Open up your MacPorts config file located at &lt;code&gt;/opt/local/etc/macports/macports.conf&lt;/code&gt;. Around line 59, find the section that has the build_arch and set it to x86_64. I have done this on both my unibody MacBook 13&quot; and Nehalem MacPro and everything has installed and works perfectly. This includes, ruby, git, and everything in between. See screenshots below for proof. Lastly, as a good habit, always run &lt;code&gt;sudo port selfupdate&lt;/code&gt; before installing ports. This makes sure you have the latest port files.
&lt;/p&gt;

&lt;h2&gt;Installing Ruby 1.8.7&lt;/h2&gt;

&lt;p&gt;
  By now Ruby 1.8.7 is the new 1.8.6. It will be the de-facto low level version that supports the enterprise. Frankly, 1.9.2 is really where it is at, but we all have our day jobs right. Either way it is good to have this version installed. You may ask why, 1.8.7 comes on OS X by default now in Snow Leopard? Correct, but the goal here is to get a base ruby installed whose libs are known and compiled the way we want them for our low level SQL Server libraries and their dependencies. The goal here is to avoid dependency hell.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install ruby

$ which ruby
/opt/local/bin/ruby

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Running that port install may have taken awhile, but let me show you something. Do you see that below? That&#39;s right, it&#39;s 64-bit ruby just like the default OS X installed 1.8.7. In fact, it&#39;s even a bit faster for some reason. So remember, using MacPorts this way means that everything you install that supports it, will be built for 64-bit.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/ruby18_darwin_x86_64.jpg&quot; alt=&quot;Ruby 1.8.7 64-bit Activity Monitor&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
  Lets get RubyGems package management up and running. Thanks again to MacPorts this is really easy. Some advice. Never use MacPorts to update RubyGems! We just used it to get it installed easily and quickly and in the right scope. If you need to update RubyGems, just use it&#39;s own self update feature.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install rb-rubygems
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Feeling good? Maybe like me, you wouldn&#39;t mind getting side tracked. If so, go ahead and install Subversion and/or Git. I personally like to install both of these since I use Git to manage my Subversion repos too.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install subversion
$ sudo port install git-core +svn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;The SQL Server Connection Stack&lt;/h2&gt;

&lt;p&gt;
  So back on track. The low level connection stack for SQL Server is pretty easy. We need unixODBC and not OS X&#39;s installed iODBC. After that FreeTDS needs to be installed with the +odbc variant so that it prefers the installed unixODBC. If you did not get side tracked above, these two installs could pull in a lot of dependency installs too and take some time. When we are done the final stack for connecting Rails to SQL Server will look something like this. Ruby/Rails =&gt; ActiveRecord SQL Server Adapter =&gt; DBI Gem w/DBD-ODBC =&gt; Ruby ODBC =&gt; unixODBC =&gt; FreeTDS =&gt; SQL Server.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install unixODBC
$ sudo port install freetds +odbc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  If all went well, you should see a configuration file notice after FreeTDS installs. This is just the port reminding us that we will ultimately have to configure FreeTDS to point to our SQL Server box. We&#39;ll get back to that later, for now, let&#39;s check that the install is looking good.
&lt;p&gt;

```
$ which tsql
/opt/local/bin/tsql

$ tsql -C
Compile-time settings (established with the &quot;configure&quot; script)
                            Version: freetds v0.82
             freetds.conf directory: /opt/local/etc/freetds
     MS db-lib source compatibility: no
        Sybase binary compatibility: no
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 5.0
                              iODBC: no
                           unixodbc: yes

$ tsql I
locale is &quot;en_US.utf-8&quot;
locale charset is &quot;utf-8&quot;
```

&lt;p&gt;
  See that last line after &lt;code&gt;tsql -C&lt;/code&gt;? It says unixodbc is a go! That&#39;s important. If for some reason you do not see this, then I suggest reinstalling unixODBC and FreeTDS in that order again. Also note the output of &lt;code&gt;tsql I&lt;/code&gt; and check out the locale settings. On Mac OS X, this seems to default to the utf-8 stuff we would expect. Possibly due to the default LANG env var is set to en_US.utf-8. However, on other systems this may note be right. See the configure FreeTDS section below for what to do if this is the case.
&lt;/p&gt;

&lt;p&gt;
  Right. That completes the UNIX&#39;y low level parts to get us talking to SQL Server, now to put the focus back on Ruby again by installing a few gems that will be needed. Here are the ones critical to this setup. Please consult the adapter&#39;s &lt;a href=&quot;http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/master&quot;&gt;README&lt;/a&gt; for update to date version information on the approved/latest gems for DBI.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo gem install dbi -v 0.4.1
$ sudo gem install dbd-odbc -v 0.2.4
$ sudo gem install activerecord-sqlserver-adapter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Almost there, we need one more piece, the Ruby ODBC bindings, so we can talk to the low level unixODBC. At the time of this writing, the MacPort portfile for rb-odbc was stuck at 0.9995 while the &lt;a href=&quot;http://www.ch-werner.de/rubyodbc/&quot;&gt;ruby odbc project page&lt;/a&gt; reports that the latest version is 0.9997. So here is a little lesson on how to edit a portfile to get our desired results.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ port file rb-odbc
/opt/local/var/macports/sources/rsync.macports.org/release/ports/ruby/rb-odbc/Portfile

$ port file rb-odbc | xargs mate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  The first command simply shows you how you can get MacPorts to revel where the port file is located. The second shows how you can pipe that result to xargs to get TextMate to open the portfile. Now that we have the port file in front of us, let&#39;s edit it so that it pulls the latest. First change all occurrences of the version to latest, in this case from 0.9995 to 0.9997. Lastly, download your target version from the ruby odbc project page and do a MD5 checksum on it. In my case, when I downloaded 0.9997, the md5 checksum is 36d21519795c3edc8bc63b1ec6682b99. Now change the odd md5 in the portfile to this new one, hit save, and close. Let&#39;s try it out.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install rb-odbc +utf8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So without little fuss, that should have worked. Did you notice how we have the +utf8 variant there? If your like me and have national/unicode columns in your database, this is a good thing. The adapter has tests and support for unicode as well.
&lt;/p&gt;

&lt;h2&gt;Configure The SQL Server Stack&lt;/h2&gt;

&lt;p&gt;
  First, let&#39;s configure FreeTDS to point to our server. Assuming you have TextMate a simple &lt;code&gt;mate /opt/local/etc/freetds/freetds.conf&lt;/code&gt; should get it open for us. FreeTDS even put in a few examples at the bottom of the file, I typically comment these out and add my own. In this example I am naming my server &quot;my_dev_server&quot;. Note that tds version section, I personally use tds version 8.0 and have tested this against my stack on all SQL Server types with the ActiveRecord tests. Some have reported that they have errors unless the use 7.0. Your mileage may vary. Save and close the file. &lt;strong&gt;UPDATE:&lt;/strong&gt; As noted above when running &lt;code&gt;tsql I&lt;/code&gt;, if you do not see a utf-8 locale setting, you may have to add this line &lt;code&gt;client charset = UTF-8&lt;/code&gt; to your configuration file. Here is a thread on &lt;a href=&quot;http://lists.ibiblio.org/pipermail/freetds/2006q3/020396.html&quot;&gt;how to set tsql&#39;s client character set&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;# A typical Sybase server
# [egServer50]
#   host = symachine.domain.com
#   port = 5000
#   tds version = 5.0

# A typical Microsoft server
# [egServer70]
#   host = ntmachine.domain.com
#   port = 1433
#   tds version = 7.0

[my_dev_server]
  host = 192.168.1.58
  port = 1433
  tds version = 8.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  It has been noted that Windows user may want to include client encodings and character sets that set UTF-8 values. If you are running on Windows, try out this style freetds conf.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[YOURSERVER]
 host             = yourserver.com
 port             = 1433
 tds version      = 7.0
 text size = 64512
 client encoding  = UTF-8
 client charset   = UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So after you have added your own server here, it is now time to configure unixODBC to use FreeTDS. Let&#39;s copy the default distribution files to the correctly named ones that unixODBC will look for.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo cp /opt/local/etc/odbc.ini.dist /opt/local/etc/odbc.ini
$ sudo cp /opt/local/etc/odbcinst.ini.dist /opt/local/etc/odbcinst.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Open up the newly copied &lt;code&gt;/opt/local/etc/odbcinst.ini&lt;/code&gt; file. More than likely, this will be the only time you ever edit this file. Add a FreeTDS configuration to it like so. No personal configuration options here, this just links up the MacPort installed unixODBC and FreeTDS.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[FreeTDS]
Decscription = FreeTDS driver for SQLServer
Driver = /opt/local/lib/libtdsodbc.so
Setup = /opt/local/lib/libtdsodbc.so
FileUsage = 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So the last thing is to create some DSNs in your &lt;code&gt;/opt/local/etc/odbc.ini&lt;/code&gt; file. It is very likely that you could edit this file often. Perhaps you do a lot of development and DB server changes. My personal file has over 20 some DSNs here. Here is one example. The name and description of the DSN is up to you. Take note how I made the server name &quot;my_dev_server&quot; line up to that used in the FreeTDS conf file. That is important. Flavor this to your tastes.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[my_dev_server_dsn]
Driver=FreeTDS
Description=My Server Connection
Servername=my_dev_server
Server=my_dev_server
Port=1433
Database=killer_app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here is an example of what your database.yml will look like. So by now you should be able to connect and work with your database. I have this working on quite a few Macs. If you found any issues, let me know, but a good place to start is running the adapter tests. That is of course if you have the stack setup right.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;development:
  adapter: sqlserver
  mode: ODBC
  username: rails
  password: secret
  database: killer_app
  dsn: my_dev_server_dsn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Going The Extra Mile With Ruby 1.9.x&lt;/h2&gt;

&lt;p&gt;
  Here is a little trick that I put in an article called &lt;a href=&quot;http://www.metaskills.net/2009/1/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9&quot;&gt;MultiRuby The MacPorts Way. Testing Your Rails Apps With Ruby 1.9&lt;/a&gt;. Follow the steps in this post to get 1.9.x installed and switchable between your default 1.8.7 install.
&lt;/p&gt;

&lt;p&gt;
  Remember, RubyGems already comes in 1.9 and that tutorial leaves your installed gems under 1.9 empty. Do the right thing and install gems on an as needed basis under 1.9. As for the ruby-odbc which is installed in the 1.8&#39;s vendor ruby directory, we will need to trick MacPorts to recompile and reinstall that for us. Here is how I did it. First make sure you in the right ruby version.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now we need to trick MacPorts to forget about the previous install so it will build and use the extconf.rb of the ruby 1.9 installation. Here are the commands to softly remove rb-odbc from MacPorts memory. If you want, you can change &lt;code&gt;rm -rf&lt;/code&gt; to just &lt;code&gt;mv&lt;/code&gt; and move these files to some other place.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;sudo rm -rf /opt/local/var/macports/receipts/rb-odbc
sudo rm -rf /opt/local/var/macports/software/rb-odbc
sudo rm -rf /opt/local/share/doc/rb-odbc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now you can tell MacPorts to reinstall ruby-odbc and it should create a new odbc.bundle in your &lt;code&gt;/opt/local/lib/ruby1.9/site_ruby/1.9.1/i386-darwin10/odbc.bundle&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install rb-odbc +utf8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here is the proof that I have 1.9 installed, working with SQL Server adapter and 64-bit. Thanks to the &lt;code&gt;chruby&lt;/code&gt; ZSH function described in my other post, I can easily switch between my ruby installs.
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/ruby19_darwin_x86_64.jpg&quot; alt=&quot;Ruby 1.8.7 64-bit Activity Monitor&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Complete The Marathon!&lt;/h2&gt;

&lt;p&gt;
  Installing apache2 and passenger, yes all 64-bit happy.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install apache2
$ sudo gem install passenger
$ sudo passenger-install-apache2-module
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  How about a more common setup for SQLite3? If you took the side track and installed subversion from above, then you already have SQLite3 installed via MacPorts. If not, that&#39;s easy to fix. Here is how to install it and the ruby sqlite3 gem. I have done this for both my 1.8.7 and 1.9.x install above and again I am all 64-bit happy and passing all my tets.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install sqlite3
$ sudo gem install sqlite3-ruby
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Installing MySQL and the ruby drivers are a bit more involved. This will get it installed and your launch control setup to act as if your box is a server, ie. load MySQL when it starts up.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install mysql5-server
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
$ sudo -u _mysql mysql_install_db5
$ sudo /opt/local/share/mysql5/mysql/mysql.server start
 Starting MySQL
 SUCCESS!
$ sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Nice, fully 64-bit and passing all the ActiveRecord tests for me. Note, sometimes you will have to reset your shell for new path binaries to become usable. It&#39;s always a good idea to open a new shell post a port install If you get an unfound &lt;code&gt;mysql_install_db5&lt;/code&gt;, try opening a new shell. Pay attention to some of the output from that command too. For instance, if you want to set a root user password. I choose not to do this for a dev DB, but I do like to limit the connections so that only local connections can be used by editing the conf file. To create yourself a my.cnf file, copy one of the templates in &lt;code&gt;/opt/local/share/mysql5/mysql&lt;/code&gt;, I choose to copy the large conf like so &lt;code&gt;sudo cp /opt/local/share/mysql5/mysql/my-large.cnf /opt/local/etc/mysql5/my.cnf&lt;/code&gt;. Then I edit the conf file and uncomment the link that says &quot;skip-networking&quot;. That way no one on the local network can hit my DBs. Lastly, here are some helpful aliases that I use.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my_stop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo launchctl stop org.macports.mysql5&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my_start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo launchctl start org.macports.mysql5&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my_rs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;my_stop ; my_start&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;myconf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mate /opt/local/etc/mysql5/my.cnf&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sat, 05 Sep 2009 00:00:00 -0400</pubDate>
        <link>/2009/09/05/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86-64-macports-ruby-1-8-1-9-sql-server-more/</link>
        <guid isPermaLink="true">/2009/09/05/the-ultimate-os-x-snow-leopard-stack-for-rails-development-x86-64-macports-ruby-1-8-1-9-sql-server-more/</guid>
      </item>
    
      <item>
        <title>Visor Terminal On Snow Leopard_redirect</title>
        <description></description>
        <pubDate>Tue, 18 Aug 2009 00:00:00 -0400</pubDate>
        <link>/2009/8/18/visor-terminal-on-snow-leopard</link>
        <guid isPermaLink="true">/2009/8/18/visor-terminal-on-snow-leopard</guid>
      </item>
    
      <item>
        <title>Visor Terminal on Snow Leopard</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: Hacks no longer needed, latest Visor/SIMBL is 64-bit Snow Leopard happy!
&lt;/aside&gt;

&lt;p&gt;
  This is a similar process that I had to go through back in the day when I had to hack visor terminal in Leopard. Basically the steps are pretty easy. First you just install &lt;a href=&quot;http://www.culater.net/software/SIMBL/SIMBL.php&quot;&gt;SIMBL&lt;/a&gt; and the &lt;a href=&quot;http://visor.binaryage.com/&quot;&gt;Visor.bundle&lt;/a&gt; as a SIMBL plugin in &lt;code&gt;~/Library/Application Support/SIMBL/Plugins/Visor.bundle&lt;/code&gt;. Once that is done here is the process to get this working in Snow Leopard.
&lt;/p&gt;

&lt;p&gt;
  First, you are going to need a copy of the Terminal.app from Leopard. I have &lt;a href=&quot;http://cdn.metaskills.net/VisorTerminal.zip&quot;&gt;provided a copy&lt;/a&gt; in the resources section below. This copy has a few key things changed in the app&#39;s Info.plist file. First I have changed the bundle identifiers and display names to VisorTerminal. This is how we are going to scope visor to use this particular app. It also allows us to set things like the LSUIElement to 1 so that this app does not show in the dock. A summary of the changes I made are below, all these are done already in the download file I provide. If you want to do these on your own copy of Leopard&#39;s Terminal.app then just right click on the app, show package contents, and edit the Info.plist file. Remember to rename the app to VisorTerminal.app.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleDisplayName&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;VisorTerminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleIdentifier&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.apple.VisorTerminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleName&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;VisorTerminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;LSUIElement&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now we need to edit the installed &lt;code&gt;~/Library/Application Support/SIMBL/Plugins/Visor.bundle&lt;/code&gt; so that it focuses on the old Leopard&#39;s terminal app (now VisorTerminal.app). Again right click on it and show the package contents, here is the complete plist below. You can see where I changed 3 places to VisorTerminal.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;plist&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleDevelopmentRegion&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;English&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleExecutable&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Visor&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleIdentifier&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.blacktree.visor&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleInfoDictionaryVersion&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;6.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleName&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Visor&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundlePackageType&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;BNDL&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleSignature&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;????&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleVersion&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Custom&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;GoogleML&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;TargetApplications&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;BundleIdentifier&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.apple.VisorTerminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;BundleVersionsRE&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;.*&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ExecPattern&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;*/VisorTerminal.app/Contents/MacOS/Terminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSPrincipalClass&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Visor&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;SIMBLTargetApplications&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;BundleIdentifier&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.apple.VisorTerminal&lt;span class=&quot;nt&quot;&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now when you launch VisorTerminal, it will be hidden from the dock and be the app that Visor.bundle focuses on. I really like how this app is removed from the doc too. More so I am just stoked it is working in Snow Leopard. As a last step, yoyou can add this to your login items so that it opens up automatically. I have found that it is a bit sticky when it first launches, but a few clicks in and out on first launch fixes that. One last note, I found it is easier to edit the custom properties for this terminal window like it&#39;s default color, font size, etc, if I turn off the LSUIElement.
&lt;/p&gt;

&lt;p&gt;
 &lt;strong&gt;UPDATE:&lt;/strong&gt; Thanks to Raptor007 for reminding us that if you want to get a head start on your terminal preferences looking the same for your VisorTerminal, you should copy &lt;code&gt; ~/Library/Preferences/com.apple.Terminal.plist&lt;/code&gt; to &lt;code&gt; ~/Library/Preferences/com.apple.VisorTerminal.plist&lt;/code&gt;. Thanks!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://visor.binaryage.com/&quot;&gt;Visor Project Page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.culater.net/software/SIMBL/SIMBL.php&quot;&gt;SIMBL Project Page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://cdn.metaskills.net/downloads/VisorTerminal.zip&quot;&gt;VisorTerminal.app (Leopard)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 18 Aug 2009 00:00:00 -0400</pubDate>
        <link>/2009/08/18/visor-terminal-on-snow-leopard/</link>
        <guid isPermaLink="true">/2009/08/18/visor-terminal-on-snow-leopard/</guid>
      </item>
    
      <item>
        <title>757rb Memcached Talk_redirect</title>
        <description></description>
        <pubDate>Sat, 18 Jul 2009 00:00:00 -0400</pubDate>
        <link>/2009/7/18/757rb-memcached-talk</link>
        <guid isPermaLink="true">/2009/7/18/757rb-memcached-talk</guid>
      </item>
    
      <item>
        <title>757rb Memcached Talk</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/memcache_slides.png&quot; alt=&quot;757.rb Memcached Presentation&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt; Earlier this week I gave a talk at our local ruby users group, &lt;a href=&quot;http://www.757rb.org/&quot;&gt;757.rb&lt;/a&gt;, about Memcached. Here recently I started picking it up again so that I could keep track of large sets of PK/FK changes during a big database move. In doing so, I decided to dig deep into it&#39;s internals and get a better grasp of how I would use it when I decided to do some serious fragment caching again.
&lt;/p&gt;

&lt;p&gt;
  The biggest thing I took away from the talk was -- First, that you can use an array of strings/objects for the key passed to various caching methods. If the object responds to #cache_key, the return of that method would be used. The default implementation of ActiveRecord&#39;s #cache_key method is to use the updated_at column for a unique timestamp. It is even smart enough to know weather the object is new or not. Thanks to Brennan Dunn for pointing that out! The second and most important thing was an article by &lt;a href=&quot;http://www.motionstandingstill.com/starting-simple-with-rails-caching/2008-11-27/&quot;&gt;Nahum Wild&lt;/a&gt; that talked about item level caching. This seemed like a strange place to start as typically I would start with a page or big sections of fragments. But as the demo app shows, this is an incredibly good place to start. Especially if you have heavy hitting pages of paginated views that talk to deep nested associations.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul class=&quot;mt10&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/metaskills/memcached-presentation-757rb&quot;&gt;Slideshare Version of my Memcached Presentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/assets/play_cache.zip&quot;&gt;The Demo Rails App of my Memcached Presentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.motionstandingstill.com/starting-simple-with-rails-caching/2008-11-27/&quot;&gt;Da Man, Nahum Wild&#39;s advice&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/andrewfromcali/mcinsight/tree/master&quot;&gt;GUI Version Of Memcached For Mac&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/nkallen/cache-money/tree/master&quot;&gt;CacheMoney Rails Plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 18 Jul 2009 00:00:00 -0400</pubDate>
        <link>/2009/07/18/757rb-memcached-talk/</link>
        <guid isPermaLink="true">/2009/07/18/757rb-memcached-talk/</guid>
      </item>
    
      <item>
        <title>Pdf Writer For Ruby 1 9_redirect</title>
        <description></description>
        <pubDate>Thu, 14 May 2009 00:00:00 -0400</pubDate>
        <link>/2009/5/14/pdf-writer-for-ruby-1-9</link>
        <guid isPermaLink="true">/2009/5/14/pdf-writer-for-ruby-1-9</guid>
      </item>
    
      <item>
        <title>PDF::Writer For Ruby 1.9</title>
        <description>&lt;p&gt;
  If you have legacy code written for ruby 1.8 and you want to run 1.9 and support your old &lt;a href=&quot;http://ruby-pdf.rubyforge.org/pdf-writer/&quot;&gt;PDF::Writer&lt;/a&gt; code, then just jump right over to &lt;a href=&quot;http://github.com/metaskills/pdf-writer/tree/master&quot;&gt;my Github pdf-writer fork&lt;/a&gt; and get it.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ gem install metaskills-pdf-writer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  If you are interested in knowing some of the dirty details about what pitfalls are under 1.9, read on. The biggest thing for me was getting used to the character encodings. Including string literals in your code that are say UTF-8 or some other encoding will blow up on you real quick. I highly highly suggest that you read &lt;a href=&quot;http://blog.grayproductions.net/categories/character_encodings&quot;&gt;James Edward Gray II: Everything About Ruby 1.9 Character Encoding Series&lt;/a&gt; series. He covers all the basics. If you want to see what two commits I did for pdf-writer, see &lt;a href=&quot;http://github.com/metaskills/pdf-writer/commit/ef9787c050a3b861089fc95f4f3af544f8e39219&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://github.com/metaskills/pdf-writer/commit/8f0ed3f1bd312bf86da47d721ca2f2070724efd6&quot;&gt;here&lt;/a&gt;. The second one is very very hackish, it basically add a marshaling support to the Mutex class which 1.9 does not have. The reason this is needed was due to pdf-writer&#39;s use of transaction simple to roll back object state as it is drawing across multiple pages. If you are like me and wish all your PDF::Writer code was in Prawn, your not alone!
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/pdf-writer/tree/master&quot;&gt;PDF::Writer For Ruby 1.9&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.grayproductions.net/categories/character_encodings&quot;&gt;James Edward Gray II: Everything About Ruby 1.9 Character Encoding Series&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9&quot;&gt;General Changes in Ruby 1.9&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://prawn.majesticseacreature.com/&quot;&gt;Prawn: Fast, Nimble PDF Generation For Ruby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 14 May 2009 00:00:00 -0400</pubDate>
        <link>/2009/05/14/pdf-writer-for-ruby-1-9/</link>
        <guid isPermaLink="true">/2009/05/14/pdf-writer-for-ruby-1-9/</guid>
      </item>
    
      <item>
        <title>Learning Objective C Iphone Development_redirect</title>
        <description></description>
        <pubDate>Tue, 10 Mar 2009 00:00:00 -0400</pubDate>
        <link>/2009/3/10/learning-objective-c-iphone-development</link>
        <guid isPermaLink="true">/2009/3/10/learning-objective-c-iphone-development</guid>
      </item>
    
      <item>
        <title>Learning Objective-C &amp; iPhone Development</title>
        <description>&lt;p&gt;
  What have I been up too lately? Well primary working my butt off in my day job and after that, I just finished a week of vacation. As an aside, I need to disconnect more often, my vacation was very relaxing. But what&#39;s more relaxing that doing things in the fresh outdoors? Well learning another programming language of course.
&lt;/p&gt;

&lt;p&gt;
  That is why this week I have seriously started learning Objective-C and iPhone application development. In fact I just got my approval today from Apple that I am a registered developer, see that pretty icon in the right column? So do you want to do the same? Below is a list of resources that I have found helpful to me. Let me explain something first, I am very tangential in my learning methods. Basically that means I take frequent breaks from my main course to learn deep details. For instance my main course is the &lt;a href=&quot;http://www.pragprog.com/titles/amiphd/iphone-sdk-development&quot;&gt;&lt;em&gt;iPhone SDK Development&lt;/em&gt;&lt;/a&gt; book. But I have found it very helpful to break early on and watch the &lt;a href=&quot;http://www.pragprog.com/screencasts/v-mcxcode/becoming-productive-in-xcode&quot;&gt;&lt;em&gt;Becoming Productive In Xcode&lt;/em&gt;&lt;/a&gt; videos. Knowing keyboard bindings and customizing my, dare I say it... IDE, just helps me get business done! Stay tuned for some updates.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.pragprog.com/titles/amiphd/iphone-sdk-development&quot;&gt;&lt;em&gt;iPhone SDK Development&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.pragprog.com/screencasts/v-bdiphone/writing-your-first-iphone-application&quot;&gt;&lt;em&gt;Writing Your First iPhone Application&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.pragprog.com/screencasts/v-mcxcode/becoming-productive-in-xcode&quot;&gt;&lt;em&gt;Becoming Productive In Xcode&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.pragprog.com/screencasts/v-bdobjc/coding-in-objective-c-2-0&quot;&gt;&lt;em&gt;Coding In Objective-C 2.0&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 10 Mar 2009 00:00:00 -0400</pubDate>
        <link>/2009/03/10/learning-objective-c-iphone-development/</link>
        <guid isPermaLink="true">/2009/03/10/learning-objective-c-iphone-development/</guid>
      </item>
    
      <item>
        <title>Git Subversion User Commit Reports_redirect</title>
        <description></description>
        <pubDate>Sun, 01 Feb 2009 00:00:00 -0500</pubDate>
        <link>/2009/2/1/git-subversion-user-commit-reports</link>
        <guid isPermaLink="true">/2009/2/1/git-subversion-user-commit-reports</guid>
      </item>
    
      <item>
        <title>Git &amp; Subversion User Commit Reports</title>
        <description>&lt;p&gt;
  Want a list of the users and the number of commits they made? Git makes it really really easy, while I could not find such an easy method on Subversion. Here they are.
&lt;/p&gt;

&lt;h2&gt;Git&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ git log | git shortlog -n -s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Subversion&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rubygems&#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;activesupport&#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;log_xml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`svn log -q --xml`&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;svn_logs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;XmlSimple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xml_in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log_xml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;logentry&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;report_hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svn_logs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;author&#39;&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;n&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&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;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:commit_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;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;n&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:commit_count&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;1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;report&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;report_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&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;a&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;report_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:commit_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reverse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cc_colsize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a_colsize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&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;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commits_authors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ca&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ca&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rjust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cc_colsize&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;s2&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ljust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_colsize&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;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 01 Feb 2009 00:00:00 -0500</pubDate>
        <link>/2009/02/01/git-subversion-user-commit-reports/</link>
        <guid isPermaLink="true">/2009/02/01/git-subversion-user-commit-reports/</guid>
      </item>
    
      <item>
        <title>Multiruby The Macports Way Testing Your Rails Apps With Ruby 1 9_redirect</title>
        <description></description>
        <pubDate>Tue, 20 Jan 2009 00:00:00 -0500</pubDate>
        <link>/2009/1/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9</link>
        <guid isPermaLink="true">/2009/1/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9</guid>
      </item>
    
      <item>
        <title>MultiRuby The MacPorts Way. Testing Your Rails Apps With Ruby 1.9</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: In a recent article, I &lt;a href=&quot;/2009/10/27/installing-ree-with-the-snow-leopard-sql-server-stack/&quot;&gt;covered how to install REE&lt;/a&gt; and have hence NOOP&#39;ed this function to ignore the symlinking when REE is installed.
&lt;/aside&gt;

&lt;p&gt;
  Ruby 1.9.1, the stable release, is just around the corner and if your like me, maybe you want to start playing around with it and perhaps test a few projects using 1.9 with edge rails 2.3. If so, and your on a Mac, then perhaps this installation method might appeal to you. I&#39;ll break this article up in two parts, the first will be on installing multiple versions of ruby and how to switch between them while the other will be some things I noticed when testing ruby 1.9 with edge rails on my favorite pet project &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master&quot;&gt;HomeMarks&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;Installing Ruby 1.9 &amp; Change Ruby Function&lt;/h2&gt;

&lt;p&gt;
  I love MacPorts and recommend using it even though OS X comes with ruby pre-installed. Doing so simply keeps things clean and separated in the &lt;code&gt;/opt&lt;/code&gt; directory vs mixing things in /usr where they might be clobbered by Apple during a system update. So no to dependency hell! This article assumes you already have ruby 1.8 installed via MacPorts, if not change some of the paths in the provided code below. Now... thanks to MacPorts it is easier than ever to get ruby 1.9 preview release 2 installed in it&#39;s own separate space.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install ruby19
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  MacPort has just added these ruby 1.9 binaries to your PATH in &lt;code&gt;/opt/local/bin&lt;/code&gt;. Nice and clean egh? From here you can start &quot;playing&quot; with 1.9 by just executing either &lt;code&gt;ruby1.9&lt;/code&gt; or &lt;code&gt;irb1.9&lt;/code&gt;, but that gets boring quick.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;erb1.9&lt;/li&gt;
  &lt;li&gt;gem1.9&lt;/li&gt;
  &lt;li&gt;irb1.9&lt;/li&gt;
  &lt;li&gt;rake1.9&lt;/li&gt;
  &lt;li&gt;rdoc1.9&lt;/li&gt;
  &lt;li&gt;ri1.9&lt;/li&gt;
  &lt;li&gt;ruby1.9&lt;/li&gt;
  &lt;li&gt;testrb1.9&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Let&#39;s hack up your setup so that you can quickly switch your whole ruby install back and forth transparently. The first step is to move the corresponding ruby 1.8 binaries to the same naming convention as their 1.9 counterparts. We will then use symlinks to change which one gets executed. Step one:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo mv /opt/local/bin/erb /opt/local/bin/erb1.8
$ sudo mv /opt/local/bin/gem /opt/local/bin/gem1.8
$ sudo mv /opt/local/bin/irb /opt/local/bin/irb1.8
$ sudo mv /opt/local/bin/rake /opt/local/bin/rake1.8
$ sudo mv /opt/local/bin/rdoc /opt/local/bin/rdoc1.8
$ sudo mv /opt/local/bin/ri /opt/local/bin/ri1.8
$ sudo mv /opt/local/bin/ruby /opt/local/bin/ruby1.8
$ sudo mv /opt/local/bin/testrb /opt/local/bin/testrb1.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So now that we have two versions of ruby installed, each in their own path suffix. So to switch back and forth without using these suffixes, we will need to create a symlink for each binary that points to the version we want to use. The users of the local ruby group &lt;a href=&quot;http://757rb.org/&quot;&gt;757rb&lt;/a&gt; came up with this ZSH function below. Place it into your &lt;a href=&quot;http://github.com/metaskills/zshkit/tree/master&quot;&gt;.zshkit&lt;/a&gt; or dotfile of choice and it will create/change symlinks for your ruby, irb, rake, etc.. that each point to the version you want to use. Calling it multiple times will simply toggle your ruby versions.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;chruby &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;ree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;ruby -e &lt;span class=&quot;s2&quot;&gt;&quot;puts RUBY_DESCRIPTION.include?(&#39;Ruby Enterprise Edition&#39;)&quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;true&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;NOOP: Currently using REE in your path.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;ruby -e &lt;span class=&quot;s2&quot;&gt;&quot;puts RUBY_VERSION.split(&#39;.&#39;)[0,2].join(&#39;.&#39;)&quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.9&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then
      &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.8&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else
      &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.9&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rubyexes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;erb gem irb rake rdoc ri ruby testrb autotest unit_diff rails&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$rubyexes&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;do
      &lt;/span&gt;sudo unlink &lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/bin/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      sudo ln -s &lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/bin/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/bin/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;done
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Now Running: &quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;ruby -v&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ chruby
Now Running: ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9]
$ chruby
Now Running: ruby 1.9.1 (2008-12-01 revision 20438) [i386-darwin9]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This works amazingly well at first. The one big gotcha is that you have to remember you have two gems directories. Any gem you installed under 1.8 will have to be installed again under 1.9. There are ways around this with some clever symlinking, but I&#39;d recommend against it. Note too, this also applies to any site/vendored libs or bundles, for instance ruby odbc.
&lt;/p&gt;

&lt;h3&gt;Things To Watch Out For&lt;/h3&gt;

&lt;p&gt;
  If you install a gem under a certain version of ruby that places an executable in say /opt/local/bin then you are going to want to watch out for a bad she bang. For instance if you install the ZenTest gem while running under ruby1.9 suffix, then the she bang for &lt;code&gt;/opt/local/bin/autotest&lt;/code&gt; would be incorrectly set to this &lt;code&gt;#!/opt/local/bin/ruby1.9 -ws&lt;/code&gt;. The simple fix is to just change it to the true sym link.
&lt;/p&gt;

&lt;h2&gt;Exploring Rails 2.3 &amp; Ruby 1.9&lt;/h2&gt;

&lt;p&gt;
  So far my HomeMarks project does not have any major issues with ruby 1.9. I&#39;m not surprised, it&#39;s very very slim ruby code due to the &lt;a href=&quot;/2008/05/24/the-ajax-head-design-pattern/&quot;&gt;AJAX head design pattern&lt;/a&gt;. I did however find a few new things about the changes an app will need when moving from 2.2 to 2.3.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Your test/test_helper.rb file will need to change to from &lt;code&gt;class Test::Unit::TestCase&lt;/code&gt; to &lt;code&gt;class ActiveSupport::TestCase&lt;/code&gt;. I&#39;m sure this change is related to future abstraction to choose Minitunit vs Test::Unit.&lt;/li&gt;
  &lt;li&gt;They have finally changed &lt;code&gt;app/controllers/application.rb&lt;/code&gt; to &lt;code&gt;app/controllers/application_controller.rb&lt;/code&gt;. Finally their hacks on that bad name are now gone. I found that I had to do this change manually on my own.&lt;/li&gt;
  &lt;li&gt;Disabling sessions for a single controller has been deprecated. Sessions are now lazy loaded. So if you don&#39;t access them, consider them off. You can still modify the session cookie options with request.session_options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Past that, about the only interesting thing I found in Ruby 1.9 was that Test::Unit is gone and is actually loading Miniunit. So things in rails that were requiring test/unit/error are going to fail.
&lt;/p&gt;
</description>
        <pubDate>Tue, 20 Jan 2009 00:00:00 -0500</pubDate>
        <link>/2009/01/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9/</link>
        <guid isPermaLink="true">/2009/01/20/multiruby-the-macports-way-testing-your-rails-apps-with-ruby-1-9/</guid>
      </item>
    
      <item>
        <title>Autotestify Brothers and Sisters</title>
        <description>&lt;p&gt;
  Based on my previous article &lt;a href=&quot;/2008/09/19/using-autotest-for-rails-plugin-development/&quot;&gt;Using Autotest For Rails Plugin Development&lt;/a&gt;, &lt;a href=&quot;http://brennandunn.com/&quot;&gt;Brennan Dunn&lt;/a&gt; wrote a ZSH function that helps him with his eager rails plugin work. Testing plugins is simply the most fun you will ever have. It&#39;s nice to test in isolation and easy to make a plugin test multiple rails versions, etc. Typically plugin testing is very fast to because you are not burdened with excessive tests in a big app that might use it. Just the ones needed to test the plugin. Enjoy this ZSH function.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;autotestify &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  git clone git://github.com/metaskills/autotest_railsplugin.git
  rm -rf ./autotest_railsplugin/.git
  mv ./autotest_railsplugin ./autotest
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Tue, 30 Dec 2008 00:00:00 -0500</pubDate>
        <link>/2008/12/30/autotestify-brothers-and-sisters/</link>
        <guid isPermaLink="true">/2008/12/30/autotestify-brothers-and-sisters/</guid>
      </item>
    
      <item>
        <title>Go Buy Envycasts Now!</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/envycasts_2.2.jpg&quot; alt=&quot;Envycasts: Ruby on Rails 2.2 Screencast&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; I got a chance to meet Gregg Pollack at this years RubyConf, a great guy. In fact I seem to owe him alot. Not only did I get 3 mentions lately on the main rubyonrails.org site, but it appears I got one of my &lt;a href=&quot;http://github.com/rails/rails/commit/f277e1d8fddfa417104c6fe095c15559f0c8713d&quot;&gt;2.2 additions&lt;/a&gt; mentioned in their new &lt;a href=&quot;http://envycasts.com/products/ruby-on-rails-22-screencast&quot;&gt;envycast that covers rails 2.2&lt;/a&gt;. Sweet!
&lt;/p&gt;

&lt;p&gt;
  So now it is my duty to help the Rails Envy guys to bank it Grossenbach-style. If you have not done so, go check out &lt;a href=&quot;http://envycasts.com/&quot;&gt;envycasts.com&lt;/a&gt; and put $9 down on one or two of their great vids! This stuff is a great resource for any ruby-rails&#39;ist. Put it on your TV and imagine your in your own little Orlando user group.
&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Nov 2008 00:00:00 -0500</pubDate>
        <link>/2008/11/26/go-buy-envycasts-now/</link>
        <guid isPermaLink="true">/2008/11/26/go-buy-envycasts-now/</guid>
      </item>
    
      <item>
        <title>SQL Server Adapter For Rails 2.2</title>
        <description>&lt;p&gt;
  &lt;a href=&quot;http://twitter.com/metaskills/statuses/1017702780&quot;&gt;&lt;img src=&quot;/assets/adapter_announcement.png&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;&lt;/a&gt; So that about sums up what I&#39;ve been doing for the past 4 weeks. A total rewrite of the &lt;a href=&quot;http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/master&quot;&gt;SQL Server Adapter for Rails&lt;/a&gt;. On top of passing all the Rails 2.2.2 tests, which is MAJOR news, it includes tons of new features. Unicode column support, pessimistic locking, date/time column casting, DDL transactions and &lt;a href=&quot;http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/master&quot;&gt;way more&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  On top of that. It was nice being mentioned on the rubyonrails.org website not for my &lt;a href=&quot;http://weblog.rubyonrails.org/2008/9/24/this-week-in-rails-september-24-2008&quot;&gt;first&lt;/a&gt;, &lt;a href=&quot;http://weblog.rubyonrails.org/2008/10/10/2-weeks-in-rails-october-10-2008&quot;&gt;second&lt;/a&gt;, but a &lt;a href=&quot;http://weblog.rubyonrails.org/2008/11/21/this-week-in-edge-rails&quot;&gt;THIRD&lt;/a&gt; time. Thanks Gregg!
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;UPDATE: I just got a &lt;a href=&quot;http://twitter.com/#!/d2h/statuses/1019410396&quot;&gt;nod from David&#39;s twitter&lt;/a&gt;. Thanks!&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 23 Nov 2008 00:00:00 -0500</pubDate>
        <link>/2008/11/23/sql-server-adapter-for-rails-2-2/</link>
        <guid isPermaLink="true">/2008/11/23/sql-server-adapter-for-rails-2-2/</guid>
      </item>
    
      <item>
        <title>Code-O-Lanterns: What Scares You?</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/php_lantern.png&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt; While reading the &lt;a href=&quot;http://tuaw.com/&quot;&gt;The Unofficial Apple Weblog&lt;/a&gt; today I noticed this sweet little &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; for OS X. After some feedback on the &lt;a href=&quot;http://757rb.org/&quot;&gt;757.rb&lt;/a&gt; group, I decided to make some Code-O-Lanterns.
&lt;/p&gt;

&lt;p&gt;
  Follow the instructions for the &lt;a href=&quot;http://www.killerrobots.com/screensavers/&quot; class=&quot;external link&quot;&gt;Jack-O-Lantern screensaver&lt;/a&gt; on where to put the carving files. If you are not on a Mac, I have taken some screen shots that you can use for desktop pictures. If you would like to see a code o lantern that is not up... just ask for one, providing it has a logo!
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/code_o_lanterns.png&quot; class=&quot;ms-Img ms-Img--responsive-ctr&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Code-O-Lanterns Files&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;757rb &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/757rb.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/757rb.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;AJAX &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/ajax.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/ajax.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;GIT &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/git.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/git.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Java &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/java.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/java.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;JavaScript &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/javascript.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/javascript.png&quot;&gt;[Desktop]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Perl &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/perl.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/perl.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;PHP &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/php.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/php.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Python &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/python.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/python.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Rails &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/rails.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/rails.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;SVN &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/carvings/svn.png&quot;&gt;[Carving]&lt;/a&gt; &lt;a href=&quot;http://cdn.metaskills.net/downloads/code_o_lanterns/desktops/svn.png&quot;&gt;[Desktop]&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 13 Oct 2008 00:00:00 -0400</pubDate>
        <link>/2008/10/13/code-o-lanterns-what-scares-you/</link>
        <guid isPermaLink="true">/2008/10/13/code-o-lanterns-what-scares-you/</guid>
      </item>
    
      <item>
        <title>Plug It In Plug It In</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/plugitin.png&quot; alt=&quot;Jack Has Many Things&quot; class=&quot;ms-Img ms-Img--responsive&quot; /&gt; I&#39;ve been busy putting together some plugins form misc work. If you did not catch my latest article &lt;em&gt;&lt;a href=&quot;/2008/9/28/jack-has_many-things&quot;&gt;Jack has_many :things&lt;/a&gt;&lt;/em&gt; where I covered GroupeScope, by all means check it out. I&#39;ve also just finished up a pretty solid backport of NamedScope that can be found on my Github page. It bills itself as a well tested complete back port for rails 1.2.6 and 2.0.4.
&lt;/p&gt;

&lt;p&gt;
  One thing that has been a real help while I&#39;ve been developing these plugins is this autotest class I put together specifically for developing rails plugins. I even got mention on rubyonrails.org. Sweet! More to come.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/named_scope/tree/master&quot;&gt;The NamedScope plugin.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot;&gt;The GroupedScope plugin.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot;&gt;The RailsPlugin class for Autotest.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.artlebedev.com/everything/vilcus/&quot;&gt;Vilcus plug dactyloadapter&lt;/a&gt;. Developed specially for people who enjoy closing electrical circuits with their own fingers.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 11 Oct 2008 00:00:00 -0400</pubDate>
        <link>/2008/10/11/plug-it-in-plug-it-in/</link>
        <guid isPermaLink="true">/2008/10/11/plug-it-in-plug-it-in/</guid>
      </item>
    
      <item>
        <title>Jack Has_many Things_redirect</title>
        <description></description>
        <pubDate>Sun, 28 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/9/28/jack-has_many-things</link>
        <guid isPermaLink="true">/2008/9/28/jack-has_many-things</guid>
      </item>
    
      <item>
        <title>Jack has_many :things</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/jack.png&quot; alt=&quot;Jack Has Many Things&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; I am Jack&#39;s sofa, stereo and wardrobe... I make Jack&#39;s life complete. I reside in a ActiveRecord table called &quot;things&quot; and Jack is the only one that has the key. This is Jack&#39;s life, and it&#39;s ending one minute at a time.
&lt;/p&gt;

&lt;p&gt;
  As rails developers, we have done this simple relationship over and over again. I&#39;m sure the has_many association is by far the most common in app/db design. It gives a single resource quick and easy access to others, but as your application grows, and depression sets in, we have to open up.
&lt;/p&gt;

&lt;h2&gt;It&#39;s cheaper than a movie, and there&#39;s free coffee.&lt;/h2&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/bob.png&quot; alt=&quot;Jack With Bob&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; I am talking about groups. Not the underground ones that carve us out of wood, but ones where we share with those around us. This is healing. The time has come to for our objects to do the same, but how?
&lt;/p&gt;

&lt;p&gt;
  The problem is that the ActiveRecord has_many association is scoped to an individual. No matter what conditions are tacked on, they are always &lt;a href=&quot;http://en.wikipedia.org/wiki/Pwn&quot;&gt;pwned&lt;/a&gt; by the proxy owner. The things they own have ended up owning you! Sure we could model some groupable schema and go through it, ActiveRecord is beautiful that way. But what about our hard work in all those existing has_many associations and scopes?
&lt;/p&gt;

&lt;h2&gt;I felt like destroying something beautiful.&lt;/h2&gt;

&lt;p&gt;
  The solution is on everyone&#39;s face, it is on the tip of everyone&#39;s tongue. I just gave it a name. It is called &lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot;&gt;GroupedScope&lt;/a&gt; and it will fundamentally change the constructed SQL for the has_many associations you want to share. The best part, it will leave those associations untouched for continued use. GroupedScope even works with your existing association extensions and any scopes. Let&#39;s have a session.
&lt;/p&gt;

&lt;p&gt;First we need to install the gem. So bundle up in your Gemfile.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;grouped_scope&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt; 3.1.0&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let&#39;s open up our people schema and the Person model, so Jack can share. First we add a group_id column to the people table.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PeopleCanChooseAGroup&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;Migration&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;up&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:integer&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;down&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remove_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group_id&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next we declare grouped_scope on a few associations.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:things&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:acquaintances&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:problems&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;grouped_scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:problems&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@jack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_by_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Jack&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_by_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Bob&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@jack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_attribute&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group_id&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;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update_attribute&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group_id&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So now every Person object in our app is now ready to share their &lt;code&gt;:things&lt;/code&gt; and their &lt;code&gt;:problems&lt;/code&gt;. I have also just arbitrarily put Jack and Bob into the same group. Declaring &lt;code&gt;grouped_scope&lt;/code&gt; in the model generates a new &lt;code&gt;group&lt;/code&gt; instance method that will allow us to either reflect on the group or delegate to the associations we have declared as now haveing grouped scope.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@jack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;Person id: 1, name: &quot;Jack&quot;, group_id: 1&amp;gt;, #&amp;lt;Person id: 2, name: &quot;Bob&quot;, group_id: 1&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;We all started seeing things differently.&lt;/h2&gt;

&lt;p&gt;
  The object returned by the group method, is an instance of &lt;code&gt;GroupedScope::SelfGrouping&lt;/code&gt;. It is far cooler than you think. It looks and acts as an enumerable array, but in reality it is a &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; object that can delegate to generated grouped association reflections which mimic their originals. Essentially giving the group access to all associated objects of its members, in this case their &lt;code&gt;:things&lt;/code&gt; and &lt;code&gt;:problems&lt;/code&gt;. Did I loose you?
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@jack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;problems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 6&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;problems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;problems&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,#&amp;lt;Problem...&amp;gt;,....]&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;problems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 8&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@jack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;problems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Without going into the detail of Jack&#39;s and Bob&#39;s problems, we can see that within the group, they are all shared. This is what the GroupedScope gem is really all about. It allows existing has_many associations to be called on the group which changes the SQL generated to be owned by the group, essentially from &lt;code&gt;id = 1&lt;/code&gt; to &lt;code&gt;id IN (SELECT id FROM people WHERE group_id = 1)&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
  The way it accomplishes this is pretty sweet. GroupedScope creates reflections that use a custom association scope method which uses a little Arel magic to build predicate conditions. Since it copies all your existing association reflection options, it can be really smart by maintaining all the logic in the existing association. So options like &lt;code&gt;:class_name&lt;/code&gt;, &lt;code&gt;:foreign_key&lt;/code&gt;, &lt;code&gt;:though&lt;/code&gt;, and &lt;code&gt;:extend&lt;/code&gt; will just work! It also lets you chain scopes existing scopes or use your custom association extensions on the original associations. Here is very contrived example:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:mental_issues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;MentalState&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dangerous&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:snap_tolerance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;n&quot;&gt;grouped_scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:mental_issues&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MentalState&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;scope&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:treatable_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&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;doctor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:doctor_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doctor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;vi&quot;&gt;@jack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mental_issues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dangerous&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;treatable_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@doctor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [#&amp;lt;MentalState...&amp;gt;,#&amp;lt;MentalState...&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;This is probably one of those &quot;cry for help&quot; things.&lt;/h2&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/marla.png&quot; alt=&quot;Marla&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; The GroupedScope gem is never quite done. It is however well tested and can do exactly all that I have outlined in ActiveRecord 3.1.0. I even have older gem versions that track our legacy 2-3-stable git branch.
&lt;/p&gt;

&lt;p&gt;
  Also, you may have noticed that &lt;code&gt;GroupedScope&lt;/code&gt; does not try to solve what your group business logic may look like. This is intentional and left to the end user to implement a &lt;code&gt;Group&lt;/code&gt; object. This object would be the primary key owner of the &lt;code&gt;group_id&lt;/code&gt; column in your models that declare grouped scope. You would also need to declare some sort of &lt;code&gt;belongs_to&lt;/code&gt; association to your custom group model too.
&lt;/p&gt;

&lt;p&gt;
  Lastly, if we you see something you might like in features or notice a bug, open a issue &lt;a href=&quot;https://github.com/metaskills/grouped_scope&quot;&gt;on our Github project&lt;/a&gt; page.
&lt;/p&gt;

&lt;h2&gt;I&#39;d like to thank the Academy.&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/grouped_scope/tree/master&quot;&gt;GroupedScope Gem On Github.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Fight_Club&quot;&gt;About the movie Fight Club.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://decisiv.net/&quot;&gt;My Workplace, Decisiv.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 28 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/09/28/jack-has-many-things/</link>
        <guid isPermaLink="true">/2008/09/28/jack-has-many-things/</guid>
      </item>
    
      <item>
        <title>Using Autotest For Rails Plugin Development_redirect</title>
        <description></description>
        <pubDate>Fri, 19 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/9/19/using-autotest-for-rails-plugin-development</link>
        <guid isPermaLink="true">/2008/9/19/using-autotest-for-rails-plugin-development</guid>
      </item>
    
      <item>
        <title>Using Autotest For Rails Plugin Development</title>
        <description>&lt;p&gt;
  I love &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;autotest&lt;/a&gt;. I have event posted before how to extend the idea of &lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;autotest sounds to a red/green playlist&lt;/a&gt; but now that I am taking more time to extract some of my work to plugins, I really wanted autotest to come with me. The problem is that the default autotest mappings do not play with rails conventions, the biggest being that test files for a lib match the name of the lib with &lt;code&gt;_test.rb&lt;/code&gt; at the END of the filename.
&lt;/p&gt;

&lt;p&gt;
  Today I posted a new project to my Github account, called &lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot;&gt;Autotest::Railsplugin&lt;/a&gt;. This project should be a great start for fleshing out all the typical mappings, ignore, libs, etc. that autotest needs to know about when developing a rails plugin. I invite you to download it and give it a try and provide feedback on missing details.
&lt;/p&gt;

&lt;h2&gt;To Install&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Rename the directory to &quot;autotest&quot;&lt;/li&gt;
  &lt;li&gt;Place inside of your pluginâ€™s root directory.&lt;/li&gt;
  &lt;li&gt;From your plugin root, you can now use autotest.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ autotest
loading autotest/railsplugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  By default, autotest will scan your present working directory for an autotest folder that has a discover.rb in it. So it should find and display the &lt;code&gt;loading autotest/railsplugin&lt;/code&gt; which means it found the plugin class just fine. If this is not the case make sure you have the directory named correctly. If you have a conflicting autotest directory for some reason you can always force the plugin class, again assuming you have it in the right, place using:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ autotest -railsplugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/metaskills/autotest_railsplugin/tree/master&quot;&gt;The New Autotest::Railsplugin on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;The Official ZenTest/AutoTest Site&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/4/6/autotest-playlist-for-red-green-feedback&quot;&gt;Autotest Playlist For Red/Green Feedback&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.fozworks.com/2007/7/28/autotest-sound-effects/&quot;&gt;Autotest Sound Idea from Jeremy Seitz @ FozWorks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 19 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/09/19/using-autotest-for-rails-plugin-development/</link>
        <guid isPermaLink="true">/2008/09/19/using-autotest-for-rails-plugin-development/</guid>
      </item>
    
      <item>
        <title>Going Horizontal On The Multicade_redirect</title>
        <description></description>
        <pubDate>Sun, 14 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/9/14/going-horizontal-on-the-multicade</link>
        <guid isPermaLink="true">/2008/9/14/going-horizontal-on-the-multicade</guid>
      </item>
    
      <item>
        <title>Going Horizontal On The Multicade</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/multicade.jpg&quot; alt=&quot;New multicade front view.&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; A few months ago I &quot;invested&quot; in a upright Galaga multicade. This is no costly refurb/restoration unit, but rather a customized new build from a great company called &lt;a href=&quot;http://www.arcadeshop.com/&quot;&gt;Arcadeshop Amusement&lt;/a&gt;. This place does two great things. First they will manufacturer/build you a new cabinet of your liking with all the parts professionally installed. This includes the display, &lt;a href=&quot;http://en.wikipedia.org/wiki/Jamma&quot;&gt;JAMMA&lt;/a&gt; harness, coin door assembly, control panel, and all artwork. I chose a classic Galaga/Ms.Pacman/Midway cabinet with a 19&quot; CRT display. My only deviation from the Galaga theme was a multicade control panel that had a 4-way joystick and two buttons for the left or right handed.
&lt;/p&gt;

&lt;p&gt;
  The second thing about this great company is that sell one of the coolest &lt;a href=&quot;http://www.arcadeshop.com/multi-pcb/multi-pcb.htm&quot;&gt;Multicade JAMMA PCBs&lt;/a&gt; I have seen. This board is programmable with a standard serial cable to run game ROM&#39;s in their approved list and that included such greats that I wanted like Galaga, Donkey Kong, Ms.Pacman, and Phoenix. For the record... I am not going after &lt;a href=&quot;http://en.wikipedia.org/wiki/Billy_Mitchell_(gamer)&quot;&gt;Billy Mitchell&#39;s&lt;/a&gt; record. I just wanted a nice low-tech diversion :)
&lt;/p&gt;

&lt;p&gt;
  So these games held me over for a time, but I really wanted to be a bit more flexible with the option to play some horizontal games. To that end, I invited my friend and fellow 757.rb&#39;er Geoff Parsons over to help me rotate my CRT. Before we got to that jun part, I had to manufacture my own horizontal cross members to hold the display. Thankfully a trip to LOWES steel part section and a new hack saw yielded a very decent support system, see here. The icing on the cake after we remounted the CRT was to replace the 4-way joystick with a new &lt;a href=&quot;http://www.happcontrols.com/joysticks/super_joy.htm&quot;&gt;4/8-way super stick from HAPP Controls&lt;/a&gt;, a new &lt;a href=&quot;http://www.lizardlickamusements.com/pages/boards.shtml&quot;&gt;19-in-one JAMMA PCB&lt;/a&gt; from Lizard Lick, and a new monitor bezel for the horizontal display. Now with this PCB, I am enjoying games like Super Mario Bros, Gradius, and Defender.
&lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;
  &lt;img src=&quot;/assets/multicade_horiz.jpg&quot; alt=&quot;New horizontal mounts for the multicade.&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt; For those that may ask, why did I not go with some sort of MAME system. Sometimes options are good... but too many are distracting. I really like the idea of having as much as my multicade mimic the old arcade cabinet as possible, and hacking on another computer to do that was not in the cards. I love just slapping in a JAMMA board and having the set of games I like. Low-tech fun!
&lt;/p&gt;
</description>
        <pubDate>Sun, 14 Sep 2008 00:00:00 -0400</pubDate>
        <link>/2008/09/14/going-horizontal-on-the-multicade/</link>
        <guid isPermaLink="true">/2008/09/14/going-horizontal-on-the-multicade/</guid>
      </item>
    
      <item>
        <title>In Hell Oo For Homemarks_redirect</title>
        <description></description>
        <pubDate>Mon, 18 Aug 2008 00:00:00 -0400</pubDate>
        <link>/2008/8/18/in-hell-oo-for-homemarks</link>
        <guid isPermaLink="true">/2008/8/18/in-hell-oo-for-homemarks</guid>
      </item>
    
      <item>
        <title>Hell&#39;OO HomeMarks</title>
        <description>&lt;p&gt;
  Well HomeMarks v2.0 is done and ready for the public. You can download it from my &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master&quot;&gt;Github project&lt;/a&gt; page. It has a real simple &lt;code&gt;rake app:bootstrap&lt;/code&gt; task that I came up with over the weekend will have you running a local copy in only a few seconds, give it a try. Sometime over the next few days, I&#39;ll move over the live site to this code base too. If you have not yet kept up on the implementation mantra I set down for the HomeMarks v2 project, you might want to &lt;a href=&quot;/2008/05/24/the-ajax-head-design-pattern/&quot;&gt;read an older post&lt;/a&gt; as well as this excerpt from the project README.
&lt;/p&gt;

&lt;blockquote&gt;
  HomeMarks was built using the Ruby on Rails framework with a heavy emphasis on object oriented JavaScript to make AJAX requests to a RESTful back-end. Unlike most Rails applications it does not use any inline JavaScript helpers nor does it rely on RJS (Remote JavaScript) for dynamic page updates. Instead it is nearly 100% unobtrusive JavaScript which uses simple HEAD or JSON responses to communicate to the objects on the page. This has yielded very slim controller code which is decoupled from the views and easily testable in isolation at a functional level.
&lt;/blockquote&gt;

&lt;p&gt;
  So what do I think of this implementation and writing all this object oriented JavaScript? Well - its been real hard, I&#39;ve been in JS Hell-OO for the better part of a few weeks as I came closer to finishing the project. Coming from a self inflicted addiction to unit/functional testing in rails, it is very hard to get into the habit of opening the browser to test view code. A big part of me hates writing all this JS without one bit of unit testing. I&#39;ve heard that Prototype v2 will have unit testing, that would be awesome!
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/oojs.gif&quot; alt=&quot;Hell&#39;oo for HomeMarks&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;
  So, bitching aside, I am very happy that my JS-fu is stronger. The end result besides all those buckets of water up the hill is that I can now really appreciate the ruby object model and how prototype strives to make JS class construction follow its example. Kudos really goes to Sam Stephenson for bridging the two object models. As I learned more about how prototype&#39;s classes work, I actually learned quite a bit about ruby too. Using that knowledge I gave a talk at the &lt;a href=&quot;http://757rb.org/&quot;&gt;Hampton Roads Ruby Users Group (757rb)&lt;/a&gt; on the topic. You can download the PDF version of the slides &lt;a href=&quot;http://www.slideshare.net/metaskills/oo-java-script-class-construction&quot;&gt; from the files section of the Google group&lt;/a&gt; page. Look for the file titled &lt;em&gt;OO JavaScript Class Construction&lt;/em&gt;
&lt;/p&gt;
</description>
        <pubDate>Mon, 18 Aug 2008 00:00:00 -0400</pubDate>
        <link>/2008/08/18/in-hell-oo-for-homemarks/</link>
        <guid isPermaLink="true">/2008/08/18/in-hell-oo-for-homemarks/</guid>
      </item>
    
      <item>
        <title>Stop Exception Notifications With The Zombieshotgun_redirect</title>
        <description></description>
        <pubDate>Sun, 06 Jul 2008 00:00:00 -0400</pubDate>
        <link>/2008/7/6/stop-exception-notifications-with-the-zombieshotgun</link>
        <guid isPermaLink="true">/2008/7/6/stop-exception-notifications-with-the-zombieshotgun</guid>
      </item>
    
      <item>
        <title>Stop Exception Notifications With The ZombieShotgun</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/zombie_shotgun.jpg&quot; alt=&quot;Resident Evil Zombie Shotgun&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;&lt;/span&gt; I am all about knowing how to survive a zombie invasion â€“ as much as I am a firm believer of using the right tool for a given job. It can not be argued that killing zombies with a shotgun to the head is as natural a fit as peanut butter to chocolate. They simply just go together.
&lt;/p&gt;

&lt;p&gt;
  Now real zombies may not be a daily nuisance, but &lt;a href=&quot;http://en.wikipedia.org/wiki/Zombie_computer&quot;&gt;computer zombies&lt;/a&gt; are a daily pain in the butt to network administrators as well as software engineers alike. If you have ever deployed a rails application into production that used some sort of exception notification, then you may at some time seen some zombie attacks throw a bunch of exceptions. My solution a few years back was to build my own ZombieShotgun module, see below.
&lt;/p&gt;

&lt;p&gt;
  The idea is simple, include the module and add this line to the very top of your filter chain &lt;code&gt;before_filter :shoot_zombies&lt;/code&gt;. Just like in real life, if rails detects a zombie attack, it will issue a 404 not found error in the beautiful rails syntax &lt;code&gt;head :not_found&lt;/code&gt;. I love it when code models the real world! Please note that there are a ton of better ways to accomplish user agent filtering, most notably, in your web server config... but that does not mean this is not a fun module to use.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ZombieShotgun&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;ZOMBIE_AGENTS&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;s1&quot;&gt;&#39;Microsoft Office Protocol Discovery&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Microsoft Data Access Internet Publishing Provider Protocol Discovery&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;FrontPage&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;ZOMBIE_ATTACK_DIRS&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;s1&quot;&gt;&#39;_vti_bin&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;MSOffice&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;verify-VCNstrict&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;notified-VCNstrict&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;protected&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shoot_zombies&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:not_found&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zombie_attack?&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;zombie_attack?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;zombie_attack_on_directory?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zombie_agent_attack?&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;zombie_attack_on_directory?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&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;n&quot;&gt;attack_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ZOMBIE_ATTACK_DIRS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attack_dir&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;zombie_agent_attack?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ua&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;HTTP_USER_AGENT&#39;&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;ua&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blank?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ZOMBIE_AGENTS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;any?&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;za&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;za&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ua&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 06 Jul 2008 00:00:00 -0400</pubDate>
        <link>/2008/07/06/stop-exception-notifications-with-the-zombieshotgun/</link>
        <guid isPermaLink="true">/2008/07/06/stop-exception-notifications-with-the-zombieshotgun/</guid>
      </item>
    
      <item>
        <title>Restful Ajax With Forgery Protection_redirect</title>
        <description></description>
        <pubDate>Wed, 18 Jun 2008 00:00:00 -0400</pubDate>
        <link>/2008/6/18/restful-ajax-with-forgery-protection</link>
        <guid isPermaLink="true">/2008/6/18/restful-ajax-with-forgery-protection</guid>
      </item>
    
      <item>
        <title>RESTful AJAX with Forgery Protection</title>
        <description>&lt;p&gt;
  Writing the new &lt;a href=&quot;http://www.homemarks.com/&quot;&gt;HomeMarks&lt;/a&gt; has been a great exercise. I&#39;ve learned that the &lt;a href=&quot;/2008/05/24/the-ajax-head-design-pattern/&quot;&gt;&lt;em&gt;AJAX Head &lt;strike&gt;Design Pattern&lt;/strike&gt; Implementation&lt;/em&gt;&lt;/a&gt; is more akin to developing a service-oriented application (SOA) since I have moved all client-side coupling from the controllers, like RJS, and only respond with HEAD or JSON data. Today I learned about &lt;a href=&quot;http://halcyon.rubyforge.org/&quot;&gt;Halcyon&lt;/a&gt; which is self described as a JSON web application framework built on Rack. If you take a look at their example, it looks a lot like HomeMarks v2, pretty cool!
&lt;/p&gt;

&lt;h2&gt;Getting To The Point&lt;/h2&gt;

&lt;p&gt;
  Last week I finally got around to doing the controller CRUD for the user&#39;s column objects. The core &lt;code&gt;homemarks/app.js&lt;/code&gt; JavaScript class contains the one (and only one) AJAX dispatcher/handler for the entire application. One problem that I ran into was how to continue to use forgery protection in rails to protect from CSRF attacks while relying solely on ad-hoc JavaScript requests to a RESTful back-end. I could have turned off &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/RequestForgeryProtection/ClassMethods.html#M000300&quot;&gt;&lt;code&gt;protect_from_forgery&lt;/code&gt;&lt;/a&gt; but that did not feel right. I wanted RESTful AJAX with forgery protection.
&lt;/p&gt;

&lt;h2&gt;My Solution&lt;/h2&gt;

&lt;p&gt;
  Since the HomeMarks v2 app has one AJAX dispatcher/handler for the entire app, all I had to do was to get the authenticity token into each and every request. It took a bit of digging in the rails source to find the methods I wanted but here both the ERB snippet I am using in my layout and the helper method found in my &lt;code&gt;application_helper.rb&lt;/code&gt; file.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;auth_params_js_var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;auth_params_js_var&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RAILS_ENV&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;test&#39;&lt;/span&gt;
    &lt;span class=&quot;sx&quot;&gt;%|var authParams = $H({#{request_forgery_protection_token}:#{form_authenticity_token.inspect}});|&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  What does this do? It creates a JS variable called &lt;code&gt;authParams&lt;/code&gt; at the window level (right term?) that all other functions can use. That variable returns a JavaScript hash that will have a single key/value pair for the rails authenticity token, see below. Basically at this point all you have to do is merge this hash with your &lt;code&gt;parameters&lt;/code&gt; option for your AJAX object. You can reference the HomeMarks app.js file in the resources section if you want to see how I did this on my app, code snippet below too.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;doAjaxRequest&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elmnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;finishMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;elmnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;post&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elmnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;onComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;completeAjaxRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;finishMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;finishMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The Latest HomeMarks &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/app.js&quot;&gt;app.js&lt;/a&gt; Class. See doAjaxRequest() function.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 18 Jun 2008 00:00:00 -0400</pubDate>
        <link>/2008/06/18/restful-ajax-with-forgery-protection/</link>
        <guid isPermaLink="true">/2008/06/18/restful-ajax-with-forgery-protection/</guid>
      </item>
    
      <item>
        <title>Coulda Shoulda Woulda_redirect</title>
        <description></description>
        <pubDate>Fri, 30 May 2008 00:00:00 -0400</pubDate>
        <link>/2008/5/30/coulda-shoulda-woulda</link>
        <guid isPermaLink="true">/2008/5/30/coulda-shoulda-woulda</guid>
      </item>
    
      <item>
        <title>Coulda Shoulda Woulda</title>
        <description>&lt;p&gt;
  It has been about 6 months now since I started using the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot;&gt;Shoulda&lt;/a&gt; testing plugin as my BDD/TDD tool of choice. Unlike a lot of other people, I did not flock to the RSpec bandwaggon. Personally I think RSpec is horribly bloated a sledgehammer for a simple issue, the need to have test code organized with nested setups and context blocks.
&lt;/p&gt;

&lt;p&gt;
  If you are new to Shoulda, I highly urge you to take a look at the &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda&quot;&gt;Thoughbot project page&lt;/a&gt; for it. If you have the time take a look at some of their other projects, like Paperclip. These guys are really smart. If you really want to see how shoulda can sing, check out &lt;a href=&quot;http://mwrc2008.confreaks.com/12saleh.html&quot;&gt;Tammer Saleh&#39;s presentation of it at the MountainWest RubyConf 2008&lt;/a&gt;. In that presentation he covers how you can extend Shoulda and write your own macros that generate additional tests. This is what my blog post is about.
&lt;/p&gt;

&lt;h2&gt;Sample Shoulda Macro For Functional Require Login&lt;/h2&gt;

&lt;p&gt;
  Here is a simple module that you might find for any restful authentication system. This would be included in your main &lt;code&gt;test_helper.rb&lt;/code&gt; file where it would add the normal login_as(user) method. The good part I want to point out is the &lt;code&gt;should_require_login(*actions)&lt;/code&gt; macro method that shows off a neat example of how you could use Shoulda in your functional tests at the class level.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AuthSystem&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;TestHelper&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;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;InstanceMethods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_require_login&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;actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Require login for &#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39; action&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;assert_redirected_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;login_url&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;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;InstanceMethods&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;login_as&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;vi&quot;&gt;@request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user_id&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;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&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;k&quot;&gt;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here is how it would look in the controller functional test. These are all contrived examples, but I think it illustrates how Shoulda can be used and in general how you can make your own macros that test at a higher level.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsersControllerTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;should_require_login&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:edit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:etc&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Fri, 30 May 2008 00:00:00 -0400</pubDate>
        <link>/2008/05/30/coulda-shoulda-woulda/</link>
        <guid isPermaLink="true">/2008/05/30/coulda-shoulda-woulda/</guid>
      </item>
    
      <item>
        <title>The Ajax Head Br Design Pattern_redirect</title>
        <description></description>
        <pubDate>Sat, 24 May 2008 00:00:00 -0400</pubDate>
        <link>/2008/5/24/the-ajax-head-br-design-pattern</link>
        <guid isPermaLink="true">/2008/5/24/the-ajax-head-br-design-pattern</guid>
      </item>
    
      <item>
        <title>The &quot;AJAX Head&quot; Design Pattern</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  Chris Williams did a really great write up on this pattern with great details on when/how to use it. Please considering &lt;a href=&quot;http://voodootikigod.com/ajax-head-design-pattern&quot;&gt;reading it&lt;/a&gt; afterward.
&lt;/aside&gt;

&lt;p&gt;
  This is the first of a few articles covering the total rewrite of the &lt;a href=&quot;http://homemarks.com/&quot;&gt;HomeMarks.com&lt;/a&gt; code base as I upgrade it to Rails 2.1. The &quot;AJAX Head&quot; pattern is the moniker I have assigned to methodology that has come about during said rewrite and the design decisions I choose early on. The rules were simple.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Total Unobtrusive JavaScript (&lt;a href=&quot;http://en.wikipedia.org/wiki/Tag_soup&quot;&gt;No Tag Soup&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;No RJS Controller Responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Rails makes it very easy to generate JavaScript with Ruby. The generator methods are extensive and cover both the Prototype and Scriptaculous libraries. The first version of HomeMarks used the generators exclusively to augment both the views and controller responses. In fact, I used a technique that is covered in the latest &lt;a href=&quot;http://www.pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;&lt;em&gt;Advanced Rails Recipes&lt;/em&gt;&lt;/a&gt; (way before it came out) under the &quot;Replace In-View Raw JavaScript&quot; chapter. Basically I created helper methods that generated JavaScript shared by both the views and controllers. It was a great technique but things &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/d33dab1405537db2d2dab86d79db415d9e7f56e5/app/helpers/application_helper.rb&quot;&gt;got messy quick&lt;/a&gt;. So life was good back then, I had a lot of Ruby code and a very dynamic site, but something did not seem right...
&lt;/p&gt;

&lt;h2&gt;What Is The AJAX Head Pattern?&lt;/h2&gt;

&lt;p&gt;
  It is an experiment into a vision to see what happens when you make the decision to totally go unobtrusive. Not just in your views but the controllers too! Imagine it this way &amp;mdash; your controllers are &lt;strong&gt;slim APIs&lt;/strong&gt;. They should do nothing but render a page on a GET request and when it comes to a POST/PUT/DELETE they should do nothing more than just say YES or NO (with errors).
&lt;/p&gt;

&lt;p&gt;
  Now lets think about that. What does that mean for an application that uses exclusive AJAX calls for dynamic page updates? It means that your visual client (the browser) will need to know ALOT less from the controller about what to do. It&#39;s great, the browser knows what is on the page, from the GET request, and what it needs to do with it. The client only needs to tell the remote resource store what it did. In this pattern the controller is relegated to nothing more than acting on model data and letting the client know if it succeeded or failed. So in short.
&lt;/p&gt;

&lt;blockquote&gt;
  The AJAX head design pattern forces the view and controller to work in isolation with the most minimal coupling possible. Kind of like a web service.
&lt;/blockquote&gt;

&lt;h2&gt;Tools and Code Needed&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;A application that does just about everything with AJAX.&lt;/li&gt;
  &lt;li&gt;Fluency with ActionController::Base#head method and HTTP status codes.&lt;/li&gt;
  &lt;li&gt;Site-wide exception rescues for ActiveRecord::RecordInvalid.&lt;/li&gt;
  &lt;li&gt;Global client-side AJAX request and response handlers.&lt;/li&gt;
  &lt;li&gt;Global client-side error handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  This may seem like a daunting list, but its pretty simple when you break it down. Let&#39;s do each one at at time with some of the current code from HomeMarks. The HomeMarks app is my first check on the list. When I did this app just about EVERYTHING was done via an AJAX call to update the page. Now on to the others.
&lt;/p&gt;

&lt;h2&gt;Head And Status Codes&lt;/h2&gt;

&lt;p&gt;
  The &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Base.html#M000454&quot;&gt;ActionController::Base#head&lt;/a&gt; method and &lt;a href=&quot;http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/status_codes.rb&quot;&gt;HTTP status codes&lt;/a&gt; are the second item on the list. The head method is very useful when you just want to respond with HTTP headers and no body content. This is typical behavior when an app responds to external web services requests. This is important to note, I chose to rely on head responses as a way to meet my design decision of not using any RJS responses from the controller.
&lt;/p&gt;

&lt;p&gt;
  The basic usage of the head method is simple, you just pass a symbol to the head method that is the lowercase underscore equivalent to an HTTP status code. For instance, if you wanted to respond with success, choose a status code from the 200 range, the easiest being &#39;OK&#39;, which would look like &lt;code&gt;head(:ok)&lt;/code&gt;. If you wanted to respond to bad authentication, you might use the 401 code like so, &lt;code&gt;head(:unauthorized)&lt;/code&gt;. Here is an example from HomeMarks restful user signup action.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsersController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:ok&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  There is actually a number of things going on in those 2 lines of code above. If the user is created, the AJAX request will get a simple &#39;OK&#39; message via the head method. Obviously the client will need to know what to do on its own. But if errors happen what to do? This brings us to...
&lt;/p&gt;

&lt;h2&gt;Invalid Object Handling&lt;/h2&gt;

&lt;p&gt;
  When Rails 2 came out, it gave us a very useful tool for our controllers, the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Rescue/ClassMethods.html&quot;&gt;ActionController#rescue_from&lt;/a&gt; method. It allows you to delegate exception handling to a method either per controller or site wide for a specific exception class. So enter the &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/lib/render_invalid_record.rb&quot;&gt;RenderInvalidRecord&lt;/a&gt; module, show below.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;RenderInvalidRecord&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;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rescue_from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;RecordInvalid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:render_invalid_record&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;kp&quot;&gt;protected&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render_invalid_record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;record&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;respond_to&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&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;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new_record?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;new&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;edit&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unprocessable_entity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;application/json&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xml&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:xml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unprocessable_entity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unprocessable_entity&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;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Once included in your application.rb file, every ActiveRecord::RecordInvalid exception will be handled by the render_invalid_record method. I use this pattern often and it is the primary reason I always use the &lt;strong&gt;bang methods&lt;/strong&gt; that end with an exclamation point, such as &lt;code&gt;create!&lt;/code&gt; or &lt;code&gt;save!&lt;/code&gt;. This module above was inspired by &lt;a href=&quot;http://github.com/josh/&quot;&gt;Joshua Peek&#39;s&lt;/a&gt; own module of the same name but has been edited here to fit my needs. Both the &quot;xml&quot; and &quot;html&quot; response formats are not used by HomeMarks but are included here to show how this module can work for any request type.
&lt;/p&gt;

&lt;p&gt;
  Now, how this fits into the AJAX Head pattern. The design decision of not having RJS responses means one of two things needs to come from the response. First, if the response is a success, meaning in the 200 range, then it is assumed that the client only needs to know that all is &#39;OK&#39;. Second, if the request has errors, then the response needs to communicate them. I choose JSON for the format of these errors since all AJAX request objects from Prototype automatically include a &lt;code&gt;application/json&lt;/code&gt; accept header. So that is why I changed both the &quot;js&quot; and the &quot;json&quot; response type in the RenderInvalidRecord module to both serialize the objects full error messages into a JSON array with an HTTP status code of 422 &quot;Unprocessable Entity&quot; which seemed to make the most sense to me. This pretty much wraps up the server side part of the pattern. Now onto the client side. Everything from here on is personal taste on how your client will react to an &quot;good&quot; or &quot;bad&quot; response object.
&lt;/p&gt;

&lt;h2&gt;Client-Side AJAX Handlers&lt;/h2&gt;

&lt;p&gt;
  I can not stress enough how much you have to bake your own functions to handle the client side reaction to both good and bad AJAX responses. The client&#39;s ability to know what to do with errors will be tightly coupled to AJAX handlers and the design choices of your site. In the examples below I have broken up methods in the same JavaScript classes to show you the parts for a specific behavior in a more concise manner. Also please note that I am using Prototype module and class organization heavily in HomeMarks. This allows me to build a Base JavaScript module and classes that mimic Rails models which inherit/mixin Base methods. I also use the Scriptaculous Builder class for creating DOM fragments too. Now back to business.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;video title=&quot;HomeMarks v2 Signup&quot; src=&quot;/assets/signup.mp4&quot; width=&quot;617&quot; height=&quot;473&quot; controls preload&gt;&lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;
  &lt;/a&gt;The first part of the AJAX head pattern was to use unobtrusive JavaScript. Because of this design choice, there are no &lt;code&gt;remote_form_for&lt;/code&gt; methods in the HomeMarks view code. All forms are simple &lt;code&gt;form_for&lt;/code&gt; methods. Below is a sample of the HomeMarksSite JavaScript class that creates AJAX handlers for all site forms. The below example is slimmed down to only show the initialization of this behavior for the signup form. But no matter which form is given this behavior the process is the same.
&lt;/p&gt;

&lt;ul class=&quot;ml20 mr20 mb20&quot;&gt;
  &lt;li&gt;The form&#39;s submit event is handled by &lt;code&gt;startAjaxForm()&lt;/code&gt;. It does the following:&lt;/li&gt;
    &lt;ul&gt;
      &lt;li&gt;Stops the normal submit behavior.&lt;/li&gt;
      &lt;li&gt;Adds a loading spinner in the #form_loading span.&lt;/li&gt;
      &lt;li&gt;Creates a new AJAX.Request using the forms own action. It also binds a function to delegate the logic of completing the form when the request is finished. More on that later in #2 below.&lt;/li&gt;
      &lt;li&gt;Finally it disables the form.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;li&gt;Once a response comes back from the server, the &lt;code&gt;delegateCompleteAjaxForm()&lt;/code&gt; function will be called with both the form object and the AJAX request object. The logic of this function includes:&lt;/li&gt;
  &lt;ul&gt;
    &lt;li&gt;Figuring out the &quot;mood&quot; of the request using getRequestMood() function which is part of my base module.&lt;/li&gt;
    &lt;li&gt;Sends the form and mood to the &lt;code&gt;completeAjaxForm()&lt;/code&gt; function. This function will replace the loading spinner with an image that reflects a good or bad response.&lt;/li&gt;
    &lt;li&gt;If the mood is good, meaning the response status code was within a 200 range, then the function will delegate to a function specific for that forms success using a simple case statement.&lt;/li&gt;
    &lt;li&gt;If this mood is bad, meaning the response status code not within a 200 range, the form will be enabled and the response JSON errors will be displayed. Currently I am using a modal class for this. Again more on that later. You may also note that my base module has a function called &lt;code&gt;messagesToList()&lt;/code&gt; that process the response into a DOM &amp;lt;ul&amp;gt; list.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HomeMarksBase&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;na&quot;&gt;getRequestMood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;good&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bad&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;messagesToList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;UL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;LI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;escapeHTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HomeMarksSite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HomeMarksBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;signupForm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;signup_form&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;startAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;form&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;imgSrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;loading_invert.gif&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&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;p&quot;&gt;{});&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loadArea&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;down&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#form_loading&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgTag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IMG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/images/&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)});&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadArea&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;onComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;delegateCompleteAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;disable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;delegateCompleteAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getRequestMood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;completeAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;good&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;supportForm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;completeSupportForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&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;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;flashHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DIV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;H2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Errors On Form!&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;messagesToList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashModal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;bad&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashHTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;completeAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;good&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&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;p&quot;&gt;{});&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loadArea&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;down&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#form_loading&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;completeId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;complete_ajax_form_&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/images/&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.png&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moodHtml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SPAN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;completeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;m0 p0&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IMG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})]);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadArea&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moodHtml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;completeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;completeSignupForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Thank your for signing up for your own HomeMarks page. An email has been sent to &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;your address along with a link to activate your account. If you have not done so already, please &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;take a moment to read the HomeMarks documentation.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;flashHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DIV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;H2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Signup Complete:&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;good&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashHTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;initEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;signupForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;signupForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;submit&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;startAjaxForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bindAsEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Client-Side Error Handling&lt;/h2&gt;

&lt;p&gt;
  Currently I have 3 client-side options that I can use to present errors back to the user from the JSON array in AJAX response. The first I started out with was using the &lt;code&gt;alert()&lt;/code&gt; function. That got boring real quick, but I left my implementation below which is part of the base class, called &lt;code&gt;messagesToAlert()&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
  The second slightly more interesting way was to create a flash message that used the same XHTML/CSS already present in my layout file. This was real easy to implement. Basically using the ERB fragment below in my layout, I guaranteed that I had 3 unique DOM elements for each of my flash message styles, good/bad/indif. Now all I had to do was to create an accessor in my HomeMarksSite class. I choose &lt;code&gt;this.flashes&lt;/code&gt;. I then created a &lt;code&gt;clearFlashes()&lt;/code&gt; function and then a &lt;code&gt;flash()&lt;/code&gt; function that would take the mood and the HTML to embed, viola â€“ I can now call &lt;code&gt;this.flash.(&#39;good&#39;,someHTML)&lt;/code&gt; and I get the same type of flash one would have seen if I set it in the controller and rendered. Note, this is what I used on the the signup form success above.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;% [:good,:bad,:indif].each &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%&amp;gt;
  &amp;lt;div id=&quot;flash_&amp;lt;%= key %&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; class=&quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flash_message&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; style=&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blank?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;none&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;block&#39;&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;s2&quot;&gt;&quot;&amp;gt;
      &amp;lt;span&amp;gt;&amp;lt;%= flash[key] %&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HomeMarksBase&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;na&quot;&gt;messagesToAlert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alertText&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;.\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alertText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alertText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alertText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;messagesToList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;UL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;LI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;escapeHTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messageList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HomeMarksSite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HomeMarksBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;div.flash_message&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clearFlashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;hide&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;update&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clearFlashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moodFlash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;flash_&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;moodFlash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;moodFlash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;site_wrapper&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;center&quot;&gt;
  &lt;video title=&quot;HomeMarks v2 Signup&quot; src=&quot;/assets/login.mp4&quot; width=&quot;617&quot; height=&quot;473&quot; controls preload&gt;&lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;
  Lastly, and probably the coolest, is the HomeMarksModal JavaScript class I created. This is my new default way of errors to a user. It can be seen in all my video examples on this page. To the right is another example of the login form that uses the same handlers described above. The HomeMarksModal JavaScript class is a bit large to paste inline in this article, but if you want to see the latest version, you can always get it &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/modal.js&quot;&gt;from the master branch of the homemarks_core project&lt;/a&gt; on Github.com. When you bind an instance of this object to the window/document, it will automatically crate the modal HTML using Builder. If you want to use it, make sure to get the CSS and images the project too. Below is a function that I put in my site class that allows me to call &lt;code&gt;this.flashModal(&#39;good&#39;,someHTML))&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HomeMarksSite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HomeMarksBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;flashModal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moodColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;flashMoodColors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;HmModal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moodColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Wrapping It Up&lt;/h2&gt;

&lt;p&gt;
  This article turned out a lot longer than I had wanted. The AJAX head pattern is pretty simple and it is really fun to see a two line user signup action yield such interactive results. Something also feels good about not putting view code in the controller, yes you can look at inline RJS as view code. Sure it requires that you do a lot more JS work, but there are benefits.
&lt;/p&gt;

&lt;p&gt;
  Image you have team of programmers, one person can stay in model/controller land while the other stays on the view/javascript. The model/controller person would write their own tests (PLEASE TAKE A LOOK AT MINE), while the view/javascript person might even take the initiative to use selenium to test the JavaScript. At the time of this writing, I have not done any selenium tests since the plugin for rails is not compatible for 2.0. That last benefit I could think of for this design pattern is that you could easily update view code without restarting your rails app. Just update the JavaScripts and your good to go.
&lt;/p&gt;

&lt;p&gt;
  In closing, please let me know what you think. Perhaps you have a better name for the design pattern? Perhaps someone else has a name for it already?
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Original &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/d33dab1405537db2d2dab86d79db415d9e7f56e5/app/helpers/application_helper.rb&quot;&gt;application_helper.rb&lt;/a&gt; from HomeMarks v1. An overboard example of shared view/controller tagsoup/rjs.&lt;/li&gt;
  &lt;li&gt;The latest &lt;a href=&quot;http://www.pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;&lt;em&gt;Advanced Rails Recipes&lt;/em&gt;&lt;/a&gt; book. See the chapter on &quot;Replace In-View Raw JavaScript&quot;. I discourage this technique used in mass.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Base.html#M000454&quot;&gt;ActionController::Base#head&lt;/a&gt; method.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/status_codes.rb&quot;&gt;HTTP status codes&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Rails API for the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionController/Rescue/ClassMethods.html&quot;&gt;ActionController#rescue_from&lt;/a&gt; method.&lt;/li&gt;
  &lt;li&gt;The latest &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/lib/render_invalid_record.rb&quot;&gt;RenderInvalidRecord&lt;/a&gt; module from the HomeMarks core.&lt;/li&gt;
  &lt;li&gt;The latest  &lt;a href=&quot;http://github.com/metaskills/homemarks/tree/master/public/javascripts/homemarks/modal.js&quot;&gt;HomeMarksModal&lt;/a&gt; JavaScript class from the HomeMarks core.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 24 May 2008 00:00:00 -0400</pubDate>
        <link>/2008/05/24/the-ajax-head-design-pattern/</link>
        <guid isPermaLink="true">/2008/05/24/the-ajax-head-design-pattern/</guid>
      </item>
    
      <item>
        <title>Using Rubyamp Textmate Bundle With Opt Ruby_redirect</title>
        <description></description>
        <pubDate>Fri, 25 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/25/using-rubyamp-textmate-bundle-with-opt-ruby</link>
        <guid isPermaLink="true">/2008/4/25/using-rubyamp-textmate-bundle-with-opt-ruby</guid>
      </item>
    
      <item>
        <title>Using RubyAMP TextMate Bundle With /opt Ruby</title>
        <description>&lt;p&gt;
  I&#39;ve been a TextMate user for a long time now and I&#39;m still finding new things to do with it. Here recently I wanted to use the &lt;a href=&quot;http://code.leadmediapartners.com/tools/rubyamp&quot;&gt;RubyAMP TextMate Bundle&lt;/a&gt; and was a little miffed to find that it was pointing to my OS X system ruby. The error message looked something like this when it went looking for my ruby/gems.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;No such file to load -- appscript (LoadError) from
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_requireâ€™
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `requireâ€™
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  My problem is that I use ruby installed from MacPorts (yes I have Leopard). I do this because I put a lot of crap and extra dependencies into my opt direcotry and I do not trust Apple to NOT blow away the crazy dependencey hell I would have ended up creating in the standard bin directories if I chose not to use MacPorts. I would have thought that my &lt;code&gt;TM_RUBY&lt;/code&gt; environment variable being set correctly to &lt;code&gt;/opt/local/bin/ruby&lt;/code&gt; in my TextMate preferences would have given RubyAMP enough info to find my correct gem environment. Obviously not... and it took me quite a bit of digging around to learn what else I needed to do. For starters, here is more than you ever wanted to know about &lt;a href=&quot;http://macromates.com/textmate/manual/shell_commands#search_path&quot;&gt;how TextMate gets the $PATH information&lt;/a&gt;. You can skip reading that and do these simple steps.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open /Developer/Applications/Utilities/Property List Editor.app&lt;/li&gt;
  &lt;li&gt;Click on &quot;New Root&quot;, now expand that node in the list view below.&lt;/li&gt;
  &lt;li&gt;Click on &quot;New Child&quot;, name it PATH&lt;/li&gt;
  &lt;li&gt;The child row for PATH should be a String type&lt;/li&gt;
  &lt;li&gt;Enter your PATH info here, should mimic your .bash_profile, without $PATH&lt;/li&gt;
  &lt;li&gt;Save this file to your Desktop as environment.plist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Now do this in the console, we need to move that file to an invisible &lt;code&gt;.MacOSX&lt;/code&gt; folder in your home directory. In all likelyhood this folder does not exists, nor does the environment.plist file inside of it, if so, please do your own work to make sure that you do not overwrite existing information. Now:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ mkdir ~/.MacOSX
$ mv ~/Desktop/environment.plist ~/.MacOSX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  With the file in place, you now have to log out and back in. To be on the safe side, just reboot. Now your OSX apps, including TextMate and it&#39;s bundles will have the correct PATH information to get to your binaries. See below for an example of what my environment.plist file looks like. Note too that my full PATH info in that file is this string &lt;code&gt;/opt/local/bin:/opt/local/sbin:/opt/local/lib/mysql5/bin:/opt/local/apache2/bin&lt;/code&gt;. Notice that path info after the apache2 path? This is where you should add the default path info for a Mac. Unlike the .bash_profile, you can not specify &lt;code&gt;$PATH&lt;/code&gt; and have it expanded from within a plist file. So to be on the safe side, when I added this, I put the standard mac path info at the end of my own additions. That standard path info is &lt;code&gt;/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin&lt;/code&gt;
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/envplist.png&quot; width=&quot;496&quot; height=&quot;302&quot; /&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/25/using-rubyamp-textmate-bundle-with-opt-ruby/</link>
        <guid isPermaLink="true">/2008/04/25/using-rubyamp-textmate-bundle-with-opt-ruby/</guid>
      </item>
    
      <item>
        <title>How To Use Passenger Mod_rails With Rails Edge 2 1_redirect</title>
        <description></description>
        <pubDate>Tue, 22 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/22/how-to-use-passenger-mod_rails-with-rails-edge-2-1</link>
        <guid isPermaLink="true">/2008/4/22/how-to-use-passenger-mod_rails-with-rails-edge-2-1</guid>
      </item>
    
      <item>
        <title>How to use Passenger (mod_rails) with rails edge 2.1</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: This issue has &lt;a href=&quot;http://github.com/FooBarWidget/passenger/commit/53301de464b323d364723854d3a8d293ab8327d6&quot;&gt;now been resolved&lt;/a&gt; in the official release.
&lt;/aside&gt;

&lt;p&gt;
  If you are like me and have &lt;a href=&quot;/2008/04/13/now-on-passenger-mod_rails/&quot;&gt;been using passenger&lt;/a&gt;, then you may have run into an issue when working with rails edge. I mean the REAL rails edge on Git, not that fancy rake task which I think is still pointing to a subversion snapshot. Let me take an aside on how to freeze rails edge to a project that you are managing in Git. This method is akin to using svn:externals. As a cop out, here are 3 links that you should read to learn how.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://railsontherun.com/2008/4/16/freezing-rails-with-git&quot;&gt;http://railsontherun.com/2008/4/16/freezing-rails-with-git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://woss.name/2008/04/09/using-git-submodules-to-track-vendorrails/&quot;&gt;http://woss.name/2008/04/09/using-git-submodules-to-track-vendorrails/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://git.or.cz/gitwiki/GitSubmoduleTutorial&quot;&gt;http://git.or.cz/gitwiki/GitSubmoduleTutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  OK... now that you know how to freeze the real rails edge to your git project, and if you have been using passenger, you may now have seen this error below. The basic problem is that passenger bypasses the work that the rails boot.rb does and in doing so, it only accounts for setting RAILS_ROOT during the ApplicationSpawner process and not the FrameworkSpawner process. In the latest rails, ActionPack is now relying on RAILS_ROOT to be set by calling Rails.root (shortcut method to that constant) when loading. So &lt;a href=&quot;http://github.com/metaskills/passenger/commit/69afcd75425a89c9d17d1fc40c0a7571d6bd547c &quot;&gt;my fix was to add the RAILS_ROOT to the FrameworkSpawner class&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Framework that failed to load: Vendor directory: /Users/foo/project/vendor/rails
Error message: Anonymous modules have no name to be referenced by
Exception class: ArgumentError
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://code.google.com/p/phusion-passenger/issues/detail?id=29&amp;can=1&amp;q=edge&amp;colspec=ID%20Type%20Status%20Priority%20Milestone%20Stars%20Summary&quot;&gt;Here is the Passenger Ticket&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com/FooBarWidget/passenger/commit/53301de464b323d364723854d3a8d293ab8327d6&quot;&gt;The official Passenger change set that fixed this issue.&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 22 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/22/how-to-use-passenger-mod-rails-with-rails-edge-2-1/</link>
        <guid isPermaLink="true">/2008/04/22/how-to-use-passenger-mod-rails-with-rails-edge-2-1/</guid>
      </item>
    
      <item>
        <title>Now On Passenger Mod_rails_redirect</title>
        <description></description>
        <pubDate>Sun, 13 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/13/now-on-passenger-mod_rails</link>
        <guid isPermaLink="true">/2008/4/13/now-on-passenger-mod_rails</guid>
      </item>
    
      <item>
        <title>Now on Passenger (mod_rails)</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/passenger_install.png&quot; width=&quot;515&quot; height=&quot;308&quot; class=&quot;floatr ml20&quot; /&gt; Well this is working out well so far. I&#39;m really liking the &lt;a href=&quot;http://modrails.com/index.html&quot;&gt;Passenger (mod_rails for Apache)&lt;/a&gt; extension. Right now I have this Mephisto site running it and it seems to be doing really well. Also, most people do not do this, but I run a full development stack Apache/MongrelCluster to mimic production boxes the best way I can. Now I am running mod_rails on all my development hosts.
&lt;/p&gt;

&lt;h2&gt;Some Things I Like&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;I do not have to fuss with OS X launchd startup scripts for my mongrels, just Apache.&lt;/li&gt;
  &lt;li&gt;Typically in a high volume site that runs mongrel behind an Apache proxy balancer, will get a large timeout and proxy error even if the mongrels are immediately available. Passenger has a &lt;a href=&quot;http://www.modrails.com/documentation/Users%20guide%20Nginx.html#_redeploying_restarting_the_ruby_on_rails_application&quot;&gt;nice way to restart&lt;/a&gt; the app, just touch the tmp/restart.txt file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Some Things I&#39;m Waiting For&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The RailsEnv can not be set per virtual host. You have to set RAILS_ENV = &#39;development&#39; in each app if you want to run mixed virtual hosts with different environments.&lt;/li&gt;
  &lt;li&gt;Normally I would pass environment variables to the console when issuing mongrel cluster starts. I would really love to see Passenger support &lt;a href=&quot;http://httpd.apache.org/docs/2.2/env.html&quot;&gt;apache environment variables.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 13 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/13/now-on-passenger-mod-rails/</link>
        <guid isPermaLink="true">/2008/04/13/now-on-passenger-mod-rails/</guid>
      </item>
    
      <item>
        <title>Autotest Playlist For Red Green Feedback_redirect</title>
        <description></description>
        <pubDate>Sun, 06 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/6/autotest-playlist-for-red-green-feedback</link>
        <guid isPermaLink="true">/2008/4/6/autotest-playlist-for-red-green-feedback</guid>
      </item>
    
      <item>
        <title>Autotest Infinite Loop On Failure Error_redirect</title>
        <description></description>
        <pubDate>Sun, 06 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/6/autotest-infinite-loop-on-failure-error</link>
        <guid isPermaLink="true">/2008/4/6/autotest-infinite-loop-on-failure-error</guid>
      </item>
    
      <item>
        <title>Autotest Playlist For Red/Green Feedback</title>
        <description>&lt;p&gt;
  Here is how to get a playlist of sounds that will be hooked to both your autotest :red and :green callbacks. Basically this gives you a folder of sounds that are played one after another, in a loop, as your tests pass or fail. See this move below for a quick example.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;object width=&quot;640&quot; height=&quot;505&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/HV_drKDclFA?fs=1&amp;amp;hl=en_US&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/HV_drKDclFA?fs=1&amp;amp;hl=en_US&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;640&quot; height=&quot;505&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;

&lt;h2&gt;Step 1: Install QTPlay from MacPorts&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install qtplay
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Step 2: Download My Autotest Playlist Files&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ cd ~
$ curl -O http://cdn.metaskills.net/downloads/autotest_playlist.tar
$ tar -xf autotest_playlist.tar
$ mv autotest_playlist .autotest_playlist &amp;amp;&amp;amp; rm autotest_playlist.tar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Step 3: Modify Your .autotest File&lt;/h2&gt;

&lt;p&gt;
  User your favorite editor to open your &lt;code&gt;~/.autotest&lt;/code&gt; file. And add this code below to it. Now you should be setup to have your own playlist of sounds that play using the &lt;code&gt;qtplay&lt;/code&gt; binary installed above. If you want to play around with the sounds, then &lt;code&gt;open ~/.autotest_playlist/sounds&lt;/code&gt; and start swapping out sounds. By the way, I made the :initialize and :quit sounds using the new Alex voice in Leopard. I hijacked some text to speech and then ran an audio tool called WavePad to speed change, flange, and chorus the voice a little bit.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~/.autotest_playlist/playlist&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Credits:&lt;/h2&gt;

&lt;p&gt;The idea for this came from &lt;a href=&quot;http://www.fozworks.com/2007/7/28/autotest-sound-effects/&quot;&gt;FoxWorks&lt;/a&gt;. Shouts out &quot;Thank You&quot;.&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/06/autotest-playlist-for-red-green-feedback/</link>
        <guid isPermaLink="true">/2008/04/06/autotest-playlist-for-red-green-feedback/</guid>
      </item>
    
      <item>
        <title>Autotest Infinite Loop On Failure &amp; Error</title>
        <description>&lt;p&gt;
  I just had an issue pop up today that seemed to be an issue for a few others. It seemed that all of a sudden that my autotest was stuck in an infinite loop after a failure or error. At first I thought it was related to some additions to my &lt;code&gt;~/.autotest&lt;/code&gt; file but after commenting out the whole lot of additions there, I realized it was something else. Here was my fix. Basically I think these errors are always related to a file that has changed during your test run. Now we just have to find out what that files are. Here are the steps I took to find out.
&lt;/p&gt;

&lt;h2&gt;Step 1: Gather Changed FIle Info&lt;/h2&gt;

&lt;p&gt;
  To find out what files are changing. To do this add the -v option when you start autotest. This will cause it to run in verbose mode. Now after you have failed a test and YOU KNOW YOU DID NOT SAVE ANYTHING watch what happens below your listing of test, assertions, failures, and errors. There will be an array dumped that will contain the files change that have caused autotest to start another test cycle. In my case here is what I saw.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;1) Failure:
test_truth(BookmarkTest)
[test/unit/bookmark_test.rb:6
test/unit/bookmark_test.rb:5]:
&amp;lt;false&amp;gt; is not true.

1 tests, 1 assertions, 1 failures, 0 errors
[[&quot;config/uuid.state&quot;, Sun Apr 06 13:58:55 -0400 2008]]
Dunno! config/uuid.state
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Ah ha... there it goes. I was using a UUID state file and it appears that file being written into the &lt;code&gt;config&lt;/code&gt; directory is the culprit. By default autotest does not ignore that directory.
&lt;/p&gt;

&lt;h2&gt;Step 2: Fix The Problem&lt;/h2&gt;

&lt;p&gt;
  We have two options here. You can either add an autotest exception in you &lt;code&gt;~/.autotest&lt;/code&gt; file or you can bail out. My option is to bail out because I should not be adding a file at run time to the config directory. It would seem a better place would be the &lt;code&gt;tmp&lt;/code&gt; directory. However if you think that adding an exception to your &lt;code&gt;~/.autotest&lt;/code&gt; file would be more appropriate, here is the syntax:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Autotest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:initialize&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autotest&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;s1&quot;&gt;&#39;.svn&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.hg&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.git&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&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;exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;autotest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 06 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/06/autotest-infinite-loop-on-failure-error/</link>
        <guid isPermaLink="true">/2008/04/06/autotest-infinite-loop-on-failure-error/</guid>
      </item>
    
      <item>
        <title>Macbook With 4gb Of Memory_redirect</title>
        <description></description>
        <pubDate>Thu, 03 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/3/macbook-with-4gb-of-memory</link>
        <guid isPermaLink="true">/2008/4/3/macbook-with-4gb-of-memory</guid>
      </item>
    
      <item>
        <title>How To Stop Delivery Of An Email Within An Actionmailer Method_redirect</title>
        <description></description>
        <pubDate>Thu, 03 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/4/3/how-to-stop-delivery-of-an-email-within-an-actionmailer-method</link>
        <guid isPermaLink="true">/2008/4/3/how-to-stop-delivery-of-an-email-within-an-actionmailer-method</guid>
      </item>
    
      <item>
        <title>MacBook With 4GB Of Memory</title>
        <description>&lt;p&gt;
  My MacBook is about a year old now and I&#39;ve read in &lt;a href=&quot;http://forums.macrumors.com/showthread.php?t=364707&quot;&gt;quite a few places&lt;/a&gt; that they could be upgraded to around 3.3GB of memory for this specific model. Unlike the latest MacBook which can &quot;as advertised&quot; accommodate 4GB of memory, the theory was that the Santa Rosa chipset can address all 4GB. It could very well be that technically my MacBook is only using ~3.3GB of that memory but the performance has been significant for a very &lt;a href=&quot;http://www.crucial.com/store/partspecs.aspx?imodule=CT25664AC667&quot;&gt;cheap stick of RAM&lt;/a&gt;. I highly recommend Crucial.
&lt;p&gt;

&lt;p&gt;
  I think this upgrade will have to hold me for some time. In general it has really helped my uptime. Odd as that is I think working with only 2GB of memory caused a lot of IO swap and memory corruption. Especially when stopping and starting so many different mongrels for local Rails development. As of this writing I have not found an issue that I have had to reboot for... uptime 10 days and going strong.
&lt;/p&gt;

&lt;p&gt;
  To keep my uptime going strong, I just purchased an app called &lt;a href=&quot;http://www.activata.co.uk/ifreemem/&quot;&gt;iFreeMem&lt;/a&gt; today after reading about it on &lt;a href=&quot;http://www.tuaw.com/&quot;&gt;TUAW&lt;/a&gt;. Because I use PhotoShop ever now and then it really helped having this utility free up some memory that it would not release. So far it is working great!
  &lt;/p&gt;
</description>
        <pubDate>Thu, 03 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/03/macbook-with-4gb-of-memory/</link>
        <guid isPermaLink="true">/2008/04/03/macbook-with-4gb-of-memory/</guid>
      </item>
    
      <item>
        <title>How To Stop Delivery Of An Email Within An ActionMailer Method</title>
        <description>&lt;p&gt;
  OK, so you want to keep your code placement REALLY organized. You have &lt;a href=&quot;/2008/03/26/don-t-be-a-plinko-programmer/&quot;&gt;read about my persnicketyness&lt;/a&gt; and now you want to practice the best in concern placement and keep those controllers of yours really slim. Like me, you may want to try and keep controller feature additions to very specific one liners of code. Organizing your controller code to do just that with ActiveRecord models or even your own custom classes is a pretty easy task, but how do you keep things simple when dealing with controller actions that have to send email AND you want that single email link of code to be responsible for everything in it&#39;s own encapsulated way.
&lt;/p&gt;

&lt;p&gt;
  The answer is to push the logic back to the model again. Your controllers should not be concerned with the logic that deals with your own business rules for sending email. The problem with ActionMailer is that most people just use the dynamic &lt;code&gt;MyMailerClass.deliver_&lt;/code&gt; methods that utilize &lt;code&gt;method_missing&lt;/code&gt; to instantiate a mailer classs, and send an email in one fell swoop. I like this usage too, but the challenge is how to tell an instance of a the ActionMailer::Base class that it needs to stop delivery within a method definition that is all set to deliver? The answer is Ruby singleton method magic.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActionMailer&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Base&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# A simple way to short circuit the delivery of an email from within&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# deliver_* methods defined in ActionMailer::Base subclases.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_not_deliver!&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;deliver!&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;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  I suggest placing this code into your &lt;code&gt;lib/core_ext/action_mailer.rb&lt;/code&gt; file. It will allow you to write mailer methods that can short circuit themselves to stop delivery. For instance:
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyMailerClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionMailer&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;user_notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_not_deliver!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blank?&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;c1&quot;&gt;# In your controller code.&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;MyMailerClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deliver_user_notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now you do not have to worry about placing delivery concerns in the controller and even worse duplicate that code when you have to use the same mailer method in multiple places. This works by letting the instance of the ActionMailer::Base class define it&#39;s own deliver! method which trumps the delier! method called by that object normally defined in ActionMailer::Base.
&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ruby-doc.org/docs/UsersGuide/rg/singletonmethods.html&quot;&gt;About Singleton Methods&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://redhanded.hobix.com/inspect/methodsThatSelfDestruct.html&quot;&gt;Methods That Self-Destruct&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 03 Apr 2008 00:00:00 -0400</pubDate>
        <link>/2008/04/03/how-to-stop-delivery-of-an-email-within-an-actionmailer-method/</link>
        <guid isPermaLink="true">/2008/04/03/how-to-stop-delivery-of-an-email-within-an-actionmailer-method/</guid>
      </item>
    
      <item>
        <title>Don T Be A Plinko Programmer_redirect</title>
        <description></description>
        <pubDate>Wed, 26 Mar 2008 00:00:00 -0400</pubDate>
        <link>/2008/3/26/don-t-be-a-plinko-programmer</link>
        <guid isPermaLink="true">/2008/3/26/don-t-be-a-plinko-programmer</guid>
      </item>
    
      <item>
        <title>Don&#39;t Be A Plinko Programmer</title>
        <description>&lt;p class=&quot;clearfix&quot;&gt;
  &lt;img src=&quot;/assets/plinko.png&quot; alt=&quot;Plink Game&quot; class=&quot;floatr ml20&quot; /&gt;
  One of the things that I have really grown persnickety about is the placement of code. For example, I am a huge advocate that controllers in a rails project should read like a mini Domain Specific Language (DSL) and that as much logic as possible be delegated to the models. In my opinion the best way to do that in a Rails project is to learn the proper usage of ActiveRecord Association Extensions. You can check out the Rails API &lt;a href=&quot;http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html&quot;&gt;on this page&lt;/a&gt; and scroll down to the section called &quot;Association Extensions&quot; if you read the official docs. In short:
&lt;/p&gt;

&lt;blockquote&gt;
  The proxy objects that control the access to associations can be extended through anonymous modules. This is especially beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association.
&lt;/blockquote&gt;

&lt;p&gt;
  Now this brings me to the topic of my article, what is a Plinko Programmer. If you have no class and don&#39;t even know what Plinko is, &lt;a href=&quot;http://en.wikipedia.org/wiki/Plinko&quot;&gt;Wikipedia has a great write up&lt;/a&gt; on it. A Plinko Programmer is someone that writes code which smells in a few ways. For instance they use excessive arguments in their methods and unnecessarily pass objects around as arguments. They like to bake their own &lt;a href=&quot;http://www.ruby-doc.org/core/classes/Enumerable.html&quot;&gt;Enumerable&lt;/a&gt; methods vs using the ones readily available. They even like to create large class level methods, or even worse controller actions, that really should be factory methods in 2 or more classes. The analogy is akin to much of the Java code I have rewritten in Rails. Plinko code is long and full of if/else conditions, it&#39;s just like the game. You drop an object in the top and just watch it &quot;by chance&quot; work it&#39;s way thru the method/function. It is a nasty way to write code and if for anything else it is illegible and hard to test.
&lt;/p&gt;

&lt;h2&gt;What Is The Right Way?&lt;/h2&gt;

&lt;p&gt;
  Here is a short example of how to use Association Extensions. This is a simple example, but when you get used to really using association extensions you will begin to see just how much of your code really belongs there. Let&#39;s assume you have a simple invoice and items class.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Invoice&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;InvoiceItem&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;invoice_id&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InvoiceItem&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;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoice&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Some complex stuff&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now let&#39;s say that you want to have a clean little method for getting the total of the Invoice object. Resist the temptation to simple add an instance method to the Invoice class. Although it is logical to have &lt;code&gt;@invoice.total&lt;/code&gt; it is better to add it too the association extension. Why? Well think about it, what are you doing? The answer is that you are working with a &quot;collection&quot; of InvoiceItems. It turns out that this is the first part of what the association extension is for, an easy way to work with a collection that has the benefits of knowing how to proxy to methods that can reflect back down to the original caller. It&#39;s hard to explain but I&#39;ll just leave you with my persnickety code example. Your general rule should be if you are working with the collection in part or in total, then the association extension is the place for it. Keep in mind that so far I have only talked about has_may association extensions, you can do these for one-to-on belongs_to and has_one associations as well.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Invoice&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;InvoiceItem&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;invoice_id&#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;proxy_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&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;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InvoiceItem&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;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoice&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Some complex stuff&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;c1&quot;&gt;# Would yeild code like:&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@invoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;P.S. Here lately I&#39;ve been creating an app/concerns directory where I put modules that encompass mixed in behavior in so many ways for top level models. Typically these modules/concerns shared instance and class methods with two or more primary classes. They have become an excellent home for association extensions since many large applications will define the same association from different models in the object. To keep the code from duplicating in those different models it is better to do something like this&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# This file &quot;invoice_item_concerns.rb&quot; would reside in app/concerns&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;InvoiceItemConcerns&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AssociationExtensions&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;proxy_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&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;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Invoice&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;InvoiceItem&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;invoice_id&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:extend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;InvoiceItemConcerns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;AssociationExtensions&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PackingSlip&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;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:shipments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;InvoiceItem&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;packing_slip_id&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:extend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;InvoiceItemConcerns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;AssociationExtensions&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InvoiceItem&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;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoice&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Some complex stuff&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;c1&quot;&gt;# Would yeild code like:&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@invoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@packing_slip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shipments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;total&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Wed, 26 Mar 2008 00:00:00 -0400</pubDate>
        <link>/2008/03/26/don-t-be-a-plinko-programmer/</link>
        <guid isPermaLink="true">/2008/03/26/don-t-be-a-plinko-programmer/</guid>
      </item>
    
      <item>
        <title>Metaskills Net Reborn On Mephisto_redirect</title>
        <description></description>
        <pubDate>Sat, 22 Mar 2008 00:00:00 -0400</pubDate>
        <link>/2008/3/22/metaskills-net-reborn-on-mephisto</link>
        <guid isPermaLink="true">/2008/3/22/metaskills-net-reborn-on-mephisto</guid>
      </item>
    
      <item>
        <title>MetaSkills.net Reborn on Mephisto</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/drax.png&quot; alt=&quot;Drax&quot; class=&quot;floatr ml20&quot; /&gt; Well after a year of neglect, the MetaSkills.net blog has been &lt;a href=&quot;/2008/03/22/metaskills-net-reborn-on-mephisto/&quot;&gt;reborn on Mephisto&lt;/a&gt;. Previously I was using Drupal and it finally got to a point where I was so deep into ruby that I did not even have the gumption to open up a PHP session to publish anything. The sad part is that I told myself that this PHP disdain would help me get off my butt and move to Mephisto. You know, eat my own dog food â€“ obviously procrastination won out â€“ but not forever. For the past week I worked hard to get the Meta theme for Drupal converted to Mephisto. You can use this theme yourself if you want, the source is available on &lt;a href=&quot;http://github.com/metaskills/metatheme/tree/master&quot;&gt;my github&lt;/a&gt; and I am making updates often. Heck... feel free to fork the project and make some changes or let me know if you want me to incorporate them into mine.&lt;/p&gt;

&lt;p&gt;Here are a few things that I liked about rewriting the Meta theme for Mephisto. First, unlike Drupal, the administration of your Mephisto blog is not inline, but all tucked away in a private admin section. When you make a theme in Drupal, you are burdened to to the task of coding all the admin CSS for the inline admin features. The Meta theme had over 500 lines of CSS just for the Drupal administration. That is all gone and I love keeping theme code focused on doing nothing but presenting the &quot;user&quot; experience.&lt;/p&gt;

&lt;p&gt;Also, when I first wrote the Meta theme I was just a JavaScript beginner. Nowadays I am pretty good at it and have moved away from the simple script like functions that pass arguments around into a full OO style that spawns from smart classes and a persistent state. The Meta theme is now 100% on Prototype and all the interactive features are tightly knit into the MetaTools, MetaSearch, and MetaContent classes. Take a look at the meta.js source if you want. Lastly, if you are on an old Drupal blog looking to get over to Mephisto, maybe this migration script will help.&lt;/p&gt;

&lt;h2&gt;Migration from Drupal to Mephisto&lt;/h2&gt;

&lt;p&gt;This script is what I used in the rails console to populate data from my old Drupal 4.7 blog to Mephisto. This code is untested on the schema of higher versions of Drupal.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# My Drupal 4.7 to Mephisto Script&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ----------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Things I did before&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   * Delete all rows from drupal node table where type != &#39;blog&#39;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   * Remove the type column from the drupal node table&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Things I did afterward&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   * Found all comments in the Mephisto contents table that were&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     from me and added user_id 1 to them.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Uncomment these if you are debugging the script and want to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# start off on a clean mephisto install&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ----------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Article.find(:all).each(&amp;amp;:destroy)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# CachedPage.delete_all&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# AssignedSection.delete_all&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Tagging.delete_all&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Tag.delete_all&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@mysite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://www.metaskills.net/&quot;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@home&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_by_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Home&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DrupalArticle&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;establish_connection&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:drupal&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:node&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:nid&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;DrupalComment&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;nid&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_one&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;DrupalArticleVerson&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;nid&#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;created_at&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&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;ss&quot;&gt;:created&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DrupalArticleVerson&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;establish_connection&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:drupal&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:node_revisions&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:vid&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DrupalComment&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;establish_connection&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:drupal&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_table_name&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:comments&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_primary_key&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:cid&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;DrupalArticle&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foreign_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;nid&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;DrupalArticle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Creating the article&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;site_id&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;created_at&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;created_at&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;published_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;created_at&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;updated_at&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;excerpt&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;teaser&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;updater_id&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user_id&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sections&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@home&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Creating comments for this article&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;da&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;site_id&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;created_at&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;published_at&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;updated_at&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;author&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;author_url&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;homepage&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;author_email&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mail&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;author_ip&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hostname&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user_agent&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/523.12.2 (KHTML, like Gecko) Version/3.0.4 Safari/523.12.2&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;referrer&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@mysite&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;approved&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;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;subject&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;comment&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save!&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sat, 22 Mar 2008 00:00:00 -0400</pubDate>
        <link>/2008/03/22/metaskills-net-reborn-on-mephisto/</link>
        <guid isPermaLink="true">/2008/03/22/metaskills-net-reborn-on-mephisto/</guid>
      </item>
    
      <item>
        <title>Rake Task To Read And Write The Activerecord Schema Version Table_redirect</title>
        <description></description>
        <pubDate>Wed, 31 Jan 2007 00:00:00 -0500</pubDate>
        <link>/2007/1/31/rake-task-to-read-and-write-the-activerecord-schema-version-table</link>
        <guid isPermaLink="true">/2007/1/31/rake-task-to-read-and-write-the-activerecord-schema-version-table</guid>
      </item>
    
      <item>
        <title>Rake task to read and write the ActiveRecord schema version table.</title>
        <description>&lt;p&gt;
  After attending Rails Edge in Reston, Virginia I decided to move some common tasks from my &lt;code&gt;~/.irbrc&lt;/code&gt; file and put them into Rake. I thought I would share a task that reads and writes the ActiveRecord schema table. Sometimes in migrations this is either good to know or manually change. Simply copy this in a foo.task file in your project/lib/tasks directory and use &lt;code&gt;rake -T&lt;/code&gt; to see the description and usage. I have placed these tasks in the db:version namespace.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:db&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Read the current version of the database.&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39; database version is: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&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;Migrator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current_version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Manually set the schema version to a specific target version with VERSION=x&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;VERSION&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;UPDATE &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&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;Migrator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;schema_info_table_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; SET version = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;VERSION&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SUCCESS: The &#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39; database version is now: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&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;Migrator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current_version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;FAILED: The &#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&#39; database version is still: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&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;Migrator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current_version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;You must specify a VERSION=n argument to this command. Use rake db:version:read to get the current version.&#39;&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;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Wed, 31 Jan 2007 00:00:00 -0500</pubDate>
        <link>/2007/01/31/rake-task-to-read-and-write-the-activerecord-schema-version-table/</link>
        <guid isPermaLink="true">/2007/01/31/rake-task-to-read-and-write-the-activerecord-schema-version-table/</guid>
      </item>
    
      <item>
        <title>Web Service Woes</title>
        <description>&lt;p&gt;
  Only now do I really get this image from &lt;a href=&quot;http://www.loudthinking.com/arc/000585.html&quot;&gt;DHH&#39;s blog&lt;/a&gt;. I am really beginning to despise SOAP for some reason, but I guess I will &quot;get it&quot; as I learn more about it -- as it seems to be the only way to do business with the big players out there. For a glimpse of some of my hell, check out this &lt;a href=&quot;http://www.brendonwilson.com/blog/2006/04/02/ruby-soap4r-wsdl-hell/&quot;&gt;Ruby + SOAP4R + WSDL Hell&lt;/a&gt; article.
&lt;/p&gt;

&lt;p&gt;
  The bad news aside, I was really happy to find someuseful tools today from Todd Ditchendorf Scandalous Software site. The list is pretty extensive so go check it out. Not on the list that I was happy to see were:
&lt;/p&gt;

&lt;p&gt;
  Check XML and XHTML documents for Well-Formedness and Validity while editing them in TextMate with support for DTD, W3C XML Schema, RELAX NG, Schematron and XInclude.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;a href=&quot;http://www.ditchnet.org/texmlmate/&quot; class=&quot;nobor&quot;&gt;
    &lt;img src=&quot;/assets/texmlmate.jpg&quot; alt=&quot;TextMate XML Editor&quot; class=&quot;shadow&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;
  SOAP Client is a free Cocoa-based developer tool for Mac OS X Tiger that allows you access and debug WSDL &amp; SOAP-based Web Services from the comfort of your desktop.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;a href=&quot;http://ditchnet.org/soapclient/&quot; class=&quot;nobor&quot;&gt;
    &lt;img src=&quot;/assets/soap_client.png&quot; alt=&quot;Free Cocoa SOAP Client&quot; class=&quot;shadow&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 29 Dec 2006 00:00:00 -0500</pubDate>
        <link>/2006/12/29/web-service-woes/</link>
        <guid isPermaLink="true">/2006/12/29/web-service-woes/</guid>
      </item>
    
      <item>
        <title>HomeMarks, My First Ruby On Rails Pet Project</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: HomeMarks is no longer an open source project available to download.
&lt;/aside&gt;

&lt;p&gt;&lt;img src=&quot;/assets/homemarks.png&quot; alt=&quot;HomeMarks, Simple Project-Based Bookmarks&quot; class=&quot;floatl mr20&quot; /&gt; I&#39;ve heard that the best web applications are ones that usually start as a simple tool that meets the needs of its creator, in this case, myself. I have always been close to Web Developers that code their own HTML start pages with links to the projects they are working on. So when the time came for me to really get serious with my programing career using &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;RAILS&lt;/a&gt;, this was the first app that I thought about building. From the site&#39;s copy...&lt;/p&gt;

&lt;p&gt;HomeMarks is a unique application allowing everyone from novice to elite the ability to create their own bookmark start page using easy drag and drop methods for sorting Columns, Boxes and Bookmarks. Our custom bookmarklet tool allows you to add links to your HomeMarks start page while surfing and/or researching online. If you&#39;re a bookmark junkie with literally hundreds of saved links to your favorite Internet haunts, HomeMarks is not for you. However, if youâ€™re looking for a clean, simple homepage to organize your most recent or relevant links in an environment tailored to your needs and interests, &lt;a href=&quot;http://www.homemarks.com/&quot;&gt;give HomeMarks a try&lt;/a&gt;. After all, HomeMarks is where the heart is.&lt;/p&gt;

&lt;p&gt;So it is not like &lt;a href=&quot;http://www.techcrunch.com/2006/01/25/yes-this-weeks-ajax-homepage/&quot;&gt;the world needs another AJAX homepage&lt;/a&gt;, there are plenty out there. My problem is that they seem to go to far and build to much into them, Netvibes is a great &quot;poor&quot; example. I do not want XML Feeds, Images, News Headlines, or anything else in my start page. I just want links and only about 100 or so at maximum. For me bookmarks are very transitory objects. They need to be direct links to the things that I am working on, or referencing at that exact time. Once they are not, they get throw away and I can almost certainly find them in the 1st page of a Google result if I really needed to. So this is what &lt;a href=&quot;http://www.homemarks.com/&quot;&gt;HomeMarks&lt;/a&gt; is for me, simple software, using &lt;a href=&quot;http://gettingreal.37signals.com/ch02_Build_Less.php&quot;&gt;build less principals&lt;/a&gt;. If you choose to use it, I hope you enjoy using it. Note, only for Firefox or Safari/WebKit.&lt;/p&gt;
</description>
        <pubDate>Thu, 21 Dec 2006 00:00:00 -0500</pubDate>
        <link>/2006/12/21/homemarks-my-first-ruby-on-rails-pet-project/</link>
        <guid isPermaLink="true">/2006/12/21/homemarks-my-first-ruby-on-rails-pet-project/</guid>
      </item>
    
      <item>
        <title>Happy Halloween from TextMate</title>
        <description>&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/spooky_textmate.png&quot; alt=&quot;Happy Halloween from TextMate&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;
  Upon downloaded the Cutting-Edge version (1.5.4 r1311) of TextMate yesterday, I was happy to find a halloween surprise. How cool can one program be - thanks Allan! Especially to some of your latest work on &lt;a href=&quot;http://macromates.com/blog/archives/2006/10/28/new-dialog-system-for-commands/&quot;&gt;extending the dialog&lt;/a&gt; features for bundle developers.
&lt;/p&gt;
</description>
        <pubDate>Tue, 31 Oct 2006 00:00:00 -0500</pubDate>
        <link>/2006/10/31/happy-halloween-from-textmate/</link>
        <guid isPermaLink="true">/2006/10/31/happy-halloween-from-textmate/</guid>
      </item>
    
      <item>
        <title>Custom Rake Task To Unload Fixtures_redirect</title>
        <description></description>
        <pubDate>Mon, 02 Oct 2006 00:00:00 -0400</pubDate>
        <link>/2006/10/2/custom-rake-task-to-unload-fixtures</link>
        <guid isPermaLink="true">/2006/10/2/custom-rake-task-to-unload-fixtures</guid>
      </item>
    
      <item>
        <title>Custom Rake Task To Unload Fixtures</title>
        <description>&lt;p&gt;
  I made a revised version of a rake task that I have used quite often, for unloading existing DB tables into fixture data and thought I would share. This rake task is the in correct name space and adds a &quot;rake db:fixtures:unload&quot; command to your rails project when you put this in &quot;lib/tasks/foo.rake&quot;. It can take an optional TABLES variable or if none is present the whole array of DB tables are converted. I find this rake task helpful when dealing with LARGE databases.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:db&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:fixtures&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Create YAML test fixtures from data in specifed tables. Set table names by TABLES=foos,bars,etc&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:unload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SELECT * FROM %s&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tables&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;s2&quot;&gt;&quot;schema_info&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;establish_connection&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TABLES&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;TABLES&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/,/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;000&quot;&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/test/fixtures/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.yml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;w&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_name&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;nf&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&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;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;succ!&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&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;record&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_yaml&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;k&quot;&gt;end&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Mon, 02 Oct 2006 00:00:00 -0400</pubDate>
        <link>/2006/10/02/custom-rake-task-to-unload-fixtures/</link>
        <guid isPermaLink="true">/2006/10/02/custom-rake-task-to-unload-fixtures/</guid>
      </item>
    
      <item>
        <title>Flying Light Configuring Drupal And Lighttpd_redirect</title>
        <description></description>
        <pubDate>Fri, 30 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/6/30/flying-light-configuring-drupal-and-lighttpd</link>
        <guid isPermaLink="true">/2006/6/30/flying-light-configuring-drupal-and-lighttpd</guid>
      </item>
    
      <item>
        <title>Flying Light - Configuring Drupal and LightTPD</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/light_logo.png&quot; alt=&quot;LightTPD Logo&quot; width=&quot;249&quot; height=&quot;239&quot; class=&quot;floatr ml20&quot; /&gt; So the WebSvr mini here at my home-based NOC (named ActionMoniker.com) is now running LightTPD as the web server. The benefits are that I can now run my PHP-based Drupal blog in FastCGI mode while also allowing virtual hosting under the same server/IP for my RAILS projects. The end result has turned out quite well and I am actually loving the speed improvements and the &lt;a href=&quot;http://lighttpd.net/documentation/&quot;&gt;simple configuration&lt;/a&gt; for LightTPD, which has a more natural feeling for me when it comes to configuring a web server.
&lt;/p&gt;

&lt;p&gt;
  Below is a code snippet of my current configuration file for this Drupal host.  Please be aware, that this is not a full LightTPD configuration file which would likely have further restrictions on how your web server operates and secures itself. That said, this snippet incorporates the following configurations which are mostly necessaries for any Drupal blog using the Drupal supplied .htaccess file for Apache.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A vhost default so that both the www and the root domain point to the same directory.&lt;/li&gt;
  &lt;li&gt;URL access rules that deny access  to common Drupal install and app files.&lt;/li&gt;
  &lt;li&gt;URL rewrite rules for my &lt;a href=&quot;http://haveamint.com/&quot;&gt;mint statistics,&lt;/a&gt; multi site setup in a &lt;code&gt;/meta-theme-for-drupal&lt;/code&gt; directory which, and the standard drupal rewrites for clean ULRs and a few system functions. It is important that these rewrites be in the correct order with the root drupal install being last.&lt;/li&gt;
  &lt;li&gt;URL expires directives that help browser caching for all page assets that are core Drupal and found in the Meta Theme. &lt;/li&gt;
  &lt;li&gt;A compress cache directory, server error log, and access log using the web server root variable set at the tops of the vhost config. I like that LightTPD can set variables.      &lt;/li&gt;
  &lt;li&gt;Finally a LightTPD declaration for spawning FastCGI process for PHP.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;simple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/Library/WebServer/hosts/&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;simple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;default&quot;&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;host&quot;&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;s&quot;&gt;&quot;^(metaskills.net)|(www.metaskills.net)$&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;simple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;metaskills.net&quot;&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;access&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deny&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;s&quot;&gt;&quot;.engine&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.inc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.install&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.sh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.sql&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.pgsql&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;.theme&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.tpl.php&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.xtmpl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.code-style.pl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.Repository&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.Root&quot;&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;rewrite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;once&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;cp&quot;&gt;# hard-coded rewrites so the drupal catch-alls do not get them.
&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;&quot;^/mint/$&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/mint/index.php&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/mint/\?(.*)&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/mint/index.php?$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;cp&quot;&gt;# drupal rules for (meta-theme-for-durpal) multi-site, these MUST BE FIRST.
&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;&quot;^/meta-theme-for-drupal/system/test/(.*)$&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/meta-theme-for-drupal/index.php?q=system/test/$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/meta-theme-for-drupal/search/node/(.*)$&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/meta-theme-for-drupal/index.php?q=search/node/$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/meta-theme-for-drupal/([^.?]*)\?(.*)$&quot;&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/meta-theme-for-drupal/index.php?q=$1&amp;amp;$2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/meta-theme-for-drupal/([^.?]*)$&quot;&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/meta-theme-for-drupal/index.php?q=$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/meta-theme-for-drupal$&quot;&lt;/span&gt;                   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/meta-theme-for-drupal/index.php&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;cp&quot;&gt;# drupal rules for default site behavior.
&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;&quot;^/system/test/(.*)$&quot;&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/index.php?q=system/test/$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/search/node/(.*)$&quot;&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/index.php?q=search/node/$1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/([^.?]*)\?(.*)$&quot;&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/index.php?q=$1&amp;amp;$2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;s&quot;&gt;&quot;^/([^.?]*)$&quot;&lt;/span&gt;                &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/index.php?q=$1&quot;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;expire&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/favicon.ico&quot;&lt;/span&gt;              &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/files/&quot;&lt;/span&gt;                   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/misc/&quot;&lt;/span&gt;                    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/css/&quot;&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/images/&quot;&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/js/&quot;&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/meta-black/&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/meta-grey/&quot;&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/meta-paper/&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;/themes/meta/meta-pink/&quot;&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;access 3 days&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;compress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;            &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tmp/cache_metaskills/&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errorlog&lt;/span&gt;               &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;logs/metaskills.error.log&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;accesslog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;            &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;logs/metaskills.access.log&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fastcgi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&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;s&quot;&gt;&quot;.php&quot;&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;s&quot;&gt;&quot;localhost&quot;&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;s&quot;&gt;&quot;socket&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/tmp/php-fastcgi.socket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;s&quot;&gt;&quot;bin-path&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/opt/local/bin/php-fcgi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;s&quot;&gt;&quot;max-procs&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;s&quot;&gt;&quot;bin-environment&quot;&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;s&quot;&gt;&quot;PHP_FCGI_CHILDREN&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                          &lt;span class=&quot;s&quot;&gt;&quot;PHP_FCGI_MAX_REQUESTS&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&lt;/span&gt;
                                        &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                        &lt;span class=&quot;s&quot;&gt;&quot;bin-copy-environment&quot;&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;s&quot;&gt;&quot;PATH&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SHELL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;USER&quot;&lt;/span&gt;
                                        &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                        &lt;span class=&quot;s&quot;&gt;&quot;broken-scriptfilename&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;enable&quot;&lt;/span&gt;
                                      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Obviously this configuration is dependant on php-fcgi being installed and If you followed along in my past &lt;a href=&quot;/2006/05/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x/&quot;&gt;Soup to Nuts Recipe for Ruby on RAILS on OS X&lt;/a&gt;, here is a few crib notes I kept on how to recompile a few things so that you can have your whole installation of LightTPD, Ruby, PHP, and MySQL all running from the Darwin Ports /opt directory.
&lt;/p&gt;

&lt;h2&gt;Reinstall LightTPD with SSL&lt;/h2&gt;

&lt;p&gt;If you do not plan on using SSL with Lighty, this step is optional.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port uninstall lighttpd
$ sudo port install lighttpd +ssl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MySQL 5 Installation in Darwin Ports &lt;/h2&gt;

&lt;p&gt;
  This part is definitely not for the week. If you are total noobie, stick with the &lt;a href=&quot;http://dev.mysql.com/downloads/&quot;&gt;compiled packages&lt;/a&gt; offered by MySQL AB because doing this installation may break some of the tools you might be familiar with. Most can be fixed, but you will definitely loose your fancy start/stop button in the System Preferences.
&lt;/p&gt;

&lt;p&gt;
  I installed MySQL 5 in this manner so that I could have PHP from Darwin Ports totally hooked into the MySQL installation by DP as well. I do not suggest you do this if you are new to this sort of stuff, again, these are just some quick notes I made. OK...
&lt;/p&gt;

&lt;p&gt;
  First, add &lt;code&gt;/opt/local/lib/mysql5/bin&lt;/code&gt; to the $PATH environment variable in your &lt;code&gt;.bash_profile&lt;/code&gt;. When you do this you are linking to the REAL path for the MySQL binaries and not the Darwin Ports suffix5 sym links that it creates in&lt;code&gt;/opt/local/bin&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
  Now issue these command. This will install mysql5 with Darwin Ports and the server startup scripts. The second command will load that startup script into your &lt;code&gt;launchd&lt;/code&gt; list. and the third will install the default MySQL tables for permissions, etc.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install mysql5 +server
$ sudo launchctl load -w /Library/LaunchDaemons/org.darwinports.mysql5.plist
$ sudo -u mysql /opt/local/lib/mysql5/bin/mysql_install_db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  So that you do not have to do the following steps, restart you computer which should let MySQL use the startup script you enabled in the step above. In this way you can bypass these first two commands below. The other two commands are some notes of mine on the usage of the wrapper LaunchDaemon installed by Darwin Ports for MySQL. For easy reading, check out the support pages for &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/unix-post-installation.html&quot;&gt;UNIX Post-Installation Procedures&lt;/a&gt; offered on the MySQL Reference Manual. Remember, I am pretty sure that you do not have to do these steps if you just restart your computer.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo -u mysql /opt/local/lib/mysql5/bin/mysqld_safe &amp;amp;
$ sudo /opt/local/lib/mysql5/bin/mysqladmin shutdown
$ sudo -u mysql /opt/local/etc/LaunchDaemons/org.darwinports.mysql5/mysql5.wrapper start
$ sudo -u mysql /opt/local/etc/LaunchDaemons/org.darwinports.mysql5/mysql5.wrapper stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here we are going to create the &lt;code&gt;my.cnf&lt;/code&gt; file in one of the places this installation of MySQL likes to find it from the example files installed by MySQL. In this example I used the medium example file, but if you are expecting more traffic and have more RAM, use the my-huge.cnf file instead. Next we are creating a sym link to the my.cnf in the standard place the normal MySQL AB binaries install them on OS X, in the &lt;code&gt;etc&lt;/code&gt; directory. In this way you can still use &lt;a href=&quot;http://www.mysql.com/products/tools/administrator/&quot;&gt;MySQL Administrator&lt;/a&gt; buy be aware that I had to use 127.0.0.1 instead of localhost. Not sure why.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo -u mysql cp /opt/local/share/mysql5/mysql/my-medium.cnf /opt/local/var/db/mysql5/my.cnf
$ sudo ln -s /opt/local/var/db/mysql5/my.cnf /etc/my.cnf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now to fix the MySQL gem that was installed the first time around. This install type uses the &lt;code&gt;mysql-config&lt;/code&gt; as described in &lt;a href=&quot;http://tmtm.org/en/mysql/ruby/&quot;&gt;the fine manual&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo gem uninstall mysql
$ sudo gem install mysql -- --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Installing PHP5 using Darwin Ports MySQL &lt;/h2&gt;

&lt;p&gt;
  Now you are ready to install PHP5 with its FastCGI support and Darwin Ports dependencies on the MySQL previously installed. The second command copies the php.ini installed by DP into the place the Darwin Ports PHP likes to find it.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install php5 +fastcgi +mysql5
$ sudo cp /opt/local/etc/php.ini-recommended /opt/local/etc/php.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now add this line of code to the php.ini file somewhere at the end of the section called &quot;Paths and Directories&quot; that is about mid way down. See also this &lt;a href=&quot;http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP&quot;&gt;web page&lt;/a&gt; for more info on this.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;cgi.fix_pathinfo = 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Fri, 30 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/06/30/flying-light-configuring-drupal-and-lighttpd/</link>
        <guid isPermaLink="true">/2006/06/30/flying-light-configuring-drupal-and-lighttpd/</guid>
      </item>
    
      <item>
        <title>Quake Style Terminal Window On Os X_redirect</title>
        <description></description>
        <pubDate>Tue, 13 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/6/13/quake-style-terminal-window-on-os-x</link>
        <guid isPermaLink="true">/2006/6/13/quake-style-terminal-window-on-os-x</guid>
      </item>
    
      <item>
        <title>Quake Style Terminal Window on OS X</title>
        <description>&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: (May 18th, 2012) The modern replacement for VisorTerminal is called TotalTerminal and cand be found &lt;a href=&quot;http://totalterminal.binaryage.com/&quot;&gt;on the binaryage site&lt;/a&gt;
&lt;/aside&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/visor_screenshot.jpg&quot; alt=&quot;Visor Screenshot&quot; width=&quot;550&quot; height=&quot;413&quot; class=&quot;floatr ml20 shadow&quot; /&gt; Well this is far beyond cool but highly functional, a Quake like terminal implementation of Terminal.app that is a HotKey away from within any application. A friend turned me on to this after it showed up on the &lt;a href=&quot;http://arstechnica.com/journals/apple.ars/2006/6/12/4291&quot;&gt;Monday morning Apple links&lt;/a&gt; post from arstechnica.com. Although I have never thought of this idea, it seems to have been a popular request for quite some time and after a &lt;a href=&quot;http://episteme.arstechnica.com/eve/forums/a/tpc/f/8300945231/m/332004739731&quot;&gt;public request&lt;/a&gt;, the author of &lt;a href=&quot;http://quicksilver.blacktree.com/&quot;&gt;QuickSilver&lt;/a&gt; stepped up to the challenge and coded this little goodie using the application enhancer method called &lt;a href=&quot;http://www.culater.net/software/SIMBL/SIMBL.php&quot;&gt;SIMBL&lt;/a&gt; which was created by Mike Solomon, the creator of the PithHelmet plugin for Safari.
&lt;/p&gt;

&lt;p&gt;So if you are itching to try this out here is what you do.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.culater.net/dl/files/SIMBL-0.8.1.tbz&quot;&gt;Download and Install SIMBL&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://download.blacktree.com/Visor.zip&quot;&gt;Download Visor&lt;/a&gt; and place it in the &lt;code&gt;/Library/Application Support/SIMBL/Plugins&lt;/code&gt; folder.&lt;/li&gt;
  &lt;li&gt;Logout and back into your account (maybe restart) &lt;/li&gt;
  &lt;li&gt;Launch Terminal.app (close it if you want, also see my AppleScript below)  &lt;/li&gt;
  &lt;li&gt;Set your Visor HotKey preferences in the new menu. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Now, when you launch any other program and hit your HotKey (mine is Command ~) a terminal application will slide down from the top of your screen just like in Quake. The only down side is that if you are used to your iTerm display, you will have to set the preferences of Terminal.app to mimic that. I set mine with a black background, ProFont 10px, and 80% visibility.
&lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;
  &lt;img src=&quot;/assets/termina_applescript.gif&quot; alt=&quot;Visor AppleScript&quot; width=&quot;370&quot; height=&quot;363&quot; class=&quot;floatl mr20 shadow&quot; /&gt;  Lastly, since you do have to have the Terminal application running for this to work and I was too lazy to open this al the time, I simple created a small AppleScript which can be compiled into an application and placed into your Login Item in the System Preferences. Here is a screenshot of the code. Notice that it tells window 2 to close. This is because once you have SIMBL and Visor installed, an invisible window opens for Terminal that you cannot see. So the window that you can see (window 2) is closed by AppleScript.
&lt;/p&gt;
</description>
        <pubDate>Tue, 13 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/06/13/quake-style-terminal-window-on-os-x/</link>
        <guid isPermaLink="true">/2006/06/13/quake-style-terminal-window-on-os-x/</guid>
      </item>
    
      <item>
        <title>Back In Black_redirect</title>
        <description></description>
        <pubDate>Tue, 06 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/6/6/back-in-black</link>
        <guid isPermaLink="true">/2006/6/6/back-in-black</guid>
      </item>
    
      <item>
        <title>Back in Black</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/macbook-front.png&quot; alt=&quot;Black MacBook Front&quot; width=&quot;500&quot; height=&quot;294&quot; class=&quot;floatr ml20&quot; /&gt; I have not been a black Mac owner since I got rid of my &lt;a href=&quot;http://en.wikipedia.org/wiki/Powerbook#PowerBook_G3&quot;&gt;Lombard&lt;/a&gt; (aka the Bronze Keyboard) way back in 2001. Before that, I was the proud owner of a &lt;a href=&quot;http://en.wikipedia.org/wiki/PowerBook_3400&quot;&gt;3400c&lt;/a&gt; which was also black and one of the first PowerPC laptops offered from Apple. That PowerBook cost me close to $4,000 if memory serves and I swear some of the debt is still hanging around today! So after being with Apple for so long I have very glad that good Mac hardware has gotten cheaper over the past 4 years and to see the return of a the darker colored books. Its about time too and the price is just right.
&lt;/p&gt;

&lt;p&gt;
  So this past Sunday I drove from Portsmouth all the way to the &lt;a href=&quot;http://www.apple.com/retail/shortpump/&quot;&gt;Apple Store at Short Pump in Richmond&lt;/a&gt; and purchased myself a brand new MacBook, the black one of course. The 12&amp;quot; G4 I have been working on lately was showing its age. Start ups were really slow, database queries on local MySQL development kept grinding to a halt and I&#39;m pretty sure that power management unit was next to go.
&lt;/p&gt;

&lt;p&gt;
  Now that it is two days later and I have spent the past two days reinstalling RAILS using my own &lt;a href=&quot;/2006/05/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x/&quot;&gt;soup to nuts&lt;/a&gt; recipe and putting back every piece of software on this new machine, I thought I would share a few of my experiences to those considering the upgrade to an Intel Mac and perhaps their own MacBook.
&lt;/p&gt;

&lt;h2&gt;Migration&lt;/h2&gt;

&lt;p&gt;
  Do not use the migration assistant. I repeat, DO NOT USE THE MIGRATION ASSISTANT. I can not tell you why but doing such will kill the speed of your new Mac. When I did this and even after I waited for the spotlight index to rebuild itself, the computer was still way slower than it should have been. I don&#39;t blame Apple for this, it would probably be impossible for the to weed out every prefs and configuration file that might conflict and I have always been a huge advocate of doing it the manual way for any drastic hardware change, but I was curious. If anyone has any insight on why the Migration Assistant would botch so bad, I would love to hear it.
&lt;/p&gt;

&lt;h2&gt;More RAM&lt;/h2&gt;

&lt;p&gt;
  Simply but, do it! There is no way to run your new Mac on only 512MB. It should be enough but, shortly after the system boots, it slows down real fast because the first few apps that need Rosetta will likely kill all the remaining RAM you have left. I highly suggest maxing the MacBook to 2 Gigabytes by ordering from &lt;a href=&quot;http://www.thechipmerchant.com/go.asp?cc=MACBOOKPROMEM&amp;amp;agent=&quot;&gt;TheChipMerchant.com&lt;/a&gt; which sell these for only $96 a stick and they have a lifetime warranty.
&lt;/p&gt;

&lt;p&gt;
  The MacBook&#39;s memory slots are &lt;a href=&quot;http://www.ifixit.com/Guide/86.3.2.html&quot;&gt;easily accessible&lt;/a&gt;, but pulling those leavers scared the hell out of me. I swear I thought they were going to break.
&lt;/p&gt;

&lt;h2&gt;The Screen&lt;/h2&gt;

&lt;p&gt;
  I cannot say anything bad about it. I love it! The size of the MacBook screen is perfect for me. I need a small computer for portability and this 13&amp;quot; wide screen is the perfect blend between compact and working real estate. This screen has to be the brightest I&#39;ve seen and in no way does the glossy cover bother me at all.
&lt;/p&gt;
</description>
        <pubDate>Tue, 06 Jun 2006 00:00:00 -0400</pubDate>
        <link>/2006/06/06/back-in-black/</link>
        <guid isPermaLink="true">/2006/06/06/back-in-black/</guid>
      </item>
    
      <item>
        <title>My Own Soup To Nuts Recipe For Ruby On Rails On Os X_redirect</title>
        <description></description>
        <pubDate>Mon, 29 May 2006 00:00:00 -0400</pubDate>
        <link>/2006/5/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x</link>
        <guid isPermaLink="true">/2006/5/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x</guid>
      </item>
    
      <item>
        <title>My Own Soup to Nuts Recipe for Ruby on Rails on OS X</title>
        <description>&lt;p&gt;
  &lt;a href=&quot;http://www.catb.org/jargon/html/T/TMTOWTDI.html&quot;&gt;Tim Toady&lt;/a&gt; tells us that (There Is More Than One Way To Do It) and I am sure this is not the first and not likely the last blog post you will ever see that tells you the best way to install RAILS on OS X. Some people would just rather than go the &lt;a href=&quot;http://locomotive.raaum.org/&quot;&gt;simple path&lt;/a&gt; but I implore you, do it this way. Gaining the experience of compiling your own software will help you down the road when it comes time for doing more advanced things, especially deploying your RAILS app. When you are done, you will have a rock solid deployment environment for RAILS that will include:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ruby  and RAILS &lt;/li&gt;
  &lt;li&gt;MySQL Community Edition&lt;/li&gt;
  &lt;li&gt;FastCGI &amp;amp; LightPPD&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Step 1 - Install Apple Developer Tools&lt;/h2&gt;

&lt;p&gt;
  The Apple Developer Tools are needed to install Darwin Ports which opens up the door for a bunch of other goodies we will need.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Go to &lt;a href=&quot;http://connect.apple.com&quot;&gt;Apple&#39;s Developer Connection&lt;/a&gt; site.&lt;/li&gt;
  &lt;li&gt;Click on &amp;quot;Join Now&amp;quot;, create an account and log into the site.&lt;/li&gt;
  &lt;li&gt;Go to the &amp;quot;Downloads&amp;quot; section.&lt;/li&gt;
  &lt;li&gt;In the right box, click on &amp;quot;Developer Tools&amp;quot;&lt;/li&gt;
  &lt;li&gt;Scroll  to the &amp;quot;Xcode Tools 2.3&amp;quot; section and download the large disk image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  This is obviously going to take awhile, if you want to skip ahead and start on some of the following steps, by all means do so. Once you are done downloading the Xcode Tools and have the disk image mounted, install the package named &amp;quot;XcodeTools.mpkg&amp;quot;. You do not have to worry about the others, especially the WebObjects package :)
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/machd_with-developer-tools.png&quot; alt=&quot;XCode Developer Tools Folder&quot; width=&quot;421&quot; height=&quot;279&quot; class=&quot;floatr ml20 shadow&quot; /&gt; Once you are finished with the install of the Developer Tools, you will have a new folder at the root of your hard drive called &amp;quot;Developer&amp;quot;, pictured below on an OS X Server install. For the most part you can largely ignore this new folder.
&lt;/p&gt;

&lt;h2&gt;Step 2 - Install MySQL &amp;amp; Setup Your First DB&lt;/h2&gt;

&lt;p&gt;
  The Ruby on Rails framework comes by default with the MySQL adapters for ActiveRecord to talk to MySQL servers. I highly recommend you start development with MySQL, its a good database and if you have not read the &lt;a href=&quot;http://developer.apple.com/business/macmarket/mysql.html&quot;&gt;recent news regarding MySQL AB and Apple working more closely&lt;/a&gt; then I will tell you now that it seems like good time to revisit MySQL as your primary database choice. If you believe the press, MySQL AB seems more committed than ever to deploy its development tools to the Mac platform. Many would say that these are not really needed when you use RoR&#39;s database migrations and a nice white board.
&lt;/p&gt;

&lt;p&gt;
  I have previously used their &lt;a href=&quot;http://www.mysql.com/products/tools/administrator/&quot;&gt;Administrator&lt;/a&gt; and &lt;a href=&quot;http://www.mysql.com/products/tools/query-browser/&quot;&gt;Query Browser&lt;/a&gt; only to find them full of bugs and crashing often. I&#39;m now happy to say that most of these bugs have disappeared and I can now use these applications with the current versions of MySQL Community Edition without much ado. I was very happy to hear that MySQL AB has a new tool in the line up (currently in beta) called &lt;a href=&quot;http://dev.mysql.com/downloads/workbench/1.0.html&quot;&gt;Workbench&lt;/a&gt;. This is their first Entity Relationship Modeling application that brings in many of the features available for editing tables from their Administrator application with the GUI development of ER diagramming. ER tools have been very sparse on the Mac and I am very happy to see this one coming. Either way, do your self a favor and download those three tools, at the least, we will need the Administrator tool to setup some database accounts on your new MySQL installation. You may also find Query Browser helpful if you find yourself debugging ActiveRecord methods. Here is our install and setup process.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Go to the &lt;a href=&quot;http://dev.mysql.com/downloads/mysql/5.0.html&quot;&gt;MySQL 5 Community Edition download page&lt;/a&gt;. &lt;/li&gt;
  &lt;li&gt;Scroll down to the section title &amp;quot;Mac OS X downloads&amp;quot; and pick the &amp;quot;Max&amp;quot; package that best matches your system.&lt;/li&gt;
  &lt;li&gt;Once downloaded, install the MySQL package, the StartupItem package, and the PreferencesPane. The PreferencePane is just a simple switch to turn MySQL on and off.&lt;/li&gt;
  &lt;li&gt;Download and install the &lt;a href=&quot;http://www.mysql.com/products/tools/administrator/&quot;&gt;MySQL Administrator&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Download and install the &lt;a href=&quot;http://www.mysql.com/products/tools/query-browser/&quot;&gt;Query Browser&lt;/a&gt;. (optional) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  That&#39;s it, MySQL is installed and ready once you restart your system. If you are still downloading the Xcode Tools, you will have to wait to do the following steps which will secure your MySQL installation.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/mysql-administrator-login.png&quot; alt=&quot;MySQL Administrator Login Screen&quot; width=&quot;322&quot; height=&quot;221&quot; class=&quot;floatl mr20 shadow&quot; /&gt; So after a fresh restart from installing MySQL, let&#39;s secure your installation by assigning some passwords. To do this launch the MySQL Administrator and log into your MySQL server using the server hostname of &lt;code&gt;localhost&lt;/code&gt; and the username of &lt;code&gt;root&lt;/code&gt;. You do not need a password, it is blank for root@localhost by default, this is what we are going to fix. It is not a big security bug as long as you are the only one on your machine, it is just a good idea to secure this account.
&lt;/p&gt;

&lt;p&gt;
  Click on &amp;quot;Accounts&amp;quot; at the top and delete the account that has no name. You optionally may want to set a password for the root at localhost. From this point on you can optionally create an account specific to any databases you may be using for developing. When creating a user, you have to create a host (typically localhost) at the same time by using that + host icon to the right of the new user icon in the bottom right. Click on &amp;quot;Catalogs&amp;quot; to create a database and then come back to &amp;quot;Accounts&amp;quot;, expand the arrow beside the user you want to have access to this new database, select the host for that user, click on &amp;quot;Schema Privileges&amp;quot;, click on the name of the newly created database schema and then assign the privileges from the available list to the assigned list. Typically I grant all privileges in development environments.
&lt;/p&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/mysql-administrator-accounts.png&quot; alt=&quot;MySQL Administrator Accounts Screen&quot; width=&quot;534&quot; height=&quot;435&quot; class=&quot;floatr ml20 shadow&quot; /&gt; In the next step, installing DarwinPorts, we are going to cover some $PATH additions that will let our system know where it can find MySQL.
&lt;/p&gt;

&lt;h2&gt;Step 3 - Install DarwinPorts &amp;amp; All Needed Packages&lt;/h2&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/darwin-ports.png&quot; alt=&quot;Darwin Ports Logo&quot; width=&quot;128&quot; height=&quot;128&quot; class=&quot;floatl mr20&quot; /&gt;&lt;a href=&quot;http://www.darwinports.com/&quot;&gt;DarwinPorts&lt;/a&gt; is your key to a TON of open source software for your Mac. This can include PHP, Ruby, Apache, and Subversion to smaller utilities like, wget, furl, and pine... the list goes on to over 2,000 ports currently available. It is generally accepted that Mac OS X and Darwin Ports is a good thing, but &lt;a href=&quot;http://objectiveministries.org/creation/propaganda.html&quot;&gt;some disagree&lt;/a&gt;. Meanwhile, using DP for all of your open source software can help you keep installed packages in one easy to understand place, by default in the &lt;code&gt;/opt&lt;/code&gt; directory at the root of your drive. This can save you lots of headaches from the dreaded &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_hell&quot;&gt;dependency hell&lt;/a&gt; that has plagued most of us whom have not used a good package management system. That is not to say that dependencies will never happen, but when the do, knowing where DP places things can help you resolve them quickly. Let&#39;s get to installing our new package management system.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.darwinports.com/&quot;&gt;Download DarwinPorts installer&lt;/a&gt; from their site.&lt;/li&gt;
  &lt;li&gt;Install the package.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  That&#39;s about it, DarwinPorts is installed and ready to use. I do however like to clean things up a little bit. If you have followed my previous article &lt;a href=&quot;/2006/03/19/getting-on-good-terms-with-the-os-x-shell/&quot;&gt;Getting on good terms with the OS X shell&lt;/a&gt; then you already know how to customize your &lt;code&gt;.bash_profile&lt;/code&gt;, so lets fire up TextMate and do just that right now. Although DP does install a &lt;code&gt;.profile&lt;/code&gt; file that will customized your &lt;code&gt;$PATH&lt;/code&gt; environments, I think it&#39;s a good idea that you put this back in your control. If your new to this path stuff, they are basically just a list of directories that lets your computer know where software is installed. Keeping it that simple lets just put these lines anywhere in your &lt;code&gt;.bash_profile&lt;/code&gt;.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# My PATH Environment Variables&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/bin:/opt/local/sbin:/usr/local/mysql/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;MANPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/share/man:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$MANPATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INFOPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/local/share/info:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INFOPATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  You can see by the example we are simply adding other path options before your systems default, denoted by the &lt;code&gt;$PATH&lt;/code&gt;. Using colons is how you separate the list and this is how we have added the MySQL installation into your system&#39;s path environment and if you ever need more, make sure to separate them too by colons and typically try to keep your default &lt;code&gt;$PATH&lt;/code&gt; at the end. One last note, that &lt;code&gt;/opt/local/sbin&lt;/code&gt; is in the code box above so that LightTTPD will be available to RAILS after we get it installed, more info below.
&lt;/p&gt;

&lt;p&gt;
  Now let&#39;s start using DarwinPorts, if you want to take a small course on the generals about how to use DP, I suggest taking a look at &lt;a href=&quot;http://wiki.opendarwin.org/index.php/DarwinPorts:Getting_Started&quot;&gt;Joe Auty&#39;s Getting Started with DarwinPorts&lt;/a&gt;, otherwise, just follow along. Remember that building and installing software from scratch is a CPU intensive task for your computer. It is not unusual for an install to take anywhere from 15 to 30 minutes and maybe longer, so be patient.
&lt;/p&gt;

&lt;p&gt;
  Fire up a terminal app and use this command, it will bring our fresh DP install up to date. If you had your terminal open before you added your path variables, remember to close it and open a new one so that the changes will take affect. All remaining installs will be issued in the Terminal window.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$sudo port -d selfupdate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now let&#39;s install the latest release of Ruby and its dependencies. This will take awhile!
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install ruby
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now install the Ruby Gems package management system.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install rb-rubygems
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Now the FastCGI Development Kit and the Ruby interface to FastCGI. These will be needed when deploying your application into a production mode (or development when using &lt;code&gt;./script/server&lt;/code&gt;) using LightTPD also known as Lighty.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install fcgi
$ sudo port install rb-fcgi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here we will now go ahead and install Lighttpd and its dependencies. The LightTPD executable is located in &lt;code&gt;/opt/local/sbin&lt;/code&gt; and this is why we placed it in our path environment. For future reference the default config file for LightTPD is in &lt;code&gt;/opt/local/etc/lighttpd&lt;/code&gt;. You may want to make friends with that file when you start thinking about deployment. The RAILS team makes it easy when you use &lt;code&gt;./script/server&lt;/code&gt; by loading in a RAILs specific LightTPD config file, so you do not have to think about this in the default development mode.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo port install pcre
$ sudo port install lighttpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Step 4 - Final Installs (RAILs and MySQL Bindings)&lt;/h2&gt;

&lt;p&gt;
  &lt;img src=&quot;/assets/rails.png&quot; alt=&quot;Ruby on Rails&quot; width=&quot;87&quot; height=&quot;112&quot; class=&quot;floatl mr20&quot; /&gt; Now to the fun part we have installed Ruby and Ruby Gems using Darwin Ports in our previous step. Now we get to install RAILS with a two part command, the first one liner will install RAILS with all the dependencies using Ruby Gems. The second command, again using Ruby Gems, we will install the latest MySQL bindings. This should speed things up a bit, you &lt;a href=&quot;http://weblog.rubyonrails.com/articles/2005/10/30/get-10-15-more-performance-with-mysql-rails&quot;&gt;can read more about this here&lt;/a&gt; along with the performance gains it offers. Please note that when you run this second command, you will likely get a prompt for which platform you would like to install on. I selected option 3 which was mysql 2.7 (ruby).
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ sudo gem install rails --include-dependencies
$ sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Just like DarwinPorts, Ruby Gems is a package management system. If you get some time or if you find yourself in a pinch, I find that the &lt;a href=&quot;http://docs.rubygems.org/read/book/2&quot;&gt;command reference here&lt;/a&gt; offers a lot of insight and help into how to use Ruby Gems.
&lt;/p&gt;
</description>
        <pubDate>Mon, 29 May 2006 00:00:00 -0400</pubDate>
        <link>/2006/05/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x/</link>
        <guid isPermaLink="true">/2006/05/29/my-own-soup-to-nuts-recipe-for-ruby-on-rails-on-os-x/</guid>
      </item>
    
      <item>
        <title>Pragmatic Studio Alumni Member_redirect</title>
        <description></description>
        <pubDate>Fri, 19 May 2006 00:00:00 -0400</pubDate>
        <link>/2006/5/19/pragmatic-studio-alumni-member</link>
        <guid isPermaLink="true">/2006/5/19/pragmatic-studio-alumni-member</guid>
      </item>
    
      <item>
        <title>Pragmatic Studio Alumni Member</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/alumni_stamp.png&quot; alt=&quot;The Pragmatic Studio Alumni Member&quot; class=&quot;floatr ml20&quot; /&gt; Well, I just got back this past weekend from the &lt;a href=&quot;http://pragmaticstudio.com/index.html&quot;&gt;Pragmatic Studio&lt;/a&gt; in &lt;a href=&quot;http://www.flickr.com/photos/tags/railsstudioboston/&quot;&gt;Boston&lt;/a&gt; and it was well worth the time and &lt;a href=&quot;http://www.cnn.com/2006/WEATHER/05/17/new.england.flooding.ap/&quot;&gt;effort&lt;/a&gt;. If you have not yet used the RoR framework for web applications, stay tuned to my next post. By next week I will lay out an extensive tutorial on how to install the framework with all the proper goodies on your Mac. So do not wimp out and go for that &lt;a href=&quot;http://locomotive.sourceforge.net/&quot;&gt;easy package&lt;/a&gt; install and dare to impress your friends as we build our own software installs with Darwin Ports.
&lt;/p&gt;

&lt;p&gt;
  Remember, if you are new to RoR, I highly advise that you take the time to browse over to the &lt;a href=&quot;http://pragmaticprogrammer.com/bookshelf/index.html&quot;&gt;Pragmatic Bookshelf&lt;/a&gt; and buy yourself some PDF books. I suggest starting with Chris Pine&#39;s &lt;em&gt;How To Program&lt;/em&gt; and then moving on to the 2nd edition of &lt;em&gt;Agile Web Development with RAILs&lt;/em&gt; mixed with brief dives into the Ruby language with the famous Pickaxe book.
&lt;/p&gt;
</description>
        <pubDate>Fri, 19 May 2006 00:00:00 -0400</pubDate>
        <link>/2006/05/19/pragmatic-studio-alumni-member/</link>
        <guid isPermaLink="true">/2006/05/19/pragmatic-studio-alumni-member/</guid>
      </item>
    
      <item>
        <title>Getting On Good Terms With The Os X Shell_redirect</title>
        <description></description>
        <pubDate>Sun, 19 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/3/19/getting-on-good-terms-with-the-os-x-shell</link>
        <guid isPermaLink="true">/2006/3/19/getting-on-good-terms-with-the-os-x-shell</guid>
      </item>
    
      <item>
        <title>Getting On Good Terms With The OS X Shell</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/iTerm.png&quot; alt=&quot;iTerm Logo&quot; width=&quot;135&quot; height=&quot;116&quot; class=&quot;floatl mr20&quot; /&gt; I will be the first to admit that I am really just learning how to tap into the power of my shell environment and to be honest, I&#39;ve spent way to many hours  reading man pages and figuring out how to do some really neat things that help my automate my workflow and system administration. Mostly these are just basic tasks like my &lt;a href=&quot;/2005/12/19/how-to-setup-a-simple-mysql-backup-script/&quot;&gt;Simple MySQL Backup&lt;/a&gt; and &lt;a href=&quot;/2006/02/24/shell-script-to-delete-all-invisible-_-resource-files/&quot;&gt;Deleting Invisible Resource Files&lt;/a&gt; scripts. But in all seriousness, when you get right down to using a UNIX-based operating system, you cannot escape using the shell environment. This is a good thing, its your friend, and getting your feet wet sooner than later is a good idea.
&lt;/p&gt;

&lt;h2&gt;Getting A Better Terminal Application&lt;/h2&gt;

&lt;p&gt;
  Go &lt;a href=&quot;http://iterm.sourceforge.net/index.shtml&quot;&gt;download iTerm&lt;/a&gt; from the sourceforge project page and install it. That default Terminal.app that comes with the Mac has got to go, it is dreadful looking and the features are really slack. Fortunately iTerm is a native Cocoa app that supports both the PowerPC and the new Intel Macs. The best feature of iTerm is that it supports tabbed windows, because you can never have to many terminal windows open. Here are some preferences I recommend after installing iTerm.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tab Position Top&lt;/li&gt;
  &lt;li&gt;Selection copies text to clipboard &amp;amp; Focus follows mouse  &lt;/li&gt;
  &lt;li&gt;The &amp;quot;Foreground&amp;quot; and ANSI Colors pictured below, most are defaults.&lt;/li&gt;
  &lt;li&gt;A dark background image with little detail so as not to interfere with your foreground text. &lt;/li&gt;
  &lt;li&gt;In there &amp;quot;Terminal&amp;quot; tab of the profiles, set the &amp;quot;Type&amp;quot; to &amp;quot;xterm-color&amp;quot;. &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/iterm_prefs-all.png&quot; alt=&quot;iTerm Profile Preferences&quot; width=&quot;500&quot; height=&quot;373&quot; class=&quot;mt20&quot; /&gt;
&lt;/div&gt;

&lt;h2&gt;Customizing Your Bash Profile &lt;/h2&gt;

&lt;p&gt;
  After you have a nice terminal program, its time to tweak your environment a bit. Here is a great set of customization commands that will change the way your shell interface is displayed when using the bash terminal, this is the standard shell environment on newer versions of OS X. Using these environment enhancements you will get a solid visual on the following information which is also colored coded to appear well on a dark background.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The current user you are logged in as (green) for you (red) for root/others. &lt;/li&gt;
  &lt;li&gt;The current machine name and working directory. &lt;/li&gt;
  &lt;li&gt;A new entry line which is not obscured by the items up above.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# User colors (root colors in /etc/bashrc)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;xterm-color&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[1;32m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[1;30m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[0m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[0;36m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PS1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\h&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) - (&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\A&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) - (&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\w&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C3&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Root colors (user colors in ~/.bash_profile)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;xterm-color&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[0;31m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[1;30m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[0m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33[0;36m&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PS1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\h&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) - (&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\A&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) - (&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C4&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\w&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C3&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  Here  is how to install these, they go into two separate places. The first customization commands go into your user home directory in a file called &lt;code&gt;.bash_profile&lt;/code&gt; and if you have never modified or used this file, you will have to make a new one. The period that precedes the name is technically not allowed by most text editors since it makes the file invisible. I suggested using &lt;a href=&quot;/2005/12/22/textmate-by-programmers-for-efficiency-experts/&quot;&gt;TextMate&lt;/a&gt; to create or modify this and the file below. Remember, the first file &lt;code&gt;.bash_profile&lt;/code&gt; needs to go into your home directory. The more you use your terminal, the more you will start to modify this file. It too is your friend.
&lt;/p&gt;

&lt;p&gt;
  The second set of customization commands go into the root &lt;code&gt;bashrc&lt;/code&gt; file. Again, using &lt;a href=&quot;/2005/12/22/textmate-by-programmers-for-efficiency-experts/&quot;&gt;TextMate&lt;/a&gt;, you can find this file in the /etc directory. If you are new to using TextMate to get to files in invisible directories, do this. When you have the &amp;quot;Open...&amp;quot; dialog window in view in TextMate, hold down &lt;code&gt;Command-Shift+G&lt;/code&gt;. This will open a sub dialog window called &amp;quot;Go to the folder:&amp;quot; with a text field to type the directory structure into. Simply enter &lt;code&gt;/etc&lt;/code&gt; and hit the &amp;quot;Go&amp;quot; button. This will take you right to the /etc directory and in there you should see the &lt;code&gt;bashrc&lt;/code&gt; file. Open it add the lines from the second code sample box above and save it. From this point onward your terminal window in iTerm should look something like this.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/my-iterm.gif&quot; alt=&quot;My iTerm Window&quot; width=&quot;523&quot; height=&quot;415&quot; class=&quot;shadow&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;
  I never setup a server without putting these customization settings in place. It just makes me feel more at home on the command line. In some later articles, I&#39;ll start to cover some really sweet shell scripts for more workflow automation. Let me know if you like this or if you have any problems setting them up on your system.
&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/03/19/getting-on-good-terms-with-the-os-x-shell/</link>
        <guid isPermaLink="true">/2006/03/19/getting-on-good-terms-with-the-os-x-shell/</guid>
      </item>
    
      <item>
        <title>Learn To Program In Ruby And Basic Sql_redirect</title>
        <description></description>
        <pubDate>Sun, 05 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/3/5/learn-to-program-in-ruby-and-basic-sql</link>
        <guid isPermaLink="true">/2006/3/5/learn-to-program-in-ruby-and-basic-sql</guid>
      </item>
    
      <item>
        <title>Learn To Program in Ruby and Basic SQL</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/ruby-sql_books.png&quot; alt=&quot;Learn To Program Ruby and SQL&quot; width=&quot;204&quot; height=&quot;182&quot; class=&quot;floatr ml20&quot; /&gt; I&#39;ve been learning to or &amp;quot;trying to learn&amp;quot; &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; for a few months now and things have always kept me from finishing the book that I purchased from those great publishers at the &lt;a href=&quot;http://www.pragmaticprogrammer.com/&quot;&gt;pragmatic bookshelf.&lt;/a&gt; My problem has been that sometimes other work has gotten in the way, but mostly it was because I did not have the core understanding of the basics for building web applications. Especially in the areas of object oriented programming and database languages. For me this was a big problem, I&#39;m typically a fundamentalist when it comes to learning and applying knowledge. Knowing the details helps me understand the big picture and more importantly the confidence to know what I am doing is correct. So rather than learning super high level code, I decided to revisit the 3-foot section of the pool again by reading these two books.
&lt;/p&gt;

&lt;h2&gt;&lt;em&gt;Teach Yourself SQL in 10 Minutes&lt;/em&gt; by Ben Forta&lt;/h2&gt;

&lt;p&gt;
  Just so you know, you are not going to  learn SQL in 10 minutes! This book is chopped up into &amp;quot;10 minute&amp;quot; exercises that take you into the language step by step. If you are new to databases, this book is great because it teaches you the core SQL syntax that most &lt;a href=&quot;http://en.wikipedia.org/wiki/Dbms&quot;&gt;database management systems&lt;/a&gt; use to extract and input data into the database itself. It even covers idioms that are unique for each database language including SQL Server, PostgreSQL, MySQL, and Oracle.
&lt;/p&gt;

&lt;p&gt;
  By the time I picked up &lt;a href=&quot;http://www.amazon.com/gp/product/0672325675/sr=8-1/qid=1141569613/ref=sr_1_1/103-7179153-7483038?_encoding=UTF8&quot;&gt;&lt;em&gt;Teach Yourself SQL in 10 Minutes&lt;/em&gt;&lt;/a&gt;, I had already learned to tread water in a huge Microsoft SQL Server database that I work in every day. So hacking stored procedures and building some basic queries were in my capabilities, but after reading Ben&#39;s book, I was able to do a lot more. It really pays off to know the basics and I&#39;ll let you in on a little secret. If you really want to work with databases and plan on sticking with it, I suggest using &lt;a href=&quot;http://www.dbsuite.com/mosg5/?action=product&amp;actionid=sql4xmanagerj&quot;&gt;SQL 4X Manager J 3&lt;/a&gt; by InterServices New Media. It will allow you to be database agnostic and its features are so rich that it will continue to be a valuable tool long after you have mastered SQL. This application is written in pure JAVA and it uses ODBC connections to support every database I have come across. I simple love its console support, the ability to edit and run stored procedures, create views, and generate entity relationship models. Trust me, it&#39;s worth the price!
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;a href=&quot;http://www.dbsuite.com/mosg5/?action=product&amp;actionid=sql4xmanagerj&quot; class=&quot;nobor&quot;&gt;
    &lt;img src=&quot;/assets/th_sql4xjmaininterface.png&quot; alt=&quot;Main Interface for SQL 4X Manager J 3&quot; width=&quot;528&quot; height=&quot;308&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;&lt;em&gt;Learn to Program&lt;/em&gt; by Chris Pine&lt;/h2&gt;

&lt;p&gt;
  If you are new to programming, this is a &lt;a href=&quot;http://www.pragmaticprogrammer.com/titles/fr_ltp/&quot;&gt;great book&lt;/a&gt; to pick up first. It is a modest 150 pages long and baby steps you into the concepts shared by most languages, using my favorite language, Ruby. That&#39;s right, I buy into that hype around this language because to me Ruby is like Apple Computer, its different! Here is an quote from its creator, Yukihiro Matsumoto, in the de facto Ruby resource guide,  the &lt;a href=&quot;http://www.pragmaticprogrammer.com/titles/ruby/index.html&quot;&gt;&lt;em&gt;Pragmatic Programmers&#39; Guide to Programming Ruby&lt;/em&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;blockquote&gt;
  I believe that the purpose of life is, at least in part, to be happy. Based on this belief, Ruby is designed to make programming not only easy but also fun. It allows you to concentrate on the creative side of programming, with less stress.
&lt;/blockquote&gt;

&lt;p&gt;
  So if you believe that JAVA is better thank Ruby or maybe PHP or any other language, please do not start to flame me. I think each language has its place. You can have yours and I&#39;ll have mine. I for one have always valued the underdog more. That said, &lt;em&gt;&lt;a href=&quot;http://www.pragmaticprogrammer.com/titles/fr_ltp/&quot;&gt;Learn to Program&lt;/a&gt;&lt;/em&gt; by Chris Pine is the place to start.
&lt;/p&gt;

&lt;p&gt;
  Like most other programming books, this one is rich in examples and test scripts. The thing that I thought most unique about it was that it forced you to utilize the concepts you learned by asking you to write a program that did X, Y, and Z. It did this without giving you the answers which really forces you out of the academia of learning into real practice. So if you &lt;a href=&quot;http://www.pragmaticprogrammer.com/titles/fr_ltp/&quot;&gt;pick up this book&lt;/a&gt;, or if decide to use &lt;a href=&quot;http://pine.fm/LearnToProgram/?Chapter=00&quot;&gt;the free tutorials&lt;/a&gt; on Chris&#39; website, check back here often and I&#39;ll keep posting updates on what code I came up with. Perhaps others can share how the faced the challenges since I could not find once single resource on the web that did this. Here are a few to start this off.
&lt;/p&gt;

&lt;h2&gt;A Few Things To Try (bottles of beer program)&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&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;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; bottles of beer on the wall. &#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; bottles of beer!&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;You take one down and pass it around... you have &#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bottles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39; bottles of beer on the wall.&#39;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;A Few Things To Try (roman numeral method)&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;romanize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integer&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mdiv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;M&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mdiv&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;D&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;C&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;L&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;X&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;V&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;I&#39;&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;integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;romanize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;420&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;romanize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;romanize&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;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;romanize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;278&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;romanize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2156&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;A Few Things To Try (how old are you, spank)&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;What year were you born in? (number please)&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chomp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;What month were you born on? (number please)&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chomp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;What day were you born on? (number please)&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chomp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bday&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mktime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;time&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;diftime&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bday&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;diftoyears&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;diftime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;365&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;diftoyears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;SPANK!&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Sun, 05 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/03/05/learn-to-program-in-ruby-and-basic-sql/</link>
        <guid isPermaLink="true">/2006/03/05/learn-to-program-in-ruby-and-basic-sql/</guid>
      </item>
    
      <item>
        <title>If Microsoft Designed The Ipod Packaging_redirect</title>
        <description></description>
        <pubDate>Thu, 02 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/3/2/if-microsoft-designed-the-ipod-packaging</link>
        <guid isPermaLink="true">/2006/3/2/if-microsoft-designed-the-ipod-packaging</guid>
      </item>
    
      <item>
        <title>If Microsoft Designed The iPod Packaging</title>
        <description>&lt;p&gt;
  iPods are part of our digital lifestyles and I have owned one ever since they first came out! Actually, I had mine one day before they came out since I was able to convince my local Apple store to release my prepaid item before the market date. Since then, I never looked back to the CD as a precious piece of material associated with music. Right after getting home with my new iPod, I promptly encoded all 300+ of my CDs onto my &lt;a href=&quot;http://en.wikipedia.org/wiki/Power_Mac_G4&quot;&gt;Quicksilver G4&lt;/a&gt;, looted Amazon for images, and &lt;a href=&quot;http://en.wikipedia.org/wiki/ID3_tag&quot;&gt;tagged&lt;/a&gt; every album with image art. After that, all my CDs turned into gifts for  my friends and as I have upgraded from computer to computer, that 20 gigabytes of music just follows me around every where I go.
&lt;/p&gt;

&lt;p&gt;
  Since I &lt;a href=&quot;/pages/resume.html&quot;&gt;used to do package design&lt;/a&gt;, I  found this little parity of Microsoft&#39;s attempt to correctly design the iPod packaging hilarious. Every time I watch it I think of all those years I&#39;ve laughed at large agencies and their inability to think as cleanly as Apple has prooved both technology and the design of it&#39;s presentation can work. Enjoy, and &lt;a href=&quot;http://youtube.com/watch?v=aeXAcwriid0&amp;amp;search=microsoft ipod&quot;&gt;watch this video&lt;/a&gt; please note, that I am not the author.
&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;a href=&quot;http://youtube.com/watch?v=aeXAcwriid0&amp;amp;search=microsoft ipod&quot; class=&quot;nobor&quot;&gt;
    &lt;img src=&quot;/assets/ms-ipod-redesign.jpg&quot; alt=&quot;If Microsoft designed the iPod packaging.&quot; width=&quot;450&quot; height=&quot;347&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 02 Mar 2006 00:00:00 -0500</pubDate>
        <link>/2006/03/02/if-microsoft-designed-the-ipod-packaging/</link>
        <guid isPermaLink="true">/2006/03/02/if-microsoft-designed-the-ipod-packaging/</guid>
      </item>
    
      <item>
        <title>Shell Script To Delete All Invisible _ Resource Files_redirect</title>
        <description></description>
        <pubDate>Fri, 24 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/2/24/shell-script-to-delete-all-invisible-_-resource-files</link>
        <guid isPermaLink="true">/2006/2/24/shell-script-to-delete-all-invisible-_-resource-files</guid>
      </item>
    
      <item>
        <title>Shell Script To Delete All Invisible ._ Resource Files</title>
        <description>&lt;p&gt;
  &lt;img src=&quot;/assets/network_drive.png&quot; alt=&quot;Network Drive&quot; width=&quot;102&quot; height=&quot;102&quot; class=&quot;floatr ml20&quot; /&gt; If you have ever accessed your website using a network protocol such as the Apple Filing Protocol (AFP), Samba (SMB), Web-based Distributed Authoring and Versioning (WebDAV), or Network File System (NFS) using your  Mac â€“ I am sure you have run into this problem before â€“ dreaded invisible resource fork files. These are the files that begin with a &lt;code&gt;._&lt;/code&gt; and they are normally not seen from within the finder. My understanding is that these files are not even created  on your local Mac hard drive since the &lt;a href=&quot;http://en.wikipedia.org/wiki/HFS+&quot;&gt;HFS+ file system&lt;/a&gt; is smart enough to keep your data and resource forks together in one single file. But even if you are accessing your website from one Mac HFS+ volume to another Mac HFS+ volume, these files will still be created by programs like DreamWeaver and TextMate because the various protocols to access that remote share and/or the file systems themselves will need to split them to cope. So ultimately when ever you use these other types of file systems or network protocols, you will eventually be creating lost of invisible resource fork files.
&lt;/p&gt;

&lt;h2&gt;Hey! ._ Files Are Not Really Bad&lt;/h2&gt;

&lt;p&gt;
  No they are not. By nature your Mac should deal with these just fine be it on you local drive or on a network volume. That said, I think it is important to point out what these invisible resource fork and other invisible files actually do. The most common one on any Mac is the &lt;code&gt;.DS_Store&lt;/code&gt; file. This stores preferences on window settings. If you open a window, and choose icon view and then move them around, the &lt;code&gt;.DS_Store&lt;/code&gt; file stores remembers all those settings. When you open that folder again, you see it the way it was left, thanks to that &lt;code&gt;.DS_Store&lt;/code&gt; file. I have  never had a problem with these files on a remote volume. They can live :)
&lt;/p&gt;

&lt;p&gt;
  The files that are prefixed with &lt;code&gt;._&lt;/code&gt; are resource fork files that have a one to one match with another file that you can see. For example, let&#39;s say you have a file called &lt;code&gt;index.php&lt;/code&gt; on your web server and you have made some changes to it with your editor such as &lt;a href=&quot;http://macromates.com/&quot;&gt;TextMate&lt;/a&gt;. Once you save that file, TextMate will create another file called &lt;code&gt;._index.php&lt;/code&gt; on your web server. Why? Well Textmate, just like the Finder, likes to save your preferences. The most common is what line number your cursor was on. Great feature, I hate scrolling back to that  line I just edited. However convenient this is, I have had &lt;code&gt;._&lt;/code&gt; files cause technical and visual problems on my web server. Most of the time these problems happen when a PHP application like &lt;a href=&quot;http://drupal.org/&quot;&gt;Drupal&lt;/a&gt; or &lt;a href=&quot;http://www.pmachine.com/&quot;&gt;Expression Engine&lt;/a&gt; needs to scan directories for files to include or enable in its application. The reason these files can be detrimental to your web application can be numerous and if you are reading this article, you probably don&#39;t care, so let&#39;s just get rid of them.
&lt;/p&gt;

&lt;h2&gt;The Killer Resource Script&lt;/h2&gt;

&lt;p&gt;
  This shell script consists of three commands. The first is the UNIX &lt;code&gt;find&lt;/code&gt; command. It is told to look for all files in a directory that have a name which starts with ._ and then print them to your window. The second part of the command is called &lt;code&gt;xargs&lt;/code&gt; and basically this takes each line form the first command and applies the  command immediately following it. In this case, remove, as indicated by the &lt;code&gt;rm&lt;/code&gt; at the end. The &lt;code&gt;-t&lt;/code&gt; after &lt;code&gt;xargs&lt;/code&gt; is optional, it is useful if you are running this from your terminal since it echos the command to you before it is executed. The final shell script looks like this.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#! /bin/bash&lt;/span&gt;
find /Volumes/Your_NetworkVolume -name &lt;span class=&quot;s1&quot;&gt;&#39;._*&#39;&lt;/span&gt; -print | xargs -t rm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  To customize this script you will need to change &amp;quot;&lt;code&gt;Your_NetworkVolume&lt;/code&gt;&amp;quot; where it appears above to the name of your web server share as it appears on your desktop.
&lt;/p&gt;

&lt;p&gt;
  I find it useful to put this script in my AppleScript menu. If your apple script menu is not on menu bar at the top of your screen, you can turn it on using the &amp;quot;AppleScript Utility&amp;quot; program located in your (/Applications/AppleScript) directory. Just check the box labeled &amp;quot;Show Script Menu in menu bar&amp;quot; and unless you want a really long  list of extra pre installed example scripts by Apple, I suggest keeping &amp;quot;Show Library scripts&amp;quot; unchecked.
&lt;/p&gt;

&lt;p&gt;
  &lt;span class=&quot;photofancy floatl mr20&quot;&gt;&lt;img src=&quot;/assets/applescript-menu.jpg&quot; alt=&quot;AppleScript Menu&quot; width=&quot;422&quot; height=&quot;267&quot; /&gt;&lt;/span&gt; Then using TextMate, create a file named something like this &amp;quot;DELETE ._ Files-on-MySvr.sh&amp;quot; and save it in your home (~/Library/Scripts) folder. While the file is still open in TextMate we need to make it executable by going to the menu (Automation Â» Run Command Â» Unix Shell Â» Make Script Executable). Once that is done you can close the script and you should see it appear in your scripts menu like this.
&lt;/p&gt;

&lt;p&gt;
  This way, you can get in the habit of running this command when you are done working on the web server. Of course, you could setup this script on the web server itself and then execute it via the crontab every so often. It&#39;s really up to you.
&lt;/p&gt;

&lt;p&gt;
  One last thing, in some cases you may have to delete invisible files on your web server that have spaces or special characters that might cause the script above to fail. Now why you would have files  on a web server that are non web friendsly is completely against my understanding, but if that is the case then you will have to use this modified version. It includes what I call a shielded version of the -print and xargs commands so they can understand how to escape or deal with the spaces and special characters.
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#! /bin/bash&lt;/span&gt;
find /Volumes/Your_NetworkVolume -name &lt;span class=&quot;s1&quot;&gt;&#39;._*&#39;&lt;/span&gt; -print0 | xargs -t0 rm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        <pubDate>Fri, 24 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/02/24/shell-script-to-delete-all-invisible-resource-files/</link>
        <guid isPermaLink="true">/2006/02/24/shell-script-to-delete-all-invisible-resource-files/</guid>
      </item>
    
      <item>
        <title>How To Control Browser Caching With Apache 2_redirect</title>
        <description></description>
        <pubDate>Sun, 19 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/2/19/how-to-control-browser-caching-with-apache-2</link>
        <guid isPermaLink="true">/2006/2/19/how-to-control-browser-caching-with-apache-2</guid>
      </item>
    
      <item>
        <title>How To Control Browser Caching with Apache 2</title>
        <description>&lt;p&gt;If you are like me, an up and coming network geek, you probably thought that browsers  automatically cached a site&#39;s assets and media as you went through it and looked at each page. I was very surprised to find out that this was not the case. In fact, every time I went from page to page on my newly created MetaSkills.net blog all of the CSS, PNG, JavaScript and  other media files that were common to those pages were being downloaded at each and every request. WOW! This was bad news for me and, if left untouched, it would have easily caused all of my bandwidth to be taken up when 50+ users came and started clicking around.&lt;/p&gt;

&lt;p&gt;This tutorial documents how I learned about browser caching and how you can force a browser to maintain representations of your site&#39;s assets using Apache 2 and its configuration directives. These directives will allow you to have either general or fine grained control over how a browser caches each file/type on your site. If you want to &lt;a href=&quot;#goodpart&quot;&gt;skip ahead to the good part&lt;/a&gt; and just apply them, feel free to do so. &lt;/p&gt;

&lt;h2&gt;Useful Tools For This Tutorial &lt;/h2&gt;

&lt;p&gt;Before we go any further, let&#39;s cover two really useful tools that will help you figure out what is going on with your website and to see if your web server is controlling browser caching as it should.  &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Tail_(Unix)&quot;&gt;The Unix &amp;quot;tail&amp;quot; Command &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://livehttpheaders.mozdev.org/&quot;&gt;The Live HTTP Headers Firefox Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a name=&quot;tail&quot; class=&quot;anchor&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;About The tail Command &lt;/h2&gt;

&lt;p&gt;Tail is a program on Unix-like systems that is used to display the last few lines of a text file, most commonly used on log files. The command syntax is real simple and for the purposes of this tutorial you will only need to concern yourself with the specific command in the code block shown below; the path can be either an absolute string (from the server root) or relative to the directory you are working in. This command will let you see live additions as they are being written to your Apache 2 log file. To exit from this program, simply press &lt;code&gt;Control-C&lt;/code&gt; on your keyboard.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ tail -f /the/path/to/your/logfile.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you have ever used the &lt;a href=&quot;http://www.apple.com/server/macosx/&quot;&gt;OS X Server Admin&lt;/a&gt; tool, you may have noticed that each service listed in the left hand side has a corresponding &amp;quot;log&amp;quot; tab on the right that allows you to see that latest log entries for that particular service. The log viewing feature even has a nifty search box. What is really happening here is that the Server Admin GUI is using  the same Unix &lt;code&gt;tail&lt;/code&gt; command mentioned above to show you the last several dozen lines in that file. I normaly like using the GUI tools that the Mac has to offer, but I am not using the default Apache 1.3 that comes with OS X, rather the &lt;a href=&quot;http://docs.info.apple.com/article.html?path=ServerAdmin/10.4/en/c5ws8.html&quot;&gt;evaluation version of Apache 2&lt;/a&gt; located in the /opt/apache2 directory. This means the GUI is not going to allow me to see the running log file of Apache2. Here is where using the underlying Unix tools on OS X comes in  handy.&lt;/p&gt;

&lt;p&gt;The tail command can be found on any OS X Server or Client installation; it is there by default. You can use this command from the server itself or you can SSH into the server with your laptop or other personal Mac and execute it from Terminal. Remember, this command is not useful to you if you do not have direct or SSH access to your web server where your log file is being written. If this is the case you will have to download it via your normal means and examine it in your favorite text editor.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;livehttpheaders&quot; class=&quot;anchor&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;About HTTP Headers &amp;amp; The Firefox Extension&lt;/h2&gt;

&lt;p&gt;HTTP headers are transparent to the end user and most people don&#39;t even care that they exist at all. Despite this, they are included at the beginning of   every response that comes from your server and they contain important information about that response. The most common  information includes the date, type of server sending the HTTP response, and encoding of the HTTP response. If you have the gumption, go read the 40+ pages on the &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14&quot;&gt;field definitions defined by the RFC 2616&lt;/a&gt; for HTTP headers. Otherwise, let&#39;s just focus on caching and seeing those HTTP headers which are normally invisible. &lt;/p&gt;

&lt;p&gt;This is where Firefox comes in handy. Many times I will use Firefox  during the development of a website simply because it has many extensions that have been specifically written to ease the technical aspects of making a website. If you don&#39;t have Firefox already, you can &lt;a href=&quot;http://www.mozilla.com/firefox/&quot;&gt;download Firefox here&lt;/a&gt;. Once you have that installed and running, you can&lt;a href=&quot;http://livehttpheaders.mozdev.org/&quot;&gt; get the Live HTTP Headers extension&lt;/a&gt; from the developers site at mozdev.org. &lt;/p&gt;

&lt;p&gt;Using the Live HTTP Headers extension is really easy. All you have to do is open the window by going to the &amp;quot;Tools&amp;quot; menu in Firefox and clicking on &amp;quot;Live HTTP headers&amp;quot;, this will open a blank window. When you use Firefox to go to a page or file, the HTTP header(s) will appear in that new window. Below is an example:&lt;/p&gt;&lt;br /&gt;

&lt;div class=&quot;center&quot;&gt;
    &lt;img src=&quot;/assets/live-http-headers.gif&quot; alt=&quot;A preview of the Live HTTP headers window in Firefox.&quot; width=&quot;468&quot; height=&quot;398&quot; class=&quot;center&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;If you are more comfortable using the Unix command line, there is one more useful tool that I would recommend called &lt;a href=&quot;http://furl.darwinports.com/&quot;&gt;furl&lt;/a&gt;.  It does the same thing as the Live HTTP Headers Firefox extension but only from the command line interface (CLI). It does not come on Mac OS X Server or Client by default but can be installed using the &lt;a href=&quot;http://darwinports.com/&quot;&gt;Darwin Ports&lt;/a&gt; system. I highly suggest using this vs. the Firefox extension since it is a leaner utility, but I&#39;ll leave it up to you whether you are more comfortable with a GUI or the command line. &lt;/p&gt;

&lt;h2&gt;Does My Site Control Browser Caching ? &lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Examining Your Apache Log Files (using tail)&lt;/strong&gt; - Let&#39;s start with the easy way of finding out. Simply open your Terminal program in the utilities folder and tail the log file for your host by typing the command &lt;a href=&quot;/2006/2/19/how-to-control-browser-caching-with-apache-2#tail&quot;&gt;described above&lt;/a&gt;. While leaving the terminal window open, navigate to your site with your browser. You should see additions to your log file appear live in your terminal window and it would look something like this picture below.&lt;/p&gt;&lt;br /&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/tail-command-in-terminal.gif&quot; alt=&quot;The Mac OS X terminal window using the tail command on my Apache 2 log file.&quot; width=&quot;547&quot; height=&quot;226&quot; class=&quot;shadow&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;As you browse around while looking at this window, you should NOT see yourself logging requests for CSS, Images, GIFFs, or JPEGs over and over again. If you are the only person on your website at that time, this should be fairly apparent. &lt;/p&gt;

&lt;p&gt;But, if you are not the only person on your site, it may get kind of noisy looking at all the log file entries whizzing by in the terminal window. In this case, you may find it useful to &amp;quot;pipe&amp;quot; an extra command to the tail program so that all you see is your requests and not the requests of others. To do this, simply make a note of your IP address and replace the &lt;code&gt;10.0.1.4&lt;/code&gt; IP address in the command below with your own.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ tail -f /the/path/to/your/logfile.log | grep 10.0.1.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This combined command will now use the &lt;a href=&quot;http://en.wikipedia.org/wiki/GREP&quot;&gt;GREP&lt;/a&gt; command in conjunction with the  tail program to search and display log entries with the matching pattern, in this case lines that contain your IP address. Remember to use &lt;code&gt;Control-C&lt;/code&gt; to exit from the tail program when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examining Your HTTP Headers&lt;/strong&gt; - The other way of finding out if your site is taking advantage of browser caching is to examine the HTTP headers on any given server response, be it a whole page or a single file. You can do this using the Live HTTP Headers Firefox extension mentioned above or by using the Unix &lt;a href=&quot;http://furl.darwinports.com/&quot;&gt;furl&lt;/a&gt; program if it is installed on your system. A common HTTP header response will look something like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;HTTP/1.1 200 OK
Date: Sun, 19 Feb 2006 16:42:05 GMT
Server: Apache/2.0.55 (Unix) DAV/2 PHP/5.1.1
Last-Modified: Sun, 08 Jan 2006 16:17:25 GMT
ETag: &quot;73049-defc-37c52f40&quot;
Accept-Ranges: bytes
Content-Length: 57084
Cache-Control: max-age=7200
Expires: Sun, 19 Feb 2006 18:42:05 GMT
Connection: close
Content-Type: image/png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What we are looking for in the header are the &amp;quot;Cache-Control&amp;quot; and &amp;quot;Expires&amp;quot; fields. These fields control how long the browser will cache this media or page asset from your server. Having a low value like &amp;quot;1&amp;quot; in &amp;quot;Cache-Control&amp;quot; can be just as bad as no value at all.&lt;/p&gt;

&lt;p&gt;If you have those fields present, you&#39;ve got a head start on the situation. If not, you may need to make sure Apache 2 is loading the &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_expires.html&quot;&gt;mod_expires&lt;/a&gt; and &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_headers.html&quot;&gt;mod_headers&lt;/a&gt; modules. Most installations and builds of Apache 2 include these modules since they are pretty essential. If you are using the Apache 2 in OS X Server&#39;s opt directory, this is the case and you only need to make sure that they are turned on by opening the http.conf file and making sure the following two lines do not have an # sign in front of them. &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-apache&quot; data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;nl&quot;&gt;LoadModule&lt;/span&gt; expires_module modules/mod_expires.so
&lt;span class=&quot;nl&quot;&gt;LoadModule&lt;/span&gt; headers_module modules/mod_headers.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When these modules are loaded and working, we can then start to use the correct Apache 2 directives to control how browsers cache everything from pages to images across the whole site or in a specific directory. &lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;goodpart&quot; class=&quot;anchor&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Using Apache 2 To Control Browser Caching &lt;/h2&gt;

&lt;p&gt;Now that we are here, I can assume that you have both the &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_expires.html&quot;&gt;mod_expires&lt;/a&gt; and &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_headers.html&quot;&gt;mod_headers&lt;/a&gt; modules  compiled and loaded into your Apache 2 installation. I can also assume that you have examined a few headers from your server&#39;s responses and  determined that the &amp;quot;Cache-Control&amp;quot; and &amp;quot;Expires&amp;quot; fields are either not set or they are configured at such a low value to be ineffective. Lastly, you may have bypassed some header examinations and just determined that browser caching is  not happening  by tailing your Apache 2 log file and monitoring redundant requests. Either way, let&#39;s get to fixing Apache 2 to control browser caching that is right for you and your particular site.&lt;/p&gt;

&lt;p&gt;Here is a code snippet of an Apache 2 directive that we will be using. This directive can be modified to suite your tastes  or it can just be used &amp;quot;as is&amp;quot; for most users. The directives here can  be placed into the &amp;lt;Directory&amp;gt; directive of your virtual host in http.conf or it can be placed loosely in a .htaccess file in the root of your website.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-apache&quot; data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IfModule&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;mod_expires.c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;  &lt;span class=&quot;nl&quot;&gt;ExpiresActive&lt;/span&gt; On
  &lt;span class=&quot;nl&quot;&gt;ExpiresDefault&lt;/span&gt; &quot;access plus 1 seconds&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; text/html &quot;access plus 1 seconds&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; image/gif &quot;access plus 120 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; image/jpeg &quot;access plus 120 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; image/png &quot;access plus 120 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; text/css &quot;access plus 60 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; text/javascript &quot;access plus 60 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; application/x-javascript &quot;access plus 60 minutes&quot;
  &lt;span class=&quot;nl&quot;&gt;ExpiresByType&lt;/span&gt; text/xml &quot;access plus 60 minutes&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IfModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&#39;s examine what is happening here in brief. If you are interested &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_expires.html&quot;&gt;full documentation of the expires directive&lt;/a&gt; can be found on Apache&#39;s website along with different syntax formats than the ones used here. I like this format since it is inheritably legible. This directive will do the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Set the default expiration of content in the browser cache to 1 second past the time of accessing that content. This is good for setting a catchall or default if you fail to explicitly define a content type in the following directives.&lt;/li&gt;
  &lt;li&gt;Set the expiration of text/html pages to 1 second. My content management system Drupal does this already in its .htaccess file, but I include it here if you wish to change it. I think this is a good setting since technically most html pages are small and I like to err on the side of caution and always want my page content to be fresh. For instance, I may make changes to my global template and want it to be visible immediately.&lt;/li&gt;
  &lt;li&gt;Set the expiration of standard images like GIFF, JPEG, and PNG to 2 hours.&lt;/li&gt;
  &lt;li&gt;Set the expiration of CSS and JavaScript to 1 hour.&lt;/li&gt;
  &lt;li&gt;Set the expiration of XML files such as RSS feeds to 1 hour. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;References &lt;/h2&gt;

&lt;p&gt;If you are interested in knowing ALL about caching including proxy caching and &lt;a href=&quot;/2006/2/16/a-review-of-digg-com-traffic-and-cdns&quot;&gt;CDNs which I covered in my last post&lt;/a&gt;, please read Mark Nottingham&#39;s article &amp;quot;Caching Tutorial for Web Authors and Webmasters&amp;quot;. Also included below are links to Apache&#39;s website manuals for each of the modules discussed here. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mnot.net/cache_docs/&quot;&gt;Caching Tutorial for Web Authors and Webmasters&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_expires.html&quot;&gt;Apache Module mod_expires&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_headers.html&quot;&gt;Apache Module mod_headers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 19 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/02/19/how-to-control-browser-caching-with-apache-2/</link>
        <guid isPermaLink="true">/2006/02/19/how-to-control-browser-caching-with-apache-2/</guid>
      </item>
    
      <item>
        <title>A Review Of Digg Com Traffic And Cdns_redirect</title>
        <description></description>
        <pubDate>Thu, 16 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/2/16/a-review-of-digg-com-traffic-and-cdns</link>
        <guid isPermaLink="true">/2006/2/16/a-review-of-digg-com-traffic-and-cdns</guid>
      </item>
    
      <item>
        <title>A Review of Digg.com Traffic and CDNs</title>
        <description>&lt;p&gt;Thanks to all those that read my recent post about &lt;a href=&quot;/2006/2/5/mini-network-with-a-big-xserve-style&quot;&gt;networking 3 Mac Mini&#39;s&lt;/a&gt; Hopefully it can help you create a network that is as close as possible to the  administrator&#39;s second home, the NOC. As an aside form the posts I had planned, I did want to share some of the statistics that the &lt;a href=&quot;http://www.digg.com/&quot;&gt;digg.com&lt;/a&gt; exposure generated and some &amp;quot;simple&amp;quot; helpful tips to those interested in surviving high traffic/bandwidth peaks. I&#39;ll cover more &amp;quot;technical&amp;quot; ways of setting up your server(s) to handle this too, but that is for &lt;a href=&quot;/2006/2/19/how-to-control-browser-caching-with-apache-2&quot;&gt;my next post.&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
    &lt;span class=&quot;photofancy&quot;&gt;&lt;img src=&quot;/assets/digg-homepage.gif&quot; alt=&quot;Mini network story on the home page of digg.com&quot; width=&quot;541&quot; height=&quot;231&quot; /&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;h2&gt;Bandwidth Chart (7 Days) &lt;/h2&gt;

&lt;p&gt;The story made it to the front page of digg about one week ago on Monday, February 6th. It was posted to Digg about 36 hours earlier on Saturday evening and within  1 hour of making it to the home page, using approximately 60 diggs to get it there, the bandwidth capacity here at ActionMoniker.com really took a dive. Below is a 7 day chart that goes from Sunday, February 5th to Saturday, February 11th.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;span class=&quot;photofancy&quot;&gt;&lt;img src=&quot;/assets/network-traffic.gif&quot; alt=&quot;7 Day Bandwidth Chart Showing Digg.com Traffic Usage&quot; width=&quot;384&quot; height=&quot;263&quot; /&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;The first big spike in the chart was the initial onslaught of traffic on Monday afternoon from the digg.com homepage. That small gap you see there before the next big spike is where the WebSvr Mini had to be rebooted. In fact, I even upgraded the RAM to one gigabyte. You can see another spike  towards the end that correlates to the secondary traffic generated from the &lt;a href=&quot;http://en.wikipedia.org/wiki/Blogosphere&quot;&gt;blogosphere&lt;/a&gt;, basically when other bloggers and news portals got around to posting the information about my article and then linking back to my site. Neat statistics, but let&#39;s take a look at why that WebSvr Mini crapped out.&lt;/p&gt;

&lt;h2&gt;We All Need Cache&lt;/h2&gt;

&lt;p&gt;Apache seemed to do well with the quantity of requests coming at it from Digg. That said, my post did have one HUGE draw back, the 10 large images on the article&#39;s page that totaled  124 Kilobytes in size. My assumption is that when the server started taking requests in mass   my 2.6 Megabit connection was not fast enough to serve those images in a timely manner. This caused a cascading effect on Apache by  keeping memory intensive threads open for longer and longer until the server could not take it any more.&lt;/p&gt;

&lt;p&gt;This is where a good cache comes in handy. Not  browser or proxy caches, those are for &lt;a href=&quot;/2006/2/19/how-to-control-browser-caching-with-apache-2&quot;&gt;my next post&lt;/a&gt; too, but rather  what are called gateway caches which are more commonly called Content Delivery Networks (CDNs). These are distributed caching servers throughout the internet that typically help deliver content to a client by geotargeting a visitors IP address and then finding a server close to that IP with the requested content. The best example of commercial CDN is &lt;a href=&quot;http://www.akamai.com/&quot;&gt;Akamai&lt;/a&gt;, I think Apple bought or invested in these guys about 3 years ago, but I digress. The point is that CDNs can help distribute the load off of your local server by copying your content be it a whole web page or just certain media types and serving them up to your visitor&#39;s browser.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/map-world-gen-1.gif&quot; alt=&quot;The Coral cache network map.&quot; width=&quot;248&quot; height=&quot;107&quot; class=&quot;floatr ml20&quot; /&gt; The most popular CDN that is freely used by many digg.com readers is a company called &lt;a href=&quot;http://www.coralcdn.org/&quot;&gt;Coral&lt;/a&gt;. Many times a Digg or Slashdot article will take down an unsuspecting server (know as the slashdot effect)   forcing prospective visitors to view your content from a cached version on a sever very far away from your own. Often readers on both Slashdot and Digg try to &amp;quot;coralize&amp;quot; your article by linking to it from a comment thread using the Coral network as a cache. This is easily done by  adding &lt;code&gt;.nyud.net:8090&lt;/code&gt; to the end of any hostname in a URL. For instance &lt;code&gt;http://www.metaskills.net/article.php&lt;/code&gt; would become &lt;code&gt;http://www.metaskills.net.nyud.net:8090/article.php&lt;/code&gt; but this is really only helpful to prospective readers if the coralized link was used as the initial link on Digg or Slashdot.&lt;/p&gt;

&lt;aside class=&quot;ms-Flash&quot;&gt;
  UPDATE: As of February 17th, Coral now uses both ports &lt;strong&gt;:8090&lt;/strong&gt; and &lt;strong&gt;:8080&lt;/strong&gt;
&lt;/aside&gt;

&lt;p&gt;In my case it was not and I did not like the idea of users having to read my article on somebody else&#39;s server nor relying on them finding a coralized link to my site buried in a comment thread. If that had happened, I would have lost traffic statistics, user comments, RSS subscriptions, lateral page visitation, and many  visitors altogether. I had to get the server running again and cope with my limited bandwidth. Wow, I just said 2.6 megabits was limited :) &lt;/p&gt;

&lt;h2&gt;Just Cache Images or Large Media &lt;/h2&gt;

&lt;p&gt;When I rebooted the WebSvr Mini, I immediately changed the the &lt;code&gt;&amp;lt;img src=&amp;quot;&amp;quot;&amp;gt;&lt;/code&gt; tags of the 10 images in the content area that had the largest file sizes to appear from the Coral network. This was done by changing the image source tags from &lt;code&gt;&amp;lt;img src=&amp;quot;/images/mac-mini-network.jpg&amp;quot;&amp;gt;&lt;/code&gt;  to a fully qualified domain source using the coral server which ended up looking something like this &lt;code&gt;&amp;lt;img src=&amp;quot;http://www.metaskills.net.nyud.net:8090/images/mac-mini-network.jpg&amp;quot;&amp;gt;&lt;/code&gt; thus ensuring any future visits to my article received those images from  1 of any of the the &lt;a href=&quot;http://coralcdn.org/maps/&quot;&gt;260 Coral network servers&lt;/a&gt;. In this way the largest aspect of my page was completely offloaded leaving my local Apache to handle the page source and other media request in a timely fashion. Best of all, this was completely transparent to the end user and no features were lost in their browsing experience. &lt;/p&gt;

&lt;p&gt;I highly suggest that if you know ahead of time that an article of yours will be Slashdoted or Dugg, that you coralize as many of the images or large media files on your web server as possible. Your options on what that media content type is may vary, but choosing the ones with the largest file size first is usually the best idea. It can save your site from going down or to a creeping crawl. &lt;/p&gt;

&lt;h2&gt;Do You Digg It ?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/digg-hat.png&quot; alt=&quot;Digg.com Hat&quot; width=&quot;125&quot; height=&quot;133&quot; class=&quot;floatl mr20&quot; /&gt;Well I do and to date we have had 34,000 reads to the Mac Mini Network article. With a success like that it was time to sport some gear. I had already changed my default home page from my &lt;a href=&quot;http://www.google.com/ig&quot;&gt;customized Google&lt;/a&gt; with Slashdot articles to digg.com and now all I needed was a hat to tell the world. For the past 5 months I have been sporting a /. hat and matching retro LED digital watch from ThinkGeek.com and it was time for a change. I thought for sure that there would be a vendor out there selling &amp;quot;I got Dugg&amp;quot; or &amp;quot;Digg It&amp;quot; or even a logo embroidered hat, but I could not find one at all! I would have to say that this company has sure missed out on some sweet merchandising opportunities. So I will have to stay with my /. hat. &lt;/p&gt;

&lt;p&gt;Above is a comp I put together at CafePress.com. I even mailed it to Digg.com and asked what they thought. They kindly asked that I refrain from using their mark on resale items until their lawyers finished helping them with their copyrights and licensing agreements. Maybe I will go back to /. &lt;/p&gt;
</description>
        <pubDate>Thu, 16 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/02/16/a-review-of-digg-com-traffic-and-cdns/</link>
        <guid isPermaLink="true">/2006/02/16/a-review-of-digg-com-traffic-and-cdns/</guid>
      </item>
    
      <item>
        <title>Mini Network With A Big Xserve Style_redirect</title>
        <description></description>
        <pubDate>Sun, 05 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/2/5/mini-network-with-a-big-xserve-style</link>
        <guid isPermaLink="true">/2006/2/5/mini-network-with-a-big-xserve-style</guid>
      </item>
    
      <item>
        <title>Mini Network with a Big XServe Style</title>
        <description>&lt;p&gt;Or, how to be the biggest network geek you can  in only 1 square foot of space. Starting last year after  reading &lt;a href=&quot;http://mundy.org/blog/index.php?p=40&quot;&gt;Ward Mundy&#39;s How-To Bonanza&lt;/a&gt;, I knew I needed to use the Mac Mini as the core hardware component for my home network. Mostly because it looks good and small form fits easily on my desk. Good as that might be, the Mac Minis do have drawbacks and, if you&#39;re serious about your hosting choices, these do have to be overcome; this is what my post is all about.  &lt;/p&gt;

&lt;p&gt; So like most people that create networks I did not realize that the Mac Mini includes 3 high speed  network interfaces and  that with a little bit of work and the right architecture they can be used  to operate in much the same manner one would  see in a high-end network operations centers. I manage one such NOC and I wanted my home network  to function like most companies who do serious business online. These features typically include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Internal LAN Network Interfaces - (10.0.1.0/24 Addresses) &lt;/li&gt;
  &lt;li&gt;Internal Perimeter Network (DMZ) Behind a NAT or Port Forwarding Firewall &lt;/li&gt;
  &lt;li&gt;Both Internal (LAN) and External (Public) DNS Services &lt;/li&gt;
  &lt;li&gt;IP Over Firewire  Connections - (192.168.1.0/25 Addresses) &lt;/li&gt;
  &lt;li&gt;Hard Drive Redundancy and Backup Using RsyncX - (typically RAID 1 or 5)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Starting At The End&lt;/h2&gt;

&lt;p&gt;Below is a simple diagram of my final network. I had to lose a few features from the list above or even change their  meaning a bit, but I did end up with a network that utilizes most of them.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/simple-mac-mini-network-diagram.jpg&quot; alt=&quot;Most Advanced Simple Mac Mini Network Diagram&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Public Interfaces&lt;/h2&gt;

&lt;p&gt;In the diagram above, the (green) represents public 100baseT ethernet interfaces while (orange) and (red) represent an internal network. Due to many questions regarding this layout, I want to stress that the WebSvr and generic Mini (mail and DNS) are publicly available on the 100baseT connections through my Linksys switch. The AirPort is for local LAN only, see below for details.&lt;/p&gt;

&lt;h2&gt;Internal Local Area Network ( LAN ) &lt;/h2&gt;

&lt;p&gt;First thing on the list that is the most important feature. A local area network that allows connections to each server without going outside to the public internet and thus taking up valuable bandwidth to those public interfaces. It&#39;s also good for security! The AirPort Extreme I had did this quite well by setting it to share a network connection using DHCP and NAT on the 10.0.1.0/24 subnet. The AirPort internet connection is setup to DHCP to my ISP from its WAN port. Each Mac Mini&#39;s AirPort network interface is manually set on its own IP address that never changes. This will need to be done so you can assign it an internal DNS name and reverse PTR record.&lt;/p&gt;

&lt;h2&gt;Internal DNS Services ( WebSvr Mini )&lt;/h2&gt;

&lt;p&gt;Now that we have an internal LAN  we can use this to host our own DNS so that machines on the local network including my powerbooks and other systems will use the AirPort interfaces for services. For instance, if I browse to my website from home, I am not using the public interface and bandwidth, but rather the IP with the AirPort address. The WebSvr Mini was my best choice for hosting DNS and I have BIND 9 configured to only listen for queries on the local 127.0.0.1 IP and its own 10.0.1.x AirPort IP address. BIND is also configured to forward all unknown queries to my ISP. It&#39;s very important to set the basestation&#39;s internet tab be set to use the WebSvr Mini&#39;s 10.0.1.x AirPort IP address for DNS, rather than your ISP. In this way, all clients that are not manually configured to do so will use the WebSvr mini for DNS and hence the AirPort interfaces on each server for services. I hope I have not lost you yet. When using internal DNS the right way, all local traffic such as Apache, Apple Remote Desktop, MySQL, SSH, etc. are all done locally and fast. So do not forget to tell Apache it can listen on that port.&lt;/p&gt;

&lt;h2&gt;IP Over Firewire Database Connection ( DbSvr Mini )  &lt;/h2&gt;

&lt;p&gt;The DdSvr Mini is using Apple&#39;s IP over firewire capabilities to connect to the WebSvr Mini. I have a patch cable connected to the WebSvr Mini with static IP addresses on both ends using the 192.168.1.0/24 subnet. For convenience each of the 192. addresses ends with the same number as their respective 10. AirPort addresses. This is the 3rd network interface that most people are not aware of. It has limitations but used wisely it can be very useful and fast. In the set up above I am able to keep all database traffic entirely off of my internal switch and localized to that one patch cable. Unless of course, I decide to access the DbSvr Mini using its LAN/AirPort address. Either way, this machine is totally off the public network and quite secure.&lt;/p&gt;

&lt;h2&gt;Other Services ( Mail and External DNS )&lt;/h2&gt;

&lt;p&gt;That&#39;s what the other unlabeled Mini is for. I have it configured to for mail and public DNS. Postfix is happily listening on its public and private addresses while DNS is only listening on the public IP. This server also does not have an external drive (see below) since I am not worried about its performance since the overhead is quite low for those two services. &lt;/p&gt;

&lt;h2&gt;Firewall Services &lt;/h2&gt;

&lt;p&gt;In this setup I did loose the ability to have private addresses for my two public Minis. Hard core network engineers would point out that this would be another layer of security by having a single firewall/router filter and translate packets to these two boxes. I agree and it makes for a nice portable network too. But, I am more than happy running the ipfw service built into OS X Server that is running on each Mac Mini. It is a great stateful firewall and it&#39;s not really a configuration nightmare to maintain each one. All in all, it&#39;s what I call the RONCO network, set it and forget it. Now on to fixing some of the deficiencies for the Mac Mini. &lt;/p&gt;

&lt;h2&gt;Improving Hard Drive Performance &lt;/h2&gt;

&lt;p&gt;One of the first drawbacks to the mac mini is its poor hard drive speed. This can be a real big hit on performance when it comes to hosting a descent web or database server. Thankfully there are alternatives including  upgrading the internal drive with a faster  form factory laptop drive. However, these can be expensive and if you are like me and have a few Barracuda 7200 RPM 3.5 inch external drives laying around, you could save a lot by purchasing an inexpensive firewire enclosure. I decided on the &lt;a href=&quot;http://www.newertech.com/products/products_mini1.php&quot;&gt;miniStack from newertechnology&lt;/a&gt; since it had the best cooling features and good Mac Mini style. More importantly it sells with a driveless option and comes with firewire cables. A deal for only $69.00 for the entire kit. &lt;/p&gt;

&lt;p&gt;I purchased (2) of these, one for each Mini who&#39;s performance I was really concerned about, one for the web server and one for the database server. Each of those Macs boot directly from that external drive connected via firewire, the internal drive is used as a back up. Currently I have the DbSvr Mini setup as an RsyncX server and every night each of the 3 servers backs up to its internal hard drive. That&#39;s a separate post in itself. &lt;/p&gt;

&lt;h2&gt;Improving AirPort Signal Strength&lt;/h2&gt;

&lt;p&gt;I was really surprised to find out how poor the Mac Mini&#39;s AirPort signal strength was  after you stack something on top of it. My extreme basestation was only a few feet away and the interference from the drive enclosures was so bad that I could not connect two of them that were in the middle of my stack. Thankfully, I was no stranger to &lt;a href=&quot;http://www.pbfixit.com/Guide/82.11.0.html&quot;&gt;taking apart my Mac Mini&lt;/a&gt;. In fact, I had installed AirPort cards on all of them since it was cheaper for me to do so and I had an idea! So be warned, the following steps will  void your warranty - but if you want to get good AirPort strength and this was a must for me, here is some helpful instructions. &lt;/p&gt;

&lt;p&gt;First though, the unordered list below is a parts list with links to Mac-Pro.com. If you are wanting to install an AirPort Extreme card in a Mac Mini, these are the parts you will need. Secondly, my AirPort signal strength &amp;quot;fix&amp;quot; below is by no means a comprehensive step by step for a first timer into the Mac Mini. I highly recommend &lt;a href=&quot;http://www.pbfixit.com/Guide/82.0.0.html&quot;&gt;PBFixIt.com&#39;s Mac Mini Take Apart Guide&lt;/a&gt; for that. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mac-pro.com/s.nl/sc.2/category.333/it.A/id.1719/.f&quot;&gt;Mezzanine Board for Mac Mini&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mac-pro.com/s.nl/sc.2/category.22/it.A/id.1720/.f&quot;&gt;AirPort Antenna for Mac Mini&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mac-pro.com/s.nl/sc.2/category.333/it.A/id.1853/.f&quot;&gt;Screws for Mac Mini Mezzanine Board&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OK, now to the fun part, Improving your AirPort signal strength. You will need to get a good clean work area setup and take apart your Mac Mini down to the mezzanine board where your AirPort card is installed. Do not actually take that out, we are just going to reroute the cable. Just unplug the AirPort extreme antenna. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/getting-ready-to-work_large.jpg&quot; alt=&quot;My best attempt at a clean work area. Remember to unplug the AirPort antenna from the extreme card.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The most logical place to run the AirPort antenna externally is through the security hole on the back right side. The only other choice would have us drilling holes in the vents and the hood that funnels air out the back of the Mac Mini. Least invasive is good, so I took a dremel and widened that hole up. I made a circular opening the same diameter as the existing width of the security hole. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/expanding-security-hole_large.jpg&quot; alt=&quot;Use a dremel to open a circular hole in the back. Make sure to use a screw driver to remove any excess plastic.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now that the hole is wide enough, route the AirPort antenna back through this new opening. Make sure not to cut the antenna cord on the metal shielding. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/threading-the-anteana_large.jpg&quot; alt=&quot;Route the AirPort antenna back through this new opening. Make sure not to cut the antenna cord on the metal shielding.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After you connect the AirPort antenna back to the AirPort extreme card, make sure that you leave the cable lying next to the slot the drive and fan assembly goes back into. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/external-mini-airport_large.jpg&quot; alt=&quot;Make sure that you leave the cable lying next to the slot the drive and fan assembly goes back into.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here is a picture of the how the antenna cable routes through the small opening that is designed to the left drive and fan assembly slot. This is where Apple intended the AirPort antenna to go. We are just taking a detour. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/airport-wire_large.jpg&quot; alt=&quot;A picture of the how the antenna cable routes through the small opening that is designed to the left drive and fan assembly slot.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now we are ready to put the cover back on the Mini, but since we have the AirPort antenna going out the security slot, we will need to cut the metal anchor off. I sliced it right at the bottom, marked in the larger photo. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cutting-the-security_large.jpg&quot; alt=&quot;Cut the metal anchor for the security slot off before putting the cover back on. Cut it flush with the Mini&#39;s casing.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have found it extremely useful to take your putty knife and push on the shielding on the back side of the Mini when you are snapping the cover back on. Otherwise you will just bend the clips when you are pushing it together. And just in case your asking, yes, a putty knife is the standard tool for taking apart a Mac Mini. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/putting-the-mini-together_large.jpg&quot; alt=&quot;Put your putty knife into the back of the Mini to help you nudge the shielding inside the cover when you are snapping it back together.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here is a final picture of the back of the Minis after they are all back together. Here you can see the AirPort antennas sitting comfortably out the back. No signal interference now! &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/final-mac-mini-w-airport_large.jpg&quot; alt=&quot;Here you can see the AirPort antennas sitting out the back of each Mac Minis.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&amp;lt;&lt;/p&gt;

&lt;p&gt;This was the reason I started my network project. I have 3 servers right on my home office desk with all the comforts of a full fledged NOC in less than 1 square foot of space. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/final-mac-mini-stacks_large.jpg&quot; alt=&quot;Final front view of 3 Mac Mini server right on my home office desk wiht all the comforts of a full fledged NOC in less than 1 square foot of space.&quot; class=&quot;ms-Img ms-Img--responsive-ctr ms-Img--fancy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That&#39;s it! If you have any questions, please let me know. Or perhaps, maybe you have some ideas on what I could work on for version two of the network?&lt;/p&gt;
</description>
        <pubDate>Sun, 05 Feb 2006 00:00:00 -0500</pubDate>
        <link>/2006/02/05/mini-network-with-a-big-xserve-style/</link>
        <guid isPermaLink="true">/2006/02/05/mini-network-with-a-big-xserve-style/</guid>
      </item>
    
      <item>
        <title>Cooking With Drupal_redirect</title>
        <description></description>
        <pubDate>Sat, 28 Jan 2006 00:00:00 -0500</pubDate>
        <link>/2006/1/28/cooking-with-drupal</link>
        <guid isPermaLink="true">/2006/1/28/cooking-with-drupal</guid>
      </item>
    
      <item>
        <title>Cooking with Drupal</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/cooking-with-drupal.png&quot; alt=&quot;Cooking With Drupal&quot; class=&quot;ms-Img ms-Img--responsive&quot;/&gt;One of my few New Year&#39;s resolutions was to blog often in the year 2006, in fact, I promised myself I was going to write at least one post every day. Well it&#39;s been two weeks since my last update and the world has missed some pretty good brain dumps from yours truly (sorry about that) but I have been keeping good notes and I do have great news about today!&lt;/p&gt;

&lt;p&gt;Over the past few weeks I have been cooking up a storm in my digital kitchen with one of the best content management systems around, &lt;a href=&quot;http://www.drupal.org/&quot; title=&quot;Learn About One of the Best Content Management Systems on the Planet, Drupal.&quot;&gt;Drupal&lt;/a&gt;. This is the same CMS that runs the metaskills.net site and it has a good history for not just being a Blog or Forum software but an entire community  platform, thus Drupal&#39;s tag line, Community Plumbing.&lt;/p&gt;

&lt;h2&gt;How Can You Say Drupal Is The Best CMS ? &lt;/h2&gt;

&lt;p&gt;OK, I would like to take back my exclamation about Drupal being the best CMS. A lot of people make absolute statements like this and they are  always never wholly true. Choosing the &amp;quot;best&amp;quot; CMS is a relative concept and only possible when one starts backwards and defines their own end requirements and vision purpose of the system  needed. For instance, if all you wanted was a personal blog, I would highly recommend &lt;a href=&quot;http://wordpress.org/&quot; title=&quot;WordPress is a state-of-the-art semantic personal publishing platform.&quot;&gt;WordPress&lt;/a&gt; as the right CMS for you. In that same vein, if you are new to the internet and tend to stay in the 3-foot section,  a hosted non open source blogging system like &lt;a href=&quot;http://www.typepad.com/&quot;&gt;TypePad&lt;/a&gt;, &lt;a href=&quot;http://www.livejournal.com/&quot;&gt;LiveJournal&lt;/a&gt;, or even Google&#39;s &lt;a href=&quot;http://www.blogger.com/&quot;&gt;Blogger.com&lt;/a&gt; would be a good choice. These are great for beginners that have no interest in the back end setup work or maintenance typically associated with a professional CMS. &lt;/p&gt;

&lt;p&gt;On the other hand, if you do real business on the internet, a &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_as_a_Service&quot;&gt;SaaS&lt;/a&gt; might not do. That&#39;s OK because your still in for a good swim as there are  numerous choices to be made. If you are a small publishing company like &lt;a href=&quot;http://www.ilounge.com/&quot;&gt;iPodLounge&lt;/a&gt;, you could use pMachine&#39;s &lt;a href=&quot;http://www.pmachine.com/ee/&quot;&gt;Expression Engine&lt;/a&gt;. Its tag-based and well documented system is very easy to use, customize, and control permissions to content and features. If you are a software developer and need workflow, project management, CRM, bug and issue tracking &lt;a href=&quot;http://www.atlassian.com/&quot;&gt;Atlassian&#39;s&lt;/a&gt; JIRA or Confluence could be right for you. Moving on into the open source software realm, options include &lt;a href=&quot;http://www.zope.org/&quot;&gt;Zope&lt;/a&gt; or &lt;a href=&quot;http://plone.org/&quot;&gt;Plone&lt;/a&gt; for the Python programmers to &lt;a href=&quot;http://www.mamboserver.com/&quot;&gt;Mambo&lt;/a&gt; or even &lt;a href=&quot;http://www.drupal.org/&quot;&gt;Drupal&lt;/a&gt; for the PHP enthusiasts. Many of the features in all of these system blur together and it really does matter on many personal and business factors to agree on the &amp;quot;best&amp;quot; CMS for your needs.&lt;/p&gt;

&lt;h2&gt;That Smells Good, What Ya Cooking ?&lt;/h2&gt;

&lt;p&gt;Ah yes, that! Well now that I have avoided a flame war by sidestepping the &amp;quot;best&amp;quot; CMS argument let&#39;s get back into my favorite CMS at the moment, Drupal. When I first launched metaskills.net I used the current 4.6 version. Since then the Drupal team has been hard at work on version 4.7 (currently beta4) and to help give back to this great open source software movement, I decided to learn how Drupal works on the back end and contribute my blog theme. Doing so meant I had to actually learn a little PHP and JavaScript and the correct &lt;a href=&quot;http://drupaldocs.org/&quot;&gt;Drupal API&lt;/a&gt; and publishing hooks, both old and new. I have to say that I am very impressed with the Drupal system. Its power and extensibility is quite unique and its community demonstrates the best practices of what open source software is all about.&lt;/p&gt;

&lt;p&gt;Here is the new &lt;a href=&quot;/2008/03/22/metaskills-net-reborn-on-mephisto//&quot; title=&quot;Meta Theme for Drupal&quot;&gt;Meta Theme for Drupal&lt;/a&gt;, this is a demonstration site that will serve as a working reference and online documentation for the theme&#39;s project on drupal.org. Here is an abstract list of some of the new features.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Total CSS over write of all Drupal&#39;s 4.7  features&lt;/li&gt;
  &lt;li&gt;The world&#39;s best style sheet switcher with DOM2 support and cookies&lt;/li&gt;
  &lt;li&gt;Custom image gallery theme with dynamic lightbox.js support&lt;/li&gt;
  &lt;li&gt;PNG support for IE 6 and lower&lt;/li&gt;
  &lt;li&gt;Multiple code syntax highlighting options  &lt;/li&gt;
  &lt;li&gt;Custom and dynamic maintenance page&lt;/li&gt;
  &lt;li&gt;Dynamic comment depth integrated with CSS rules  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please feel free to browse this site and comment and ask question. If you see any problems, let me know as I will be actively supporting this them for upcoming Drupal releases. &lt;/p&gt;
</description>
        <pubDate>Sat, 28 Jan 2006 00:00:00 -0500</pubDate>
        <link>/2006/01/28/cooking-with-drupal/</link>
        <guid isPermaLink="true">/2006/01/28/cooking-with-drupal/</guid>
      </item>
    
      <item>
        <title>The Best Font For Mac Programmers Profont_redirect</title>
        <description></description>
        <pubDate>Wed, 11 Jan 2006 00:00:00 -0500</pubDate>
        <link>/2006/1/11/the-best-font-for-mac-programmers-profont</link>
        <guid isPermaLink="true">/2006/1/11/the-best-font-for-mac-programmers-profont</guid>
      </item>
    
      <item>
        <title>The Best Font for Mac Programmers, ProFont</title>
        <description>&lt;p&gt;After being exposed to using &lt;a href=&quot;/2005/12/22/textmate-by-programmers-for-efficiency-experts/&quot;&gt;TextMate&lt;/a&gt; for all my normal text editing needs, I soon began to do more things than just simple &lt;a href=&quot;http://en.wikipedia.org/wiki/Grep&quot;&gt;GREP-based&lt;/a&gt; search and replace functions. I actually started to look at code more often. Within a few short months, I had gone away from my established norm of the happenstantial viewing of simple CSS, HTML and PlainText files to a ful-time lookey lou of languages such as Ruby, XML, PHP, SQL or any number of configuration files for Apache, PHP, Postfix, Bind, and so on. It&#39;s been an exciting time for me over the past 6 months and it feels like open hunting season on any hard to find UNIX application files that are deep in the brush of  my Mac OS X. Belive me, treasure are rich once you start digging.&lt;/p&gt;

&lt;h2&gt;So What&#39;s Great About ProFont?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/provsmonaco.gif&quot; alt=&quot;ProFont vs. Apple&#39;s Monoco&quot; class=&quot;ms-Img ms-Img--responsive ms-Img--fancy&quot; /&gt;&lt;/span&gt; On the left, you can see ProFont compared to the original version of Apple&#39;s Monaco font face. This picture was taken from the ProFont distribution readme file. It really shows the differences in how it treats zeros, apostrophes, lowercase L, upper I, colons, and semi colons. This stuff makes it really important if you are looking at code all the time. Profont even shines in the Terminal window too. Size matters too, ProFont works well at 9pt if your eyes are holding up that well, mine are not, so I have to stick at 10pt.&lt;/p&gt;

&lt;h2&gt;Where Do I Get ProFont?&lt;/h2&gt;

&lt;p&gt;Right here.   I&#39;ve packaged it for Mac and Windows. If your a Linux or Atari junky and want ProFont, go check out an &lt;a href=&quot;http://www.tobias-jung.de/seekingprofont/&quot; title=&quot;ProFont for Windows, for Macintosh, for Linux, and even for Atari!&quot;&gt;indepentdant maintainer&lt;/a&gt; for the font and download those verions from his website. &lt;/p&gt;
</description>
        <pubDate>Wed, 11 Jan 2006 00:00:00 -0500</pubDate>
        <link>/2006/01/11/the-best-font-for-mac-programmers-profont/</link>
        <guid isPermaLink="true">/2006/01/11/the-best-font-for-mac-programmers-profont/</guid>
      </item>
    
      <item>
        <title>TextMate, by Programmers, for Efficiency Experts</title>
        <description>&lt;p&gt; About a year ago a fellow co-worker of mine was raving that I should learn VIM from the command line interface (CLI) so that I could use it for all my text editing needs. My co-worker at the time was (and probably still is) the Systems Administrator and Lead Application Developer for a company that sold &lt;a href=&quot;http://www.planetcdrom.com/&quot; title=&quot;Buy Cheap Discounted Educational Software&quot;&gt;cheap discount software&lt;/a&gt;. During my tenure there I served as the Marketing Manager and as such, many of my projects to completely overhaul their search engine and online marketing strategies called for aligning their internal tools and processes. While doing said technical revamps and specification writing, I guess I was exposed as more of a geek than your typical marketer. Hence the recommendation to go further down the rabbit hole. &lt;em&gt;DISCLAIMER: before I go any further -- I would like to say, yes, that link up there is a shameless plug and is meant only to help in the organic search strategies for PlanetCDROM.com.&lt;/em&gt; OK, I feel better. &lt;/p&gt;

&lt;h2&gt;Down the Rabbit Hole? &lt;/h2&gt;

&lt;p&gt;So did I do it? Am I using VIM and did I even code this XHTML in such an arcane system? The answer is no, but I will admit that I love the CLI from a UNIX operating system. In fact, I will be writing another installment on how to &lt;a href=&quot;/2006/03/19/getting-on-good-terms-with-the-os-x-shell/&quot;&gt;tweak and customize your shell environment.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main reason I did not learn VIM is because it goes against my technical MO which is also the main theme of this website -- that working at a higher level is better than keeping your head in the trenches. Sure tried and true pays off sometimes, but technology moves fast and there evolves better ways. VIM stays to far down the path of the harder, at least for me anyway. I typically like to get into the details only enough, so that I can figure out a better way of doing things. VIM would have made a good choice to learn if I was forced to work in a Windows environment where my only escape to the UNIX-style world was shell access to a Fedora Core operating system, but hey, that&#39;s not the case. I like to advocate working and hosting on Macs and that&#39;s a convention all to itself. &lt;/p&gt;

&lt;h2&gt;Die VIM, Die! Enter TextMate.&lt;/h2&gt;

&lt;p class=&quot;clearfix&quot;&gt;OK, now I&#39;m going to say it and say it only once. Using &lt;a href=&quot;http://macromates.com/&quot; title=&quot;Code and markup brought into the 21st century.&quot;&gt;TextMate&lt;/a&gt; from the Mac OS X is pure &amp;quot;&lt;a href=&quot;http://agilemanifesto.org/&quot; title=&quot;Agile Software Develeopment Manifesto&quot;&gt;Convention over Configuration&lt;/a&gt;&amp;quot; one of the founding principles of agile software development. I know many don&#39;t like the hype of this methodology, especially when used to discuss Ruby on Rails application development but I think these are the same people that like working harder, not smarter and I&#39;m sure they said the same thing about PHP six years ago and also think &lt;a href=&quot;http://troutgirl.com/blog/index.php?/archives/22_Friendster_goes_PHP.html&quot; title=&quot;JAVA vs. PHP, go discuss it elsewhere!&quot;&gt;JAVA is the only way of programming&lt;/a&gt;. So we can ignore them, I choose to. So here are a few of the marketing reasons  about why I choose TextMate as my editor over BBEdit on the Mac OS.&lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;&lt;img src=&quot;/assets/columns.gif&quot; alt=&quot;Column Typing in TextMate&quot; width=&quot;200&quot; height=&quot;60&quot; class=&quot;floatr ml20&quot; /&gt;&lt;strong&gt;Column Typing&lt;/strong&gt; - I love clean organized code and this image snippet shows that editing clean organized code is really easy in TextMate which keeps you from performing the same change across multiple lines. &lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;&lt;img src=&quot;/assets/foldings.gif&quot; alt=&quot;Collapse Content in TextMate&quot; width=&quot;228&quot; height=&quot;150&quot; class=&quot;floatr ml20&quot; /&gt;&lt;strong&gt;Collapsible Foldings&lt;/strong&gt; - Use these to hide method definitions, class files, tables, DIVs, or any of your markup that you want out of view. I have also found this especially helpful when editing or viewing very large XML files. &lt;em&gt;HINT: You can old down the option button to fully collapse and expand the foldings. Option-collapse to hide everything and then open up the folding like normal and it will easy you in tag by tag. &lt;/em&gt;&lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;&lt;img src=&quot;/assets/syntax.png&quot; alt=&quot;Syntax Highlighting in TextMate&quot; width=&quot;200&quot; height=&quot;135&quot; class=&quot;floatr ml20&quot; /&gt;&lt;strong&gt;Syntax Highlighting&lt;/strong&gt; - Not just for the whole document, but nested markup too. TextMate does this better than any program I&#39;ve seen and it does it really well for a huge amount of different file types, even shell scripts. This task was a huge chore in BBEdit. &lt;em&gt;HINT: When you download TextMate, don&#39;t stop there. &lt;a href=&quot;http://macromates.com/textmate/manual/bundles.html#getting_more_bundles&quot; title=&quot;Get more TextMate bundles with subversion.&quot;&gt;Install Subversion on your system and download the trunk files to get all the bundles.&lt;/a&gt;&lt;/em&gt; This not only gives you more syntax highlighting, but more actions too. &lt;/p&gt;

&lt;p class=&quot;clearfix&quot;&gt;&lt;img src=&quot;/assets/tabs.gif&quot; alt=&quot;Tabbed Files in TextMate&quot; width=&quot;239&quot; height=&quot;49&quot; class=&quot;floatr ml20&quot; /&gt;&lt;strong&gt;Tabbed Navigation &amp;amp; Project Drawers &lt;/strong&gt;- This was another chore in BBEdit and by now most applications are figuring out that tabbed navigation is a must for every program. HINT: &lt;em&gt;One of the things I really like about using the project drawer, which comes up automatically if you drag a folder onto TextMate, is that you can create custom environment variables for the project that talk directly to your shell environment. These could be custom paths, etc. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That&#39;s just a small excerpt from their &lt;a href=&quot;http://macromates.com/&quot; title=&quot;Code and markup brought into the 21st century.&quot;&gt;their website&lt;/a&gt; on why TextMate is so great. There are many more and I have only really started to scratch the surface on using it. Here are a few more that directly relate to how I use it. &lt;/p&gt;&lt;a name=&quot;manpages&quot; class=&quot;anchor&quot;&gt;&lt;/a&gt;


&lt;h2&gt;Man oh Man.&lt;/h2&gt;

&lt;p&gt;TextMate links directly with your shell environment. That means you can run scripts and code directly from the editor. It even has an HTML output window. I am constantly reading the &lt;code&gt;man&lt;/code&gt; pages for all the UNIX software that comes on OS X. Rather than doing this in the shell, I select the command or application name from within TextMate and it pops up the manual page in a nice searchable HTML window. For instance, rather than using &lt;code&gt;man dig&lt;/code&gt; or &lt;code&gt;man rsync&lt;/code&gt; from the terminal, just select it in TextMate and hit Control-H. &lt;/p&gt;

&lt;h2&gt;It&#39;s all Hallow&#39;s Eve&lt;/h2&gt;

&lt;p&gt;What can be cooler than a built in theme called &amp;quot;All Hallow&#39;s Eve&amp;quot;. This theme is the typical black background with high contrast code and markup that you see in many of the screenshots for TextMate. Many VIM&#39;ers loved this setting for legibility and its built right into Textmate. &lt;/p&gt;

&lt;h2&gt;What&#39;s the Difference?&lt;/h2&gt;

&lt;p&gt;Diffs are great and tell you a lot. I really only discovered them because TextMate offers such a simple way of using them. In this example I can show the differences in the configuration of a 2621 Cisco router. This really helps sort things out.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/textmate-diff.gif&quot; alt=&quot;TextMate DIFF Example&quot; width=&quot;539&quot; height=&quot;415&quot; class=&quot;shadow&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Lastly, I would love to hear why some other people have moved to using TextMate or perhaps you may have an example of another editor that is the end all for geeks like us?&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Dec 2005 00:00:00 -0500</pubDate>
        <link>/2005/12/22/textmate-by-programmers-for-efficiency-experts/</link>
        <guid isPermaLink="true">/2005/12/22/textmate-by-programmers-for-efficiency-experts/</guid>
      </item>
    
      <item>
        <title>How To Setup a Simple MySQL Backup Script</title>
        <description>&lt;p&gt;Lately, I&#39;ve been loving all things that can be solved by using &lt;a href=&quot;http://archive.macosxlabs.org/rsyncx/rsyncx.html&quot; title=&quot;Solving Problems With RsyncX&quot;&gt;RsyncX&lt;/a&gt;. It&#39;s my de facto backup utility and I just keep finding more and more tasks for it as each day goes by. It has become the hammer for all my system&#39;s needs. So when it came time for me to implement a nice little backup routine for the MySQL databases hosted here at ActionMoniker.com, it was the first tool I considered. My requirements were simple, I needed a SQL script of selected databases in logically named folders for each DB with time-stamps in the file name. Then step and repeat on a regular basis. &lt;/p&gt;

&lt;p&gt;To use RsyncX for the job, I would have to copy the literal file system for the databases, typically these are located in &lt;code&gt;/usr/local/mysql/data/dbname&lt;/code&gt; on your macintosh file system. Doing such would have been a technically valid method, but this solution would not have given me a portable backup file since RsyncX would copy the directory in whole, which includes separate files for each table in the database. Not to mention permission issues for restoring the files.&lt;/p&gt;

&lt;h2&gt;Perhaps MySQL Administrator?&lt;/h2&gt;

&lt;p&gt; So instead of square pegging RsyncX I turned to the one of the greatest inventions for the Open Source database community, the &lt;a href=&quot;http://dev.mysql.com/downloads/administrator/index.html&quot; title=&quot;Database Administration GUI for OS X MySQL Databases&quot;&gt;MySQL Administrator&lt;/a&gt; application. This wonderful program brings many features of administrating MySQL databases into a nice tidy graphical user interface that most users can understand by simply pointing and clicking around. It is very easy to understand and it is akin to the &quot;Enterprise Manager&quot; for Microsoft SQL Server running on Windows. The things you can accomplished with MySQL Administrator are past the scope of this article, but I do want to point out that MySQL Administrator does offer a manual and automatic backup solution for you by using your Mac&#39;s &quot;user&quot; crontab. If you are unfamiliar with cron, it is your Mac&#39;s (UNIX-Style) built-in job scheduling system. &lt;/p&gt;

&lt;p&gt; If you have ever tried using MySQL Administrator&#39;s backup routine, DO NOT DO IT! The program fails miserably for most users since it uses your local system account, not the DB user account associated with the database you are tying to backup. If you are reading this article because you have tried using MySQL Administrator&#39;s backup system, you may have seen a system message like this: &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;From: kencollins@ken-pb.local (Cron Daemon)
To: kencollins@ken-pb.local
Date: Mon, 19 Dec 2005 23:04:01 -0500 (EST)
Subject: Cron &amp;lt;kencollins@ken-pb&amp;gt; &quot;/Applications/MySQL Administrator.app/Contents/Resources/mabackup&quot; --directory=&quot;/Users/kencollins/Desktop&quot; --connection=&quot;localhost&quot; --prefix=&quot;MetaDB&quot; MetaDB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; Before I get to that simple solution and if you are one of the unlucky that tried backups with MySQL Administrator, let&#39;s digress for a moment and clean up the work it did to your system. First, if you have not already done so, install &lt;a href=&quot;http://webmin.com/&quot; title=&quot;The Swiss Army Knife of Mac OS X Admin Tools&quot;&gt;Webmin&lt;/a&gt; . Many of my tutorials will rely on it. This is a powerful tool that runs as a bundle of PERL modules accessible via a web browser on your local machine. It allows you to administrate many underlying system events and programs on your system. &lt;strong&gt;DISCLAIMER: It can be somewhat hazardous if you are not familiar with what you are doing.&lt;/strong&gt; That said, the documentation on their website has a very straight forward  help file on installing the latest version. Now to the cleanup: &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Step 1&lt;/strong&gt; - removing the MySQL Administrator cron entry. Open Webmin and navigate to &quot;System -&amp;gt; Scheduled Cron Jobs&quot;, directly beside &quot;yourusername&quot; you should see a command similar to the subject line in my example error above. Click on it to edit the job, and hit &quot;delete&quot; at the bottom of the page.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 2&lt;/strong&gt; - removing any junk emails or system notices. Open Webmin and navigate to &quot;Servers -&amp;gt; Read User Mail&quot;, click on your username, then delete any messages similar to the ones above. You should have one message each time MySQL Administrator failed to do what you wanted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Simple Solution&lt;/h2&gt;

&lt;p&gt;OK, now that our system has less junk processes, to the fun part, a simple and working MySQL backup. For this task I created a really simple script. Let&#39;s take a look at it below. &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;date -u +%Y-%m-%d_%a&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
/usr/local/mysql/bin/mysqldump -uXXXX -pXXXX metadb &amp;gt; /Backups/MetaDB_&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are two parts to this script, the first line sets a variable called &quot;timestamp&quot; in the friendliest format I can think of (YYYY-MM-DD_Day), for example 2005-12-19_Mon. The second line of this script uses the mysqldump utility, gives it a username, password, and your database name. Replace XXXX with the username and password of your database and remember, if you are calling this script from a remote machine, it must have remote access to the database name, directly after your password. The last half of the second line writes your database backup file in a directory of your choosing with a filename using the &lt;code&gt;${timestamp}&lt;/code&gt; variable of the system time from line one. In this example, this will generate a file called &quot;MetaDB_2005-12-19_Mon.sql&quot;. &lt;/p&gt;

&lt;p&gt; To run this script, save it to a text file like MyDB-Backup.command or .sh and make it executable. My favorite way of doing this is to use &lt;a href=&quot;http://macromates.com/&quot; title=&quot;The Best Text Editor for the Mac OS X&quot;&gt;TextMate&#39;s&lt;/a&gt; built-in UNIX Shell automation scripts, but if you do not have such a fancy text editor, simple use the Terminal and enter this command on the file &lt;code&gt;chmod +x yourfilename.sh&lt;/code&gt; Lastly, you can schedule this job to run at any interval using the system&#39;s crontab. This can be added using Webmin or by opening up the crontab, located at &lt;code&gt;/etc/crontab&lt;/code&gt; and then follow the example in the header of the file. &lt;/p&gt;
</description>
        <pubDate>Mon, 19 Dec 2005 00:00:00 -0500</pubDate>
        <link>/2005/12/19/how-to-setup-a-simple-mysql-backup-script/</link>
        <guid isPermaLink="true">/2005/12/19/how-to-setup-a-simple-mysql-backup-script/</guid>
      </item>
    
  </channel>
</rss>
