<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>psychedeli.ca</title>
    <description>tubbo's blog about music, hacking and fresh fruit.</description>
    <link>http://www.psychedeli.ca/</link>
    <item>
      <title>introducing active copy</title>
      <pubDate>26 Jan 2014</pubDate>
      <link>http://psychedeli.ca/2014/01/26/introducing-active-copy</link>
      <guid>http://psychedeli.ca/2014/01/26/introducing-active-copy</guid>
      <description>&lt;p&gt;If you&amp;#39;ve ever browsed &lt;a href="https://github.com/tubbo/psychedeli.ca"&gt;the source code&lt;/a&gt; of this blog, you might
have noticed a directory called &lt;strong&gt;lib/active_copy&lt;/strong&gt;. Opening up that
directory is somewhat interesting, as you&amp;#39;ll be able to see exactly how
I take Markdown files with YAML front matter and render them through
ActionView. But unfortunately, unless you fork this repo and hack it to
bits, you were unable to use ActiveCopy in your own Rails projects.&lt;/p&gt;

&lt;p&gt;Until today.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve released &lt;a href="http://rubygems.org/gems/active_copy"&gt;ActiveCopy&lt;/a&gt; to the world as a RubyGem and Rails
plugin. While not mountable, ActiveCopy requires Rails, and especially
ActionView, for all functionality to work properly.&lt;/p&gt;

&lt;h2&gt;so...what is it?&lt;/h2&gt;

&lt;p&gt;ActiveCopy is a replacement for ActiveRecord, but instead of being
backed by a SQL database, it is backed by files which use a specific
kind of markup format. ActiveCopy was born out of the necessity (or
rather, desire) to &amp;quot;wrap &lt;a href="http://jekyllrb.com"&gt;Jekyll&lt;/a&gt; in a &lt;a href="http://rubyonrails.org"&gt;Rails&lt;/a&gt; app&amp;quot;, giving
one the benefits of Jekyll&amp;#39;s static file template compilation and simple
formatting, as well as Rails&amp;#39; deployment and testing toolchain.
Additionally, the use of Rails allows me to experiment a bit with the
features of this site, a prospect that would not be possible (in Ruby,
anyway) with Jekyll.&lt;/p&gt;

&lt;h2&gt;get it working&lt;/h2&gt;

&lt;p&gt;First, add this to Gemfile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;active_copy&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Install the bundle:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle install
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can generate an ActiveCopy model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate copy article name title
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&amp;#39;ll get a free generator that will generate files for you:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate article the-id-of-my-article
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ActiveCopy supports date prefixing, to do so, run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails generate copy article name title --datestamp
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;when you declare the generator for your model.&lt;/p&gt;

&lt;h2&gt;more information&lt;/h2&gt;

&lt;p&gt;You can view &lt;a href="http://rdoc.info/tubbo/active_copy"&gt;the complete documentation&lt;/a&gt; if you wish to get more
involved with how the code works. But the &lt;a href="http://github.com/tubbo/active_copy"&gt;README&lt;/a&gt; on GitHub is
probably what you want to look at, as it contains a complete setup guide
and usage information for the gem.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>irssi? in MY notifications center?</title>
      <pubDate>8 Sep 2013</pubDate>
      <link>http://psychedeli.ca/2013/09/08/irssi-in-my-notifications-center</link>
      <guid>http://psychedeli.ca/2013/09/08/irssi-in-my-notifications-center</guid>
      <description>&lt;p&gt;As I&amp;#39;ve said before, I&amp;#39;m constantly working in &lt;a href="http://zsh.org"&gt;the shell&lt;/a&gt; and have
found &lt;a href="http://github.com/tubbo/dots"&gt;many ways to improve my flow&lt;/a&gt; since I began working
this way. I also like to keep in contact on &lt;a href="http://freenode.org"&gt;IRC&lt;/a&gt; to give out
help on Ruby, JS or Rails (and constantly learn in the process), chat
with friends, or discuss open-source projects. I use &lt;a href="http://irssi.org"&gt;irssi&lt;/a&gt; to
connect to Freenode, a shell client, and I wondered if it would be
possible to get Notifications Center to listen in on my chats and let me
know when I get new messages. Thanks to alloy&amp;#39;s powerful
&lt;a href="http://github.com/alloy/terminal-notifier"&gt;terminal-notifier&lt;/a&gt;, I can!&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;Like I said, I run &lt;a href="http://irssi.org"&gt;irssi&lt;/a&gt; through my own VPS which is running an
&lt;a href="http://irssi.org/documentation/proxy"&gt;irssi-proxy&lt;/a&gt; to keep me connected all the time. This way,
connections to chat are speedy and efficient, and people can contact me
whenever they want...I&amp;#39;ll see it when I get online. I&amp;#39;ve also begun to
wrestle with a project called [bitlbee][bitl] that connects to XMPP
chats, so I can talk with my co-workers with my IRC client...but I
haven&amp;#39;t been able to get that up and running...maybe soon...&lt;/p&gt;

&lt;p&gt;Anyway, this post is about getting Mac OS Notifications for your irssi
mentions and private messages.&lt;/p&gt;

&lt;h2&gt;requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/alloy/terminal-notifier"&gt;terminal-notifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://irssi.org"&gt;irssi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://scripts.irssi.org/html/trigger.pl.html"&gt;trigger.pl&lt;/a&gt;, an irssi script&lt;/li&gt;
&lt;li&gt;Mac OS X 10.7 or greater&lt;/li&gt;
&lt;li&gt;The Homebrew package manager, or you can opt to compile irssi/TN from
source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;installation&lt;/h2&gt;

&lt;p&gt;First, install the necessary packages with Homebrew:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew install irssi terminal-notifier
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make sure your scripts directory is in place:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mkdir -p ~/.irssi/scripts/autorun
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, install the &lt;code&gt;trigger.pl&lt;/code&gt; script to your irssi config directory.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="s1"&gt;&amp;#39;http://scripts.irssi.org/scripts/trigger.pl&amp;#39;&lt;/span&gt; -o ~/.irssi/scripts/autorun/trigger.pl
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can open up irssi and type &lt;code&gt;/LOAD trigger&lt;/code&gt; to enable triggers!&lt;/p&gt;

&lt;p&gt;The triggers I used for building this feature are below. Just change the &lt;code&gt;-regexp&lt;/code&gt; pattern
to your nick instead of &amp;#39;tubbo&amp;#39; to get it working right:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;privmsgs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;exec /usr/local/bin/terminal-notifier -message &amp;quot;$\M&amp;quot; -title &amp;quot;$\N&amp;quot;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;publics&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;regexp&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;tubbo&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;exec /usr/local/bin/terminal-notifier -message &amp;quot;$\M&amp;quot; -title &amp;quot;$\N ($\C)&amp;quot;&amp;#39;&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You should be able to just paste those lines into &lt;code&gt;~/.irssi/triggers&lt;/code&gt; (a
file you create), then run &lt;code&gt;/TRIGGER LOAD&lt;/code&gt; from irssi to get the
triggers working.&lt;/p&gt;

&lt;p&gt;And that should do it! Get one of your friends to &lt;code&gt;/msg&lt;/code&gt; you or say your
name in a channel!&lt;/p&gt;

&lt;h3&gt;one small caveat&lt;/h3&gt;

&lt;p&gt;Currently, all spaces are escaped in the notification. Makes it a bit
harder to read, but it still works. If anyone out there knows of a great
solution, hit me up on Twitter (&lt;a href="http://twitter.com/tubbo"&gt;@tubbo&lt;/a&gt;) and let me know about
it!&lt;/p&gt;
</description>
    </item>
    <item>
      <title>the shape of web uis to come</title>
      <pubDate>30 Aug 2013</pubDate>
      <link>http://psychedeli.ca/2013/08/30/the-shape-of-web-uis-to-come</link>
      <guid>http://psychedeli.ca/2013/08/30/the-shape-of-web-uis-to-come</guid>
      <description>&lt;p&gt;Recently, I&amp;#39;ve been very interested in the development of the
&lt;a href="http://emberjs.com/"&gt;Ember.js&lt;/a&gt; framework, which has grown rapidly in the 3 years or
so that I&amp;#39;ve known it. We&amp;#39;ve seen &lt;a href="http://discourse.com/"&gt;great apps&lt;/a&gt; being made
with (&lt;a href="http://eviltrout.com/2013/03/23/ember-without-data.html"&gt;most of&lt;/a&gt;) it, and it&amp;#39;s gone from something that left
me truly puzzled into an understandable and almost indispensable
tool in my web development arsenal. While developing a Backbone app,
I took a second look at Ember after they released their new
&lt;a href="http://emberjs.com/guides/routing/"&gt;routing API&lt;/a&gt;, and fell in love with how &lt;em&gt;little&lt;/em&gt; code I
wrote while &lt;a href="http://github.com/tubbo/forthcoming"&gt;developing a simple application&lt;/a&gt;. But the way
that Ember worked flies in the face with one of my other favorite
tools...&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This post is written from the perspective of a
&lt;a href="http://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; developer, using &lt;a href="http://github.com/emberjs/ember-rails"&gt;ember-rails&lt;/a&gt; to
generate my content and &lt;a href="http://github.com/rails-api/active_model_serializers"&gt;ActiveModel::Serializers&lt;/a&gt; for constructing
my HTTP API.&lt;/p&gt;

&lt;h2&gt;ember and coffeescript&lt;/h2&gt;

&lt;p&gt;While I have been writing JavaScript for about 14
years as of the date this article was written, I still prefer
CoffeeScript as a DSL for defining my objects. It&amp;#39;s cleaner, easier to
read, and generates compliant JavaScript that (without too many
hang-ups) is very close to or exactly what I would have written by hand
anyway. Unfortunately, some of the unusual conventions in Ember,
especially related to adding computed properties and observers to
methods, make working with CoffeeScript quite difficult. Not to mention
that the &lt;code&gt;class&lt;/code&gt;/&lt;code&gt;extends&lt;/code&gt; keywords do not work reliably in conjunction
with &lt;code&gt;Ember.Object.extend()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;emberscript to the rescue&lt;/h2&gt;

&lt;p&gt;Thankfully, &lt;a href="https://github.com/ghempton"&gt;Gordon Hempton&lt;/a&gt; has created &lt;a href="http://emberscript.com"&gt;EmberScript&lt;/a&gt;,
a CoffeeScript-style languaage that compiles to JavaScript. It is a
subset of CoffeeScript (you can avoid the special syntax altogether and
it compiles to the exact same code as CoffeeScript), but it compiles
directly to JavaScript so you&amp;#39;re not dealing with trans-compiling
issues.&lt;/p&gt;

&lt;p&gt;EmberScript adds a number of syntactical features to CoffeeScript that
make it well-suited for writing Ember apps. For example, in Ember.js
you must retrieve data using &lt;code&gt;Ember.Object.get()&lt;/code&gt; (all Ember objects
are derived from &lt;code&gt;Ember.Object&lt;/code&gt;, by the way):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// wouldn&amp;#39;t really do this, just pseudocode for &amp;quot;runtime&amp;quot;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;firstName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lastName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But in EmberScript, you can write that code like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;
  &lt;span class="nv"&gt;firstName: &lt;/span&gt;&lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;
  &lt;span class="nv"&gt;lastName: &lt;/span&gt;&lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# wouldn&amp;#39;t really do this, just pseudocode for &amp;quot;runtime&amp;quot;&lt;/span&gt;
  &lt;span class="nv"&gt;person = &lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how I used class/extends to describe the model. This is a visible
effect of the fact that EmberScript does not compile to CoffeeScript,
because it defines class/extends in a different way.&lt;/p&gt;

&lt;p&gt;You can do even more with EmberScript. Let&amp;#39;s say I wanted to make the
text in the alert dialog a method on Person, because I wanted to use it
elsewhere. In JavaScript, I&amp;#39;d have to define it this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;firstName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lastName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;firstName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lastName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// alright i guess i don&amp;#39;t have to tell you again..&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;#39;s a &lt;em&gt;little&lt;/em&gt; better, but I feel like we can do a lot more with
less code. It&amp;#39;s a pretty verbose way to say &amp;quot;combine firstName and
lastName in the return value of this method&amp;quot;, we have to specify all of
the &amp;quot;dependencies&amp;quot; of the method at the bottom and then we still have to
use &lt;code&gt;this.get&lt;/code&gt; in order to retrieve the attributes. Once again,
EmberScript comes to the rescue:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;
  &lt;span class="nv"&gt;firstName: &lt;/span&gt;&lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;
  &lt;span class="nv"&gt;lastName: &lt;/span&gt;&lt;span class="nx"&gt;DS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;
  &lt;span class="nv"&gt;name: &lt;/span&gt;&lt;span class="o"&gt;~&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nx"&gt;@firstName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nx"&gt;@lastName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# blah blah apologizing comment&lt;/span&gt;
  &lt;span class="nv"&gt;person = &lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wow, that&amp;#39;s more like it! We define the method just like CoffeeScript,
except with a special &lt;code&gt;~&amp;gt;&lt;/code&gt; operator that defines functions wrapped in
the &lt;code&gt;.property()&lt;/code&gt; method. Also something that&amp;#39;s missing is the
dependencies declared in the arguments to &lt;code&gt;property()&lt;/code&gt;. That&amp;#39;s because
EmberScript automatically defers dependencies for computed properties.
Now that&amp;#39;s what I call progress.&lt;/p&gt;

&lt;p&gt;There&amp;#39;s a lot more you can do. Check out the site for everything. Some
other highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directives for observers (&lt;code&gt;+observer&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;mixin&lt;/code&gt; keyword for defining mixins&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;with&lt;/code&gt; suffix of &lt;code&gt;extends&lt;/code&gt; that allow you to compose your Ember
objects using mixins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my opinion, the combination of Ember.js and EmberScript is already a
major productivity boost. But we can go even further.&lt;/p&gt;

&lt;h2&gt;moving past handlebars&lt;/h2&gt;

&lt;p&gt;Ember uses &lt;a href="http://handlebarsjs.com/"&gt;Handlebars.js&lt;/a&gt; as a templating language for
&amp;quot;sprucing up&amp;quot; your markup. They&amp;#39;re mostly static templates, but they do
have some dynamic qualities like basic conditionals and loops for
visualizing collections of data. Handlebars is great, but much like
&lt;a href="http://ruby-lang.org/"&gt;Ruby&lt;/a&gt; has &lt;a href="http://haml-lang.org/"&gt;Haml&lt;/a&gt;, someone&amp;#39;s gone along and coded a
replacement for Ember called &lt;a href="http://emblemjs.com/"&gt;Emblem.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Emblem is unlike a lot of other templating languages, because it
actually compiles down to Handlebars, which is used as the static
templating language on the client side. Like EmberScript, Emblem is
somewhat of a DSL for writing Ember apps, except Emblem takes care of
the templating layer. Since it compiles to Handlebars, it&amp;#39;s possible to
use both custom Handlebars helpers and the ones you use from a 3rd-party
(or Ember itself).&lt;/p&gt;

&lt;h2&gt;in the wild&lt;/h2&gt;

&lt;p&gt;The best example I can give is the one I&amp;#39;m currently working on, the
official site of [wax poetic records][waxpoetic]. It&amp;#39;s built entirely
with Ember/EmberScript/Emblem.js, with a light backend written in Ruby
on Rails. It also uses the excellent [Zurb Foundation][foundation] CSS
framework, also in use on this blog. Check it out, and if you see
anything wrong, [file an issue][waxpoetic-issues]. I&amp;#39;ve made the
[source code][waxpoetic-source] available on GitHub if you&amp;#39;re interested
in seeing how an app like this can be written.&lt;/p&gt;

&lt;h2&gt;one more thing..&lt;/h2&gt;

&lt;p&gt;I haven&amp;#39;t been able to get EmberScript working with Rails 4, but that&amp;#39;s
a project I&amp;#39;m going to tackle this weekend. Also, it doesn&amp;#39;t seem as
though &lt;code&gt;therubyracer&lt;/code&gt; is supported, so uhh...install Node.js. :)&lt;/p&gt;
</description>
    </item>
    <item>
      <title>pv: a shell interface for pivotal tracker</title>
      <pubDate>29 Mar 2013</pubDate>
      <link>http://psychedeli.ca/2013/03/29/pv-a-shell-interface-for-pivotal-tracker</link>
      <guid>http://psychedeli.ca/2013/03/29/pv-a-shell-interface-for-pivotal-tracker</guid>
      <description>&lt;p&gt;At &lt;a href="http://elocal.com"&gt;eLocal&lt;/a&gt;, we use the lovely &lt;a href="http://pivotaltracker.com"&gt;Pivotal Tracker&lt;/a&gt; to track our
work progress. It has a really great interface for viewing stories, and
some additional features like tasks, rich text comments, and the ability
to &amp;quot;predict&amp;quot; future iterations by using the velocity and &amp;quot;points&amp;quot; system
(which is totally arbitrary). Another great feature is the story states,
which are also arbitrary, but we use them for very specific
purposes...for example, &lt;strong&gt;Delivered&lt;/strong&gt; means the story has been placed on
the stage server and is ready for testing, while &lt;strong&gt;Finished&lt;/strong&gt; just means
that I&amp;#39;ve pushed the code to master branch and it &lt;em&gt;can&lt;/em&gt; be deployed at
any time.&lt;/p&gt;

&lt;p&gt;But enough about our workflow, I want to talk about a tool I wrote that
makes it easier for you to see upcoming stories in a &lt;code&gt;git log&lt;/code&gt;-style
format, totally within the shell...&lt;/p&gt;

&lt;h2&gt;introducing &lt;a href="http://github.com/tubbo/pv"&gt;pv&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://github.com/tubbo/pv"&gt;pv&lt;/a&gt; is a command-line tool that views and edits the Pivotal Tracker
stories that have been assigned to you in the &lt;strong&gt;My Work&lt;/strong&gt; pane. It&amp;#39;s
scoped to just your work, and &lt;code&gt;pv&lt;/code&gt; was definitely designed from the
perspective of developers &lt;em&gt;working on&lt;/em&gt; a project, not project managers
who are managing those developers. My opinion is that Pivotal Tracker&amp;#39;s
UI was designed primarily for people like that, so this shell tool is
simply a different way of seeing that, geared more towards developers
who don&amp;#39;t need to see the scope of the whole project every time they
want to check up on their stories.&lt;/p&gt;

&lt;p&gt;The goal behind &lt;a href="http://github.com/tubbo/pv"&gt;pv&lt;/a&gt; is to mirror the functionality of
&lt;a href="http://pivotaltracker.com"&gt;pivotaltracker.com&lt;/a&gt; in a manner that is suitable for &amp;quot;worker bee&amp;quot;
developers who need only be concerned with their work. We are slowly
working towards that, with a roadmap that includes &lt;strong&gt;commenting&lt;/strong&gt;,
viewing tasks in a nice bulleted list (in &lt;code&gt;pv show&lt;/code&gt;), and more...&lt;/p&gt;

&lt;h2&gt;viewing stories&lt;/h2&gt;

&lt;p&gt;The two most useful features are &lt;code&gt;pv log&lt;/code&gt; (aliased to &lt;code&gt;pv&lt;/code&gt; for
convenience), which shows your entire &amp;quot;My Work&amp;quot; pane:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://i.imgur.com/PtJaGV2.png" alt="pv log"&gt;&lt;/p&gt;

&lt;p&gt;...and &lt;code&gt;pv show $STORY_ID&lt;/code&gt;, which shows more details about a single
Pivotal story:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://i.imgur.com/5VVADzZ.png" alt="pv show"&gt;&lt;/p&gt;

&lt;p&gt;From these two commands, as well as &lt;code&gt;pv open&lt;/code&gt; (which just runs &lt;code&gt;open&lt;/code&gt; on
the story ID you pass in, opening the URL for it in a browser), you can
see practically every aspect of the story from within the shell
environment.&lt;/p&gt;

&lt;h2&gt;editing stories&lt;/h2&gt;

&lt;p&gt;You can also modify stories using &lt;code&gt;pv&lt;/code&gt;. When I combine it with
&lt;a href="http://github.com/stevenharman/git_tracker"&gt;git-tracker&lt;/a&gt;, I don&amp;#39;t really have to ever visit
&lt;a href="http://pivotaltracker.com"&gt;pivotaltracker.com&lt;/a&gt; at any point during my work day, unless I just
&lt;em&gt;want&lt;/em&gt; a better interface, or I need to click links (better to do that
in a web browser than in the shell, IMO). If you want to modify a
story&amp;#39;s state outside of a commit message, pass the state and story ID
to &lt;code&gt;pv&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;pv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;finish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="il"&gt;123456&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can pass any state here, like &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;finish&lt;/code&gt;, &lt;code&gt;deliver&lt;/code&gt;, &lt;code&gt;accept&lt;/code&gt;
and &lt;code&gt;reject&lt;/code&gt;, as the first command to change the state of your story.
However, at this point it&amp;#39;s best to just &lt;code&gt;pv open&lt;/code&gt; the story to change
details like its title, tasks, description, or to leave comments.&lt;/p&gt;

&lt;h2&gt;per-project configuration&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tubbo/pv/blob/master/README.md"&gt;Check out pv&amp;#39;s README&lt;/a&gt; for more information on how to configure,
but basically you can opt to always use the same config in &lt;code&gt;~/.pv&lt;/code&gt;, or
you can place a &lt;code&gt;.pv&lt;/code&gt; file in each of your repos to change the account
or project ID that &lt;code&gt;pv&lt;/code&gt; uses to make API calls.&lt;/p&gt;

&lt;h3&gt;&lt;a href="https://github.com/tubbo/pv/blob/master/README.md#installation"&gt;install that shit&lt;/a&gt; if you want to know more&lt;/h3&gt;
</description>
    </item>
    <item>
      <title>writing jquery plugins with coffeescript</title>
      <pubDate>25 Mar 2013</pubDate>
      <link>http://psychedeli.ca/2013/03/25/writing-jquery-plugins-with-coffeescript</link>
      <guid>http://psychedeli.ca/2013/03/25/writing-jquery-plugins-with-coffeescript</guid>
      <description>&lt;p&gt;At &lt;a href="http://elocal.com"&gt;the job&lt;/a&gt;, we&amp;#39;re constantly trying to improve the UX of
&lt;strong&gt;eLocal.com&lt;/strong&gt; by making the site behave &lt;a href="http://randomaccessmemories.com"&gt;harder, better, faster,
stronger&lt;/a&gt;. For some reason, recently we&amp;#39;ve had a surge in these kind
of feature requests from the &amp;quot;peanut gallery&amp;quot; of sales and operations
staff who are the primary source of feedback for the application. Most
of what I do every day is solving bugs or adding new features to this
big monolithic app, which powers the vast majority of our business. It
is used by the staff on a daily basis to accomplish all sorts of tasks,
from an in-house CRM to an advanced billing system (complete with
recurring charges and invoicing), as well as basic control of our paying
customers&amp;#39; ZIP code ads and lead dissemination.&lt;/p&gt;

&lt;p&gt;Recently, I&amp;#39;ve been trying to codify and refactor the way I write
JavaScript code. Using CoffeeScript has been a major advantage, as it
makes the code much more readable for the way I develop my jQuery
plugins. As a proponent of the &lt;a href="http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/"&gt;object-oriented plugin design
pattern&lt;/a&gt;, CoffeeScript has always been in my radar for doing this
kind of thing, and now that I&amp;#39;ve learned enough about the language I
think it&amp;#39;s now possible to codify how I&amp;#39;ve been writing my JavaScript
code, so the next guy doesn&amp;#39;t have to write as much.&lt;/p&gt;

&lt;h2&gt;how we write our javascript components&lt;/h2&gt;

&lt;p&gt;All of our components are instantiated with the [jQuery][jq] framework.
If you&amp;#39;re dealing with the DOM, there&amp;#39;s just no substitute. jQuery
handles a lot of boilerplate we&amp;#39;d have to build ourselves, and is
cross-browser to boot! The major reason we&amp;#39;re talking about jQuery here,
however, is its minimal plugin architecture.&lt;/p&gt;

&lt;p&gt;A simple jQuery plugin written in CoffeeScript might look like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;jQuery.fn.viewAllButton = &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;@each&lt;/span&gt; &lt;span class="nf"&gt;(i, element) -&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;(event) -&amp;gt;&lt;/span&gt;
      &lt;span class="nv"&gt;container = &lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;button = &lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;button&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;form = &lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;form&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;per_page = &lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;data-per-page&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;input[name=&amp;quot;per_page&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="nx"&gt;per_page&lt;/span&gt;
      &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;input[type=&amp;quot;submit&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty easy to understand. For every element selected by this plugin,
bind a click action that submits the form without its &lt;code&gt;per_page&lt;/code&gt; param
sent over, effectively returning all pages of all content. Most of the
details are just for the specific implementation on eLocal&amp;#39;s admin
system.&lt;/p&gt;

&lt;p&gt;But once plugins become complected to a further degree than this, the
functional model employed by the previous example begins to break down.
Having a lot of functions in your scope (that&amp;#39;s &lt;em&gt;any&lt;/em&gt; scope, not just
the global one) in JavaScript makes your code harder to read, and
eventually harder to debug. It is at this point when jQuery is no longer
enough to write effective, efficient and most of all easy to debug
JavaScript components. You need some bigger guns.&lt;/p&gt;

&lt;p&gt;Thankfully, [CoffeeScript][cs] is here to save the day. CoffeeScript
&amp;quot;fixes&amp;quot; the absolutely disgusting syntax that JavaScript provides to
build objects. If you can imagine trying to stuff OOP into the concept
of a function, you basically got what JavaScript is doing. Using a
relatively common keyword, &lt;code&gt;class&lt;/code&gt;, CoffeeScript gets the job done by
sticking to JavaScript best practices and, at the most simple level,
builds JavaScript object definitions in much the same way that I used to
by hand.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s an example of a CoffeeScript plugin that was built to solve a
simple UX problem when dealing with Rails &lt;code&gt;fields_for&lt;/code&gt; associated forms:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;jQuery.fn.undoFieldsFor = &lt;/span&gt;&lt;span class="nf"&gt;(pluginOptions) -&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;@each&lt;/span&gt; &lt;span class="nf"&gt;(i, element) -&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UndoFieldsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;pluginOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UndoFieldsFor&lt;/span&gt;
  &lt;span class="nv"&gt;defaults:&lt;/span&gt;
    &lt;span class="nv"&gt;form: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;form&amp;#39;&lt;/span&gt;
    &lt;span class="nv"&gt;item: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.line-item&amp;#39;&lt;/span&gt;

  &lt;span class="c1"&gt;# Assign the `&amp;lt;form&amp;gt;` and `&amp;lt;input&amp;gt;` buttons that we&amp;#39;re working with&lt;/span&gt;
  &lt;span class="c1"&gt;# to properly &amp;quot;undo&amp;quot; changes made to the line items in a form.&lt;/span&gt;
  &lt;span class="nv"&gt;constructor: &lt;/span&gt;&lt;span class="nf"&gt;(@element, options) -&amp;gt;&lt;/span&gt;
    &lt;span class="vi"&gt;@options = &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt; &lt;span class="nx"&gt;@defaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;
    &lt;span class="vi"&gt;@form = &lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@item = &lt;/span&gt;&lt;span class="nx"&gt;@element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;@initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;# Bind a removal event onClick &lt;/span&gt;
  &lt;span class="nv"&gt;initialize: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;input[type=checkbox]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;@element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;@removeItem&lt;/span&gt;

  &lt;span class="nv"&gt;removeItem: &lt;/span&gt;&lt;span class="nf"&gt;(event) =&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;@_disableSubmission&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

  &lt;span class="nv"&gt;_disableSubmission: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nv"&gt;submit = &lt;/span&gt;&lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;input[type=&amp;quot;submit&amp;quot;]&amp;#39;&lt;/span&gt;

    &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;
    &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Disabled&amp;quot;&lt;/span&gt;
    &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addClass&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;inactive&amp;quot;&lt;/span&gt;
    &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basically, it replaces the &lt;code&gt;_destroy&lt;/code&gt; checkbox on every additional item
with an &amp;quot;UNDO&amp;quot; button. When this button is clicked, the surrounding
line item element is destroyed and Rails will not submit that data as
part of the form, because it&amp;#39;s no longer on the page. The plugin takes
advantage of the way Rails associations work, as long as you have an
index number higher than that of its previous index, you&amp;#39;re good to go.
So that &lt;code&gt;_destroy&lt;/code&gt; checkbox is really just there for compatibility, as
clients without JavaScript will not be able to take advantage of this
nice feature.&lt;/p&gt;

&lt;p&gt;You can see just in this short example how easy it is to understand a
slightly more complex plugin like &lt;code&gt;undoFieldsFor&lt;/code&gt;. For each selected
item that &lt;code&gt;jQuery.undoFieldsFor()&lt;/code&gt; is applied to, the &lt;code&gt;_destroy&lt;/code&gt;
checkbox is hidden and replaced with an &amp;quot;Undo&amp;quot; button. The click event
on this button (actually an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; link) is bound to a JS action that
destroys the current &lt;code&gt;.line-item&lt;/code&gt; but also disables form submission in
the event that no line items are in the DOM at the time the event is
fired.&lt;/p&gt;

&lt;h2&gt;sumatra tastes exactly how it smells...delicious&lt;/h2&gt;

&lt;p&gt;You can already see a &lt;em&gt;lot&lt;/em&gt; of boilerplate going on in the above
CoffeeScript plugin example. For starters, I always have to do that
little code on line 1 which sets up the jQuery plugin and tells it to
instantiate a helper class every time. Also, because &lt;code&gt;UndoFieldsFor&lt;/code&gt; is
an object, I need to construct it with an &lt;code&gt;$(element)&lt;/code&gt; jQuery object and
the &lt;code&gt;options&lt;/code&gt; hash passed into the plugin at time of instantiation.
Wouldn&amp;#39;t it be sweet if I didn&amp;#39;t have to do this every time? Wouldn&amp;#39;t it
be nice if I could use an interface that allowed practically every part
of the object building process to be customized, but in most
conventional setups, would default to some sane settings that could be
used for quickly writing jQuery plugins in a beautiful way.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s the same plugin implemented using the JavaScript
framework/library I made to codify this technique, [sumatra][sum]:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;sumatra&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;undoFieldsFor&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UndoFieldsFor&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SumatraPlugin&lt;/span&gt;
    &lt;span class="nv"&gt;action: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;
    &lt;span class="nv"&gt;defaults:&lt;/span&gt;
      &lt;span class="nv"&gt;form: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;form&amp;#39;&lt;/span&gt;
      &lt;span class="nv"&gt;item: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.line-item&amp;#39;&lt;/span&gt;

    &lt;span class="c1"&gt;# Set up the &amp;lt;form&amp;gt;, .line-item and submit button we&amp;#39;ll&lt;/span&gt;
    &lt;span class="c1"&gt;# be working with, and hide the checkbox from view.&lt;/span&gt;
    &lt;span class="nv"&gt;initialize: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="vi"&gt;@form = &lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@submit = &lt;/span&gt;&lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;input[type=&amp;quot;submit&amp;quot;]&amp;#39;&lt;/span&gt;
      &lt;span class="vi"&gt;@item = &lt;/span&gt;&lt;span class="nx"&gt;@element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;input[type=checkbox]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Remove the surrounding .line-item&lt;/span&gt;
    &lt;span class="nv"&gt;perform: &lt;/span&gt;&lt;span class="nf"&gt;(event) =&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;@_disableSubmission&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;@_lineItemsExist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# If no more items are left, disable the submit button on this form.&lt;/span&gt;
    &lt;span class="nv"&gt;_disableSubmission: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Disabled&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addClass&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;inactive&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if any line items still exist in the form.&lt;/span&gt;
    &lt;span class="nv"&gt;_lineItemsExist: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By comparing these two bits of code, you can clearly see how we&amp;#39;ve
abstracted some common functionality and increased the readability of
our code. I have yet to find a JavaScript problem that I can&amp;#39;t apply
this solution to. As long as I have to create a new plugin, this always
seems like the best way to do it. Let&amp;#39;s break down what I&amp;#39;m doing here..&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sumatra()&lt;/strong&gt; is a globally-available function that performs that
first line of jQuery from the control example. Since it&amp;#39;s written in
CoffeeScript, this function also returns the object defined on its
last line, which is typically the implementation of the plugin itself.
You can name the plugin here, defining how you will call it via
jQuery, and that code you pass in as a function is called as the body
of the jQuery plugin.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;sumatra&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;undoFieldsFor&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we&amp;#39;re defining a new class which extends from &lt;strong&gt;SumatraPlugin&lt;/strong&gt;.
The object it extends from has some [really awesome time-saving
features][sp], but it is purely optional and has no bearing on the
plugin you actually make.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UndoFieldsFor&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SumatraPlugin&lt;/span&gt;
    &lt;span class="nv"&gt;action: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;
    &lt;span class="nv"&gt;defaults:&lt;/span&gt;
      &lt;span class="nv"&gt;form: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;form&amp;#39;&lt;/span&gt;
      &lt;span class="nv"&gt;item: &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.line-item&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the class itself, we define an &lt;strong&gt;action&lt;/strong&gt; which is the event that
we&amp;#39;re listening for, and when fired will cause &lt;code&gt;perform()&lt;/code&gt; to execute.
This &lt;code&gt;perform()&lt;/code&gt; method is another thing we have to define in the
class itself, as it is the hard-set event handler for the plugin.&lt;/p&gt;

&lt;p&gt;Additionally, Sumatra gives us a place to define default option values
for the &lt;code&gt;options&lt;/code&gt; hash that can be passed into any Sumatra plugin. You
can set up this hash in &lt;code&gt;defaults&lt;/code&gt;, which is merged with the passed in
options to build the public &lt;code&gt;@options&lt;/code&gt; property.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="nv"&gt;initialize: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="vi"&gt;@form = &lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@submit = &lt;/span&gt;&lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;input[type=&amp;quot;submit&amp;quot;]&amp;#39;&lt;/span&gt;
      &lt;span class="vi"&gt;@item = &lt;/span&gt;&lt;span class="nx"&gt;@element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;input[type=checkbox]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While the constructor sets us up with some sane, minimal defaults, the
&lt;code&gt;initialize()&lt;/code&gt; method is for code that would normally go in the
constructor. &lt;strong&gt;It is bad practice to override SumatraPlugin&amp;#39;s
constructor&lt;/strong&gt;, since &lt;code&gt;initialize()&lt;/code&gt; provides everything you need to
get the class support up and running. Here, we&amp;#39;re just caching some
&amp;quot;instance&amp;quot; variables to some other elements that UndoFieldsFor needs to
know about, like the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; surrounding all of this, and the &lt;code&gt;&amp;lt;input
type=&amp;quot;submit&amp;quot;&amp;gt;&lt;/code&gt; button that is used to submit the form. Additionally, we
have the ability to set the item class in case of a conflict, so we also
cache the item property here and delete its corresponding checkbox.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="nv"&gt;perform: &lt;/span&gt;&lt;span class="nf"&gt;(event) =&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;@item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;@_disableSubmission&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;@_lineItemsExist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now it comes time to actually define what this plugin is doing. Notice
that here, unlike the other plugin, it&amp;#39;s much less &amp;quot;baroque&amp;quot;, and
basically defines the control flow of th event handler, instead of its
logic. Using Sumatra directly influenced the design of this plugin,
because now that we have a trusted framework set up to handle all of the
boilerplate crap (that I make EVERY TIME), we can go ahead and abstract
more of, if not all of, the actual logic into methods.&lt;/p&gt;

&lt;p&gt;Since we&amp;#39;ve already defined &lt;code&gt;this.item&lt;/code&gt;, we can just &lt;code&gt;remove()&lt;/code&gt; it as
it&amp;#39;s just a jQuery DOM object. And the line above that, preventing the
event from bubbling up and firing the default browser action, is also
standard for plugin/event authoring. That leaves us with the two custom
private methods, &lt;code&gt;this._disableSubmission()&lt;/code&gt; and
&lt;code&gt;this._lineItemsExist()&lt;/code&gt;. As you can see, we denote private methods with
a preceding &lt;code&gt;_&lt;/code&gt; in the method name. &lt;strong&gt;There are no private methods in
JavaScript&lt;/strong&gt;, so this convention is how we solve for that. Note that the
distinction between public and private is purely semantic, and has no
bearing on the logic of the code. They&amp;#39;re to show &lt;em&gt;you&lt;/em&gt; that the
methods were not written to be called externally on this object.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s take a look at &lt;strong&gt;_disableSubmission()&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="nv"&gt;_disableSubmission: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Disabled&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addClass&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;inactive&amp;quot;&lt;/span&gt;
      &lt;span class="nx"&gt;@submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We already know about &lt;code&gt;this.submit&lt;/code&gt; because it was saved up in the
initialize method. So basically, all this method does is disable
submission until a new line item is added. But this method is only
called when another method returns, true:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="nv"&gt;_lineItemsExist: &lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;@options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&amp;#39;s a method that offers no real code line reduction, but increases
readability and visibility in the &lt;code&gt;perform()&lt;/code&gt; method. This is the kind
of thing that Sumatra makes it easy for you to do, add methods that
increase readability and should enable a higher understanding of the
code out of its readers.&lt;/p&gt;

&lt;h2&gt;doing it yourself because you&amp;#39;re hardcore&lt;/h2&gt;

&lt;p&gt;Sumatra is &lt;a href="https://github.com/tubbo/sumatra/blob/master/pkg/sumatra.coffee"&gt;121 lines of
CoffeeScript&lt;/a&gt;
and its concepts aren&amp;#39;t very hard to implement from scratch in the first
place. Realistically, the most complex part is the &lt;code&gt;sumatra()&lt;/code&gt; function,
which uses a bit of meta-programming to get the job done and allow you
to choose any class name as your service object. Other than that, I&amp;#39;m
just giving you an &amp;quot;interface&amp;quot; prototype object to build your plugin off
of, with &lt;em&gt;very&lt;/em&gt; limited resources. This keeps the codebase light and
easy to read, and lets you take care of the important things.&lt;/p&gt;

&lt;h2&gt;when you SHOULDN&amp;#39;T use sumatra&lt;/h2&gt;

&lt;p&gt;Sumatra&amp;#39;s great for small jQuery plugins, but doesn&amp;#39;t offer much more
than traditional jQuery for building and organizing huge,
JavaScript-centric applications. For that, you should use a more
complete framework like [Ember][ejs], [Backbone][bjs], or
[Angular][ajs], which provide more support and an MVC style for
designing your code base for both efficiency and readability. Sumatra is
best used as an addendum to mostly-HTML apps which desire little
bits of Ajax functionality or fun animations.&lt;/p&gt;

&lt;h2&gt;check it out!&lt;/h2&gt;

&lt;p&gt;I&amp;#39;m interested to hear what others think of this, and I always at least
read over any contribution made by pull request to
&lt;a href="http://github.com/tubbo/sumatra"&gt;http://github.com/tubbo/sumatra&lt;/a&gt;. That&amp;#39;s where the codebase for Sumatra
is stored. To install it, you can use [bower][bwr]:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;bower&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;sumatra&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or, you can use the handy-dandy [sumatra-rails][smr] gem that I made to
use Sumatra within Rails&amp;#39; &amp;quot;asset pipeline&amp;quot;. For efficiency and
consistency, each Sumatra package pushed to Bower is correspondingly
pushed to &lt;strong&gt;sumatra-rails&lt;/strong&gt;, so simply by updating your Gemfile you can
start using the latest edition of Sumatra:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sumatra-rails&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/tubbo/sumatra"&gt;http://github.com/tubbo/sumatra&lt;/a&gt; is where the basic JS/CS is located&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/tubbo/sumatra-rails"&gt;http://github.com/tubbo/sumatra-rails&lt;/a&gt; is where you can find the
Rails helper engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this was at the very least entertaining, and at best helped you
learn a little more about the way we do things here at &lt;strong&gt;eLocal&lt;/strong&gt;. A
short disclaimer: we do not use &lt;code&gt;sumatra&lt;/code&gt; in production (yet!), but I
thought it&amp;#39;d be a great way to show you guys our conventions as
&lt;code&gt;sumatra&lt;/code&gt; is somewhat of a codification of those techniques.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>a case for scopes</title>
      <pubDate>8 Mar 2013</pubDate>
      <link>http://psychedeli.ca/2013/03/08/a-case-for-scopes</link>
      <guid>http://psychedeli.ca/2013/03/08/a-case-for-scopes</guid>
      <description>&lt;p&gt;There has been a lot of hate towards &lt;a href="http://guides.rubyonrails.org/active_record_querying.html#scopes"&gt;scopes&lt;/a&gt; recently. I&amp;#39;m here
to tell you that scopes aren&amp;#39;t all bad, and they can be used to create
some astonishingly elegant model definitions.&lt;/p&gt;

&lt;p&gt;Consider the following bit of code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Events fired by Sendgrid that tell us more information about Messages&lt;/span&gt;
&lt;span class="c1"&gt;# we send out on a daily basis. We only respond to a number of&lt;/span&gt;
&lt;span class="c1"&gt;# +EVENT_TYPES+, but they tend to tell us everything we need to know&lt;/span&gt;
&lt;span class="c1"&gt;# about the messages sent out at this time.&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageEvent&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;# The types of Sendgrid events we will be responding to. We are mostly&lt;/span&gt;
  &lt;span class="c1"&gt;# saving events that tell us when a problem has occurred with message&lt;/span&gt;
  &lt;span class="c1"&gt;# delivery, but we do have a &amp;#39;delivered&amp;#39; event in there so we can keep&lt;/span&gt;
  &lt;span class="c1"&gt;# track of sunny-day message delivery. +View source+ below to see the&lt;/span&gt;
  &lt;span class="c1"&gt;# events we&amp;#39;re tracking.&lt;/span&gt;
  &lt;span class="no"&gt;EVENT_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(bounce delivered dropped spamreport unsubscribe)&lt;/span&gt;

  &lt;span class="c1"&gt;# &amp;#39;Bad&amp;#39; events trigger a red message icon on the front-end. The&lt;/span&gt;
  &lt;span class="c1"&gt;# bad events include when a message bounced, was dropped, the user&lt;/span&gt;
  &lt;span class="c1"&gt;# unsubscribed to the list, or they marked the message as spam.&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Only one recipient has to mark a message as &amp;#39;bad&amp;#39; in some way&lt;/span&gt;
  &lt;span class="c1"&gt;# for it to be considered bad by the system.&lt;/span&gt;
  &lt;span class="no"&gt;BAD_EVENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(bounce dropped spamreport unsubscribe)&lt;/span&gt;

  &lt;span class="c1"&gt;# &amp;#39;Good&amp;#39; events trigger a green message icon on the front-end, and&lt;/span&gt;
  &lt;span class="c1"&gt;# a message is considered good when all recipients fire back with&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;#39;delivered&amp;#39; events.&lt;/span&gt;
  &lt;span class="no"&gt;GOOD_EVENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(delivered)&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;inclusion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;EVENT_TYPES&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:recent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;created_at DESC&amp;#39;&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:bad&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="ss"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;BAD_EVENTS&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:good&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="ss"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;GOOD_EVENTS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, this is a relatively clear model definition. It only
consists of code pertaining to the data model, or configuring the
validations made just before insertion into a database. We have a number
of constants defined, as well as some scopes...but no class methods.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve avoided these for a reason. &lt;strong&gt;I don&amp;#39;t like the way they look.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now this is an obviously stupid reason to cut out code that makes
your code more understandable in the long run, and if it&amp;#39;s a case
where you&amp;#39;re sliming in lambdas and trying to make your code look
&amp;quot;pretty&amp;quot; even though it&amp;#39;s surrounded by a million formal brackets,
you&amp;#39;re probably not using scopes correctly. But as you can see
above, writing those definitions in any other way is not only
way more verbose than it needs to be, but is unnecessarily adding
lines and decreasing readability usually for the sake of some other
purpose.&lt;/p&gt;

&lt;p&gt;Typically, people who preach against the use of scopes tell me that
scopes rob you of the ability to document methods. Let&amp;#39;s look at the
model if I used class methods, and give them some extra documentation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Events fired by Sendgrid that tell us more information about Messages&lt;/span&gt;
&lt;span class="c1"&gt;# we send out on a daily basis. We only respond to a number of&lt;/span&gt;
&lt;span class="c1"&gt;# +EVENT_TYPES+, but they tend to tell us everything we need to know&lt;/span&gt;
&lt;span class="c1"&gt;# about the messages sent out at this time.&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageEvent&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;# The types of Sendgrid events we will be responding to. We are mostly&lt;/span&gt;
  &lt;span class="c1"&gt;# saving events that tell us when a problem has occurred with message&lt;/span&gt;
  &lt;span class="c1"&gt;# delivery, but we do have a &amp;#39;delivered&amp;#39; event in there so we can keep&lt;/span&gt;
  &lt;span class="c1"&gt;# track of sunny-day message delivery. +View source+ below to see the&lt;/span&gt;
  &lt;span class="c1"&gt;# events we&amp;#39;re tracking.&lt;/span&gt;
  &lt;span class="no"&gt;EVENT_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(bounce delivered dropped spamreport unsubscribe)&lt;/span&gt;

  &lt;span class="c1"&gt;# &amp;#39;Bad&amp;#39; events trigger a red message icon on the front-end. The&lt;/span&gt;
  &lt;span class="c1"&gt;# bad events include when a message bounced, was dropped, the user&lt;/span&gt;
  &lt;span class="c1"&gt;# unsubscribed to the list, or they marked the message as spam.&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Only one recipient has to mark a message as &amp;#39;bad&amp;#39; in some way&lt;/span&gt;
  &lt;span class="c1"&gt;# for it to be considered bad by the system.&lt;/span&gt;
  &lt;span class="no"&gt;BAD_EVENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(bounce delivered dropped spamreport unsubscribe)&lt;/span&gt;

  &lt;span class="c1"&gt;# &amp;#39;Good&amp;#39; events trigger a green message icon on the front-end, and&lt;/span&gt;
  &lt;span class="c1"&gt;# a message is considered good when all recipients fire back with&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;#39;delivered&amp;#39; events.&lt;/span&gt;
  &lt;span class="no"&gt;GOOD_EVENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w(delivered)&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;inclusion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;EVENT_TYPES&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# Order events by the date they were received.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recent&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;created_at DESC&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Find all events where the &amp;#39;event&amp;#39; is included in +BAD_EVENTS+.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bad&lt;/span&gt;
    &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="ss"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;BAD_EVENTS&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Find all events where the &amp;#39;event&amp;#39; is included in +GOOD_EVENTS+.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;good&lt;/span&gt;
    &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="ss"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;GOOD_EVENTS&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My belief is in this class, I&amp;#39;ve added about 9 lines of useless code
and useless documentation. As you can see, I&amp;#39;ve clearly documented
the constants &lt;code&gt;EVENT_TYPES&lt;/code&gt;, &lt;code&gt;BAD_EVENTS&lt;/code&gt; and &lt;code&gt;GOOD_EVENTS&lt;/code&gt;, because
this is what data really matters. As we&amp;#39;re in a Rails 3 ActiveRecord
environment for this case, it&amp;#39;s pretty common to chain scopes together
to form larger queries when you need them, and so far nothing functionally
has changed with this example. But my point here is I&amp;#39;ve added about 9
lines and that really hasn&amp;#39;t improved the readability of my model.&lt;/p&gt;

&lt;p&gt;In fact, I argue that it has &lt;em&gt;decreased&lt;/em&gt; the readability in this case.
When I had my scopes set up, it was 3 lines and with the exception of
the lambda surrounding each query clause, there was not a single bit
of &amp;quot;baroque&amp;quot; code (e.g., syntax that has nothing to do with readability,
but is necessary for the compiler to understand what&amp;#39;s going on). Given
you&amp;#39;re a reader of the source code, as most professional Ruby developers
tend to be, you&amp;#39;d see the scopes clearly laid out and &lt;em&gt;most&lt;/em&gt; likely if
you needed them, they&amp;#39;d be easy to understand. The documentation for
the scope sort-of &amp;quot;writes itself&amp;quot;, in this case, so there&amp;#39;s really no
need to over-document those class methods which hopefully won&amp;#39;t be used
by most people outside of the class.&lt;/p&gt;

&lt;p&gt;As &lt;code&gt;MessageEvent&lt;/code&gt; is a support model for &lt;code&gt;Message&lt;/code&gt;, we&amp;#39;re assuming that
most interaction with events comes through the Messages interface, and
since there&amp;#39;s no need to design a crazy search system for events at
this time (hopefully ever), I&amp;#39;m pretty confident that the &amp;quot;scope&amp;quot; (hah!)
of this particular problem won&amp;#39;t be changing anytime soon.&lt;/p&gt;

&lt;p&gt;So just to wrap it up, I feel confident that those 3 lines of &lt;code&gt;scope&lt;/code&gt;
macros are just as effective as writing the methods as actual class methods,
and furthermore, increases the readability of the entire class definition.
This does come at the expense of lacking documentation for methods that
are public and &lt;em&gt;do&lt;/em&gt; exist on your class (breaking some rule I&amp;#39;m sure), but
my arguement is that this is not always needed.&lt;/p&gt;

&lt;p&gt;Use your own judgement. If you feel like your scope is getting too complex,
or you&amp;#39;re writing a scope with the express purpose of having others/yourself
use it outside of the domain of this model (or its original design), you
might want to give yourself the freedom of documenting it further by
turning it into a class method. Regardless, it&amp;#39;s up to you, and I&amp;#39;m glad
that Rails gives me the option to make my code more elegant, because it has
caused me to attempt to simplify my design patterns and streamline my
model definitions to only deal with the data model itself.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>don't make this simple mistake...</title>
      <pubDate>1 Mar 2013</pubDate>
      <link>http://psychedeli.ca/2013/03/01/dont-make-this-simple-mistake</link>
      <guid>http://psychedeli.ca/2013/03/01/dont-make-this-simple-mistake</guid>
      <description>&lt;h2&gt;install bundler-1.3 before installing Ruby 2.0!&lt;/h2&gt;

&lt;p&gt;So as the Ruby community has been unanimously updating to version 2.0
in the past few weeks, I decided to check out some of the newest goodies
available to us developers now that stable versions of Ruby, Rails,
RubyGems and Bundler are all available.&lt;/p&gt;

&lt;p&gt;If you, like me, are installing this through &lt;code&gt;ruby-build&lt;/code&gt;, be aware that
&lt;strong&gt;ruby-build will not install or update Bundler for you!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is somewhat problematic because Bundler (if it&amp;#39;s installed) &lt;em&gt;has&lt;/em&gt; to
be version 1.3 or above for RubyGems to install. Otherwise, you&amp;#39;ll get this
when you try to run any RubyGem (after installing through Bundler which actually
works fine)..&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;There&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Gemfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Bundler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;continue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Go try and install Bundler. Don&amp;#39;t worry, I&amp;#39;ll wait:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="err"&gt;♬&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bundler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="vg"&gt;pre&lt;/span&gt;
&lt;span class="nl"&gt;Fetching:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bundler&lt;/span&gt;&lt;span class="mf"&gt;-1.3.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="il"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;While&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;executing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Gem:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;Package:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="vg"&gt;PathError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="vg"&gt;installing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;necromancer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;Sites&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;elocal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;bundler&lt;/span&gt;&lt;span class="mf"&gt;-1.3.0&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="vg"&gt;gitignore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;bundler&lt;/span&gt;&lt;span class="mf"&gt;-1.3.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;allowed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will now happen for every RubyGem you try to install.&lt;/p&gt;

&lt;h2&gt;the fix&lt;/h2&gt;

&lt;p&gt;What you need to do here is clear out the .ruby-version file so your app
isn&amp;#39;t running off Ruby 2.0 anymore, then install Bundler 1.3 using
RubyGems 1.8. Or, you could just downgrade RubyGems to 1.8 by doing&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="vg"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.8.25&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That should downgrade RubyGems to a point that you can just do a
&lt;code&gt;gem install bundler&lt;/code&gt; to obtain 1.3. Once you begin installing gems
with 1.3, everything in Ruby 2.0 will work out again.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>why garage is growing</title>
      <pubDate>21 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/21/why-garage-is-growing</link>
      <guid>http://psychedeli.ca/2013/02/21/why-garage-is-growing</guid>
      <description>&lt;p&gt;This began as a response on Facebook to &lt;a href="http://twitter.com/Carbon43"&gt;a friend of mine&lt;/a&gt; and I
felt like more people should know my thoughts on why UK Garage is more
respected now as a genre than it ever was before. I&amp;#39;m not an expert
on UKG, but I&amp;#39;ve been listening to it for the past 3-4 years (and before
that even, I just didn&amp;#39;t know it yet..) and been noticing some exciting
changes in its projected legitimacy and adoption.&lt;/p&gt;

&lt;h2&gt;how i discovered garage&lt;/h2&gt;

&lt;p&gt;Being a DJ at the time, I was first turned on to UKG by Todd &amp;quot;The God&amp;quot;
Edwards with his remix of &lt;a href="http://www.youtube.com/watch?v=92aJ3hb4VMU"&gt;St. Germain - Alabama Blues&lt;/a&gt;. Not only
is it still one of my favorite UKG tracks, it&amp;#39;s also one of my favorite
&lt;em&gt;dance&lt;/em&gt; music tracks, period. It still gets me moving and shaking and
a lot of my best produced music has been influenced, directly, by the
sounds and production values I first heard in that tune.&lt;/p&gt;

&lt;p&gt;So that was a UKG song, but it was played in a &lt;a href="https://www.youtube.com/watch?v=Ezx0oivE9gg"&gt;Daft Punk set&lt;/a&gt;, so
I wasn&amp;#39;t aware that it was Garage. Not only that, but pretty much any
DJ I played the tune for didn&amp;#39;t know it existed &lt;em&gt;and&lt;/em&gt; loved the song
very much. This begged a fascinating question: &lt;strong&gt;Why didn&amp;#39;t UK Garage
take off in the late 90s?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that I&amp;#39;ve studied UK Garage, Dubstep and House music a little more
thoroughly, I have a few suggestions for why this phenomenon occurred.&lt;/p&gt;

&lt;h2&gt;why we woke up&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;People finally realized how intricate and awesome the genre was, and
grew bored with the repetitive nature of most dance music, instead
taking some of the best parts of House, Jungle &amp;amp; Breaks and combining
them into a single, funky idiom.&lt;/li&gt;
&lt;li&gt;It has the same vibe as deep house, lots of vocals/pianos/melody with
little if any aggression. So it works in a deep house set. A lot of
the time it&amp;#39;s almost impossible to tell deep house from UK Garage,
but also...&lt;/li&gt;
&lt;li&gt;It has the same vibe as tech house. With all those tuned and filtered
drums, Garage works in a Techno or Tech House set, given the correct
tracks.&lt;/li&gt;
&lt;li&gt;Now that Dubstep is a big-room sound, House needs to compete. UKG was
originally designed as a means for House/Techno producers to compete
with what was then the new sound in EDM: Hardcore and Jungle. So that&amp;#39;s
where UKG gets its speed and &amp;quot;oldskool hardcore&amp;quot; sensibilities from:
a desire for House to remain relevant with those listening to Jungle.
It&amp;#39;s sort-of come around again, except &amp;quot;This Time It&amp;#39;s Dubstep!&amp;quot; Now,
we&amp;#39;re actually speeding up House to slow it down. Since 140 is the
average Dubstep tempo, UKG works in a Dubstep set.&lt;/li&gt;
&lt;li&gt;Artists like &lt;a href="https://soundcloud.com/mj-cole"&gt;MJ Cole&lt;/a&gt;, &lt;a href="https://soundcloud.com/submerse"&gt;Submerse&lt;/a&gt; and &lt;a href="http://www.djqmusic.com/"&gt;DJ Q&lt;/a&gt; have been
releasing new UKG music that sounds an order of magnitude better, from
a technical perspective, than anything that had ever come before it.
The UK Garage from the old days sounds...well...old! Even though some
of those classics from &lt;a href="https://www.facebook.com/NiceNRipe"&gt;Nice &amp;#39;N Ripe&lt;/a&gt; and &lt;a href="http://icecreamrecords.co.uk/"&gt;Ice Cream&lt;/a&gt; were
and are still absolute smash hits, there&amp;#39;s just no way you can play
&amp;quot;Hurt You So &amp;#39;99&amp;quot; in a club these days without catching &lt;em&gt;some&lt;/em&gt; flack.
So &amp;quot;big ups&amp;quot; to MJ, Submerse, Q and &lt;a href="http://silencenogood.net/disclosure-uk-garage/"&gt;Disclosure&lt;/a&gt; for really showing
the &amp;quot;vast unwashed&amp;quot; that UK Garage is alive, well, and most of all,
still has a &lt;em&gt;lot&lt;/em&gt; to do!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The artists I mentioned above, as well as pretty much anyone who&amp;#39;s been
rocking the Juno Download UKG/UK Funky section have been sacrificing a lot
by continuing in a genre that was &lt;a href="https://en.wikipedia.org/wiki/Ishkur&amp;#x27;s_Guide_to_Electronic_Music"&gt;famously dissed on one of the most
popular ways to learn about electronic music&lt;/a&gt;, and definitely not
given the respect it deserves.&lt;/p&gt;

&lt;h2&gt;the merits of uk garage...for another time&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ll go into further detail on why I believe UK Garage is going to
eventually, if it hasn&amp;#39;t already in some diversion, usurp House and
Techno as the world&amp;#39;s most popular genres of dance music. I believe that
UK Garage has a lot going for it: almost universal adoption potential,
great quality tracks, and a tight-knit community from East London
complete with its own slang, events and culture. This is all working to
make UKG into something huge, something a lot bigger than what we&amp;#39;re
all observing right now...&lt;/p&gt;

&lt;p&gt;But that&amp;#39;s for a later post :)&lt;/p&gt;
</description>
    </item>
    <item>
      <title>minitest is still wonderful</title>
      <pubDate>15 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/15/minitest-is-still-wonderful</link>
      <guid>http://psychedeli.ca/2013/02/15/minitest-is-still-wonderful</guid>
      <description>&lt;p&gt;So after posting my &lt;a href="http://www.psychedeli.ca/2013/02/08/use-assertions-in-rspec"&gt;article on how to use assertions in rspec&lt;/a&gt;, I
was involved in a discussion with &lt;a href="https://twitter.com/cheapRoc"&gt;@cheapRoc&lt;/a&gt; over the discovery
that indeed assertions do work within the context of RSpec. To my
surprise, it seemed &lt;a href="https://twitter.com/seattlerb"&gt;@seattlerb&lt;/a&gt; was following at least one of us
and overheard our conversation, mistaking &lt;a href="https://twitter.com/tubbo/status/302147170251993089"&gt;my quite hyperbolic statement&lt;/a&gt;
for a diss on Minitest.&lt;/p&gt;

&lt;p&gt;This was not the case. I still love and use Minitest every day.
&lt;a href="https://github.com/tubbo/psychedeli.ca/tree/master/test"&gt;This blog is tested using Minitest&lt;/a&gt;, and we use Minitest at work
to run a giant test suite that takes over a half-hour to complete
(&lt;em&gt;without&lt;/em&gt; the smoke tests!). What has happened here is a colossal
misunderstanding on my part about what Minitest actually is. Basically,
I was under the impression that Test::Unit had been totally and
unabashedly replaced by Minitest when Ruby 1.9 was released. While
the Test::Unit class names and assertions remained the same, (as
they had in Minitest which was concieved of as a drop-in replacement
for the slower Test::Unit in Ruby 1.8), it seems that Ruby 1.9&amp;#39;s
&lt;a href="https://twitter.com/seattlerb/status/302206878392401920"&gt;Test::Unit is inspired by, but not exactly Minitest&lt;/a&gt;. From what
&lt;a href="https://twitter.com/seattlerb"&gt;@seattlerb&lt;/a&gt; is saying, it seems as though Test::Unit needed
to mostly stay compatible with existant Ruby 1.8 programs and so the
new Test::Unit was developed to address the problems of the older
version, and as a side effect introduced new inconsistencies and
problems when migrating between Test::Unit and Minitest.&lt;/p&gt;

&lt;p&gt;My blog post was geared towards people who want to make Minitest look
just like RSpec, and behave in the same ways, solely because they prefer
the syntax of Minitest to the syntax of RSpec. There are definitely
times where assertions just make more sense, visually, than matchers.
Basically, I don&amp;#39;t believe there&amp;#39;s a reason to toil with juggling 5
different gems that make your assertion-based testing framework behave
just like RSpec. RSpec is a complete package, you install it and it
runs with sensible defaults that make your tests look good and easy
to read.&lt;/p&gt;

&lt;p&gt;At the same time, it&amp;#39;s good to know that tools such as Minitest are
there for when you don&amp;#39;t need all of that extra fluff in your tests.
Maybe you&amp;#39;re just testing a little shell-script that you wrote in
Ruby and you could practically use Test::Unit if you so desired,
but maybe you have the ability to load in extra gems so Minitest
would definitely improve your life.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>lowest common denominator</title>
      <pubDate>14 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/14/lowest-common-denominator</link>
      <guid>http://psychedeli.ca/2013/02/14/lowest-common-denominator</guid>
      <description>&lt;p&gt;We hear a lot of talk by musicians and other &amp;quot;insiders&amp;quot; (who are mostly
either aficionados or amateur musicians who aren&amp;#39;t doing this kind of
thing full-time. I would be included in this list) about entropy in our
musical lexicon. We hear talk about DJs not spinning vinyl anymore,
thereby making DJing even easier than it once was (and more reliable).
We hear about DJs not constructing their set in the same way as they
used to, with less variation and care taken to the actual sound levels.
The fact that there are people who are paid more money in an hour than
most of us are paid in a day, and they aren&amp;#39;t even really making sure
they don&amp;#39;t redline the mixer (which actually &lt;em&gt;can&lt;/em&gt; cause damage, I&amp;#39;ve
seen it in real life!) or take care to not ruin their fans&amp;#39; ears, is
both sad and hilarious at the same time. After all, your fans aren&amp;#39;t
going to buy your music anymore if they can&amp;#39;t hear it...&lt;/p&gt;

&lt;p&gt;Anyway, I&amp;#39;m off track. This post is supposed to be positive, to show
the average &lt;a href="http://www.merriam-webster.com/dictionary/gormandizer"&gt;gormandizer&lt;/a&gt; that there isn&amp;#39;t some big conspiracy
going on and the electronic music community &lt;em&gt;needs&lt;/em&gt; people like
Skrillex, Deadmau5, and even Tiesto to further its stranglehold on
our eardrums. Even though these guys might be less skilled than
others who get paid/credited for less, we need them as &amp;quot;evangelists&amp;quot;
of our community. Basically, I&amp;#39;m telling you not to &lt;a href="https://en.wikipedia.org/wiki/The_Emperor&amp;#x27;s_New_Clothes"&gt;tell the emperor
that he&amp;#39;s not wearing clothes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;musical reaganomics&lt;/h2&gt;

&lt;p&gt;Reagan proposed the &amp;quot;&lt;a href="http://en.wikipedia.org/wiki/Trickle-down_economics"&gt;trickle-down theory&lt;/a&gt;&amp;quot; of economics, to the
instantaneous praise of many white-haired, over-privileged WASP-like
creatures in Congress, and the idea came into America&amp;#39;s lexicon just
as quickly. While the jury&amp;#39;s still out on whether it worked for
America, the trickle-down theory of economics has definitely made
itself known in the music community, as well as most other forms of
mass media. Here&amp;#39;s a quick example..&lt;/p&gt;

&lt;p&gt;Before Deadmau5 and Skrillex toured the US and spread the &amp;quot;gospel&amp;quot; of
electronic music to middle-america kids, it was really difficult to
get anyone to respond to &lt;a href="http://thewonderbars.com"&gt;The Wonder Bars&lt;/a&gt;&amp;#39; music. Nobody really
knew what to make of it, and it didn&amp;#39;t really help that the only places
you could hear it were dirty warehouses or small clubs at the time. I
understand that even before my college years (where I was introduced
to House music and began composing it), it was much more difficult to
find quality house music. But that changed after Deadmau5 played the
Electric Factory in Philly. It took a couple years, but now we&amp;#39;re
seeing an absolute explosion in just about everything that has to do
with EDM...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There have been 3, count &amp;#39;em!, THREE new venues in the last 2 years
alone that have produced a purely electronic bill every night they&amp;#39;re
open. This is proof that even in the hardest city to musically make it in
America, you can &lt;em&gt;still&lt;/em&gt; turn a profit by booking electronic acts.&lt;/li&gt;
&lt;li&gt;Attendance at PEX parties has increased exponentially every year.
HeartBurn was cancelled this year for the first time in its history
because a suitable venue could not be found in time.&lt;/li&gt;
&lt;li&gt;If you have a crew of DJs in Philly and a warehouse you have instant
success. Period. There&amp;#39;s such a small scene here that those of us
who just love that warehouse vibe are forced to go out and hear music
like Trap and ratchet-y Dubstep that we may not go out to hear
on our own. This is actually a really good thing, because it forces
people out of their comfort zone(s) and into new musical territory,
which effectively increases our overall comprehension levels for
different sounds and types of music.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;conclusions&lt;/h2&gt;

&lt;p&gt;So I like Skrillex. I appreciate Deadmau5, even though I think his music
is boring. I like them because they benefit me, by Skrillex existing
and turning on new audiences to EDM, the &amp;quot;trickle-down&amp;quot; of House-heads
that will inevitably discover the music and be drawn into the love
of House increases. It&amp;#39;s a numbers game, and while the probability is
most likely fractions of a percent, multiplying that by 10,000 or even
100,000 people is still a significant fanbase by default. As a concrete
example, take a look at my friends &lt;a href="http://cousinbrian.bandcamp.com"&gt;Cousin Brian&lt;/a&gt;, who are playing
shows all the time in other cities like Richmond, Washington DC and
Baltimore, but had trouble finding shows larger than a house basement
in Philly. I think they have a big enough name now that they don&amp;#39;t
have this problem as much as when they started, but compare them
with &lt;a href="https://soundcloud.com/jackdeezl"&gt;Jack Deezl&lt;/a&gt; who has literally played the biggest all-ages
electronic venue in Philly, and if I&amp;#39;m not mistaken has been producing
and performing music for a much shorter time frame than Cousin
Brian has. I think this is significant, because even though there was
much less &amp;quot;prep&amp;quot; work that Jack had/has to do to get on stage and
play his tunes, the fan base that Jack was tapping into is by default
larger than the punk community in Philly, and while Cousin Brian is
certainly doing wilder, weirder things with the genre (who the hell
plays punk with 9th chords?? amazing!), Jack is going to have an
easier time promoting himself because a lot of the groundwork
has been done for him by the scene that came before.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>give me my assert_response back!</title>
      <pubDate>11 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/11/give-me-my-assert-response-back</link>
      <guid>http://psychedeli.ca/2013/02/11/give-me-my-assert-response-back</guid>
      <description>&lt;p&gt;Did you &lt;a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/AFBKNY7VSH8"&gt;just upgrade Ruby on Rails&lt;/a&gt; and now all of your &lt;code&gt;assert_response()&lt;/code&gt;
tests are failing? Simply add the following code to &lt;strong&gt;test/test_helper.rb&lt;/strong&gt;
and everything will work again!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="no"&gt;ActionDispatch&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Assertions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ResponseAssertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instance_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Override so deprecation warnings stop popping up. This uses a proper&lt;/span&gt;
  &lt;span class="c1"&gt;# +assert+ method but retains the functionality of +assert_response+.&lt;/span&gt;
  &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:assert_response_test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;expected_status&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;response_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="n"&gt;response_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;Expected response to be &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;expected_status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;, but was &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response_status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Major shout-outs to &lt;a href="http://innovationontherun.com"&gt;Rob Di Marco&lt;/a&gt; who actually wrote this and
figured out that &lt;code&gt;instance_eval&lt;/code&gt; was the proper method to use here,
not &lt;code&gt;class_eval&lt;/code&gt;... :D&lt;/p&gt;

&lt;h3&gt;update!&lt;/h3&gt;

&lt;p&gt;We have drastically improved this little snippet and ripped a monkey patch directly from
&lt;a href="https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/assertions/response.rb"&gt;Rails 4&lt;/a&gt;. Here&amp;#39;s the &lt;a href="https://gist.github.com/tubbo/5124630"&gt;full code&lt;/a&gt;, pasted here in case you want to read it:&lt;/p&gt;

&lt;script src="https://gist.github.com/tubbo/5124630.js"&gt;&lt;/script&gt;
</description>
    </item>
    <item>
      <title>use assertions in rspec</title>
      <pubDate>11 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/08/use-assertions-in-rspec</link>
      <guid>http://psychedeli.ca/2013/02/08/use-assertions-in-rspec</guid>
      <description>&lt;h1&gt;tl;dr -- you can do MiniTest::Assertions inside RSpec examples.&lt;/h1&gt;

&lt;p&gt;A few years ago, &lt;a href="http://github.com/rspec/rspec"&gt;RSpec&lt;/a&gt; was extracted from the &lt;a href="http://cukes.info"&gt;Cucumber&lt;/a&gt;
project as a separate entity for BDD and testing with natural language
in Ruby apps which may not need all of the weight of Cucumber. It gained
traction pretty much everywhere, but it&amp;#39;s primary evangelists were
Rails developers (well, &lt;a href="http://www.rubyinside.com/dhh-offended-by-rspec-debate-4610.html"&gt;except DHH&lt;/a&gt;), and in the Rails community
it was commonly used. But two years ago, DHH lit the spark that would
become a major debate and one that &amp;quot;divides&amp;quot; Rails developers all over
the map. DHH argued that [test_unit is all you will ever need][dhh] for
testing a Rails application. And he&amp;#39;s basically right, because you can
&lt;code&gt;rails generate model {something&lt;/code&gt; and then &lt;code&gt;rake test&lt;/code&gt; and watch the
assertions run.&lt;/p&gt;

&lt;h2&gt;why don&amp;#39;t people use rspec?&lt;/h2&gt;

&lt;p&gt;RSpec is a pretty strange testing framework to work with if you&amp;#39;re used
to doing assertions and unit-testing each component of your application
with the built-in &lt;code&gt;Test::Unit&lt;/code&gt; library. &lt;code&gt;Test::Unit&lt;/code&gt;, and it&amp;#39;s successor,
&lt;a href="https://github.com/seattlerb/minitest"&gt;Minitest&lt;/a&gt;, was designed primarily as a unit testing framework at
its most basic level. Since it&amp;#39;s included in the Ruby standard library,
it needs to follow the paradigms of how Ruby classes are designed by
doing one thing, and one thing well. You&amp;#39;re meant to add other libraries
such as &lt;a href="http://mocha.rubyforge.org"&gt;Mocha&lt;/a&gt; and &lt;a href="https://github.com/TwP/turn"&gt;Turn&lt;/a&gt; to give &lt;code&gt;Test::Unit&lt;/code&gt; more
functionality, or make it easier to read. These libraries all have their
quirks, and tests written for basic &lt;code&gt;Test::Unit&lt;/code&gt; tend to fail in strange
ways when adding these other libraries on top of them, so typically
users of Minitest or test_unit won&amp;#39;t be keen on installing a lot of &amp;quot;sugary&amp;quot;
plugins that could introduce a bug in the test suite.&lt;/p&gt;

&lt;h2&gt;the problem that rspec solves&lt;/h2&gt;

&lt;p&gt;If you completely divorce yourself from RSpec&amp;#39;s syntax and the framework
which surrounds it to provide a killer testing experience, you realize
even less reasons to use Minitest. Speed and efficiency aside, RSpec gives
you a lot of sensible defaults and configuration options just for modifying
how its returning results to you. Don&amp;#39;t like colors? Turn &amp;#39;em off. How about
the way it just shows you every test&amp;#39;s name? Try &lt;code&gt;--format=dot&lt;/code&gt; to make large
test suites easier to read. Or better yet, use &lt;code&gt;--format=progress&lt;/code&gt; for really
big test suites where you need to see the health of all tests but don&amp;#39;t need
to necessarily see which tests fails immediately in real-time.&lt;/p&gt;

&lt;p&gt;Tools like &lt;a href="https://github.com/skalnik/vim-vroom"&gt;vim-vroom&lt;/a&gt; were built for RSpec. &lt;a href="https://github.com/garybernhardt/dotfiles/blob/master/.vimrc"&gt;Gary Bernhardt&amp;#39;s vimrc&lt;/a&gt;
is designed for RSpec and works best when you&amp;#39;re not constantly switching between
Minitest and RSpec. It&amp;#39;s more reliable to run single tests and single examples
with RSpec, because you don&amp;#39;t need a special shell alias or &lt;em&gt;not&lt;/em&gt; use things
like Turn which muck with the actual name of the &lt;code&gt;test_method&lt;/code&gt; you developed.&lt;/p&gt;

&lt;h2&gt;have your cake and eat it too&lt;/h2&gt;

&lt;p&gt;You can take advantage of these lovely niceties of RSpec, without having to
write in that nasty syntax! Since RSpec is just syntactic sugar overtop of
&lt;code&gt;Test::Unit&lt;/code&gt;, there&amp;#39;s nothing stopping you from writing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;should pass&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;not true&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So why are you screwing around with &lt;code&gt;Test::Unit&lt;/code&gt; and Minitest&amp;#39;s difficulties and
caveats? Just use RSpec. And make your life easier.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>how to bang...like a boss</title>
      <pubDate>11 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/11/how-to-bang</link>
      <guid>http://psychedeli.ca/2013/02/11/how-to-bang</guid>
      <description>&lt;p&gt;In the Ruby programming language, there exists two characters you are
only permitted to use when naming a method: &lt;strong&gt;?&lt;/strong&gt; and &lt;strong&gt;!&lt;/strong&gt;. These
special permissions are designed to allow you to establish a certain
level of convention in your method naming, for example, a method ending
in &amp;quot;?&amp;quot; in Ruby is mosty likely always going to return a Boolean response
of true or false. Not only is this convention not questioned much, but
there seems to be very little sensible use out of making a &amp;quot;?&amp;quot; method
not return a boolean response.&lt;/p&gt;

&lt;p&gt;Unlike the &amp;quot;?&amp;quot; suffix, which has an established and unchallenged purpose
within the Ruby community, &amp;quot;!&amp;quot; is a lot less cut and dry. In ActiveRecord,
for example, &amp;quot;!&amp;quot; is added to methods like &lt;code&gt;save()&lt;/code&gt; and &lt;code&gt;create()&lt;/code&gt; when you
want an Exception to be thrown in the case where those methods fail to
execute properly. It&amp;#39;s easy enough to add the &amp;quot;!&amp;quot; to those methods when
you need to change the nature of your business logic, or perhaps you wish
to capture the Exception so you can raise a new one overtop of that
error case.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;validates_presence_of&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# app/controllers/posts_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create!&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; throws ActiveRecord::ValidationError&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; just returns &amp;#39;false&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But Ruby, on the other hand, uses &amp;quot;!&amp;quot; to denote when you&amp;#39;re mutating the
object that you&amp;#39;re calling the method on. This is an entirely different
use case from Rails, yet this use case also seems to make sense on a
syntactic level:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;starter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;newer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;starter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; returns a new Hash: { foo: &amp;#39;bar&amp;#39;, baz: &amp;#39;bat&amp;#39; }&lt;/span&gt;

&lt;span class="n"&gt;starter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; merges in { baz: &amp;#39;bat&amp;#39; } to the starter Hash instance&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;bang is the yolo convention&lt;/h2&gt;

&lt;p&gt;At eLocal, we use &amp;quot;!&amp;quot; as a generalized YOLO convention. It means we&amp;#39;re
about to execute some actions which may fail, or are connecting to an
outside resource (such as an API or our mothership site) In either case,
the &amp;quot;!&amp;quot; dictates that our app&amp;#39;s control flow should stop.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>who needs docs when you have ctags</title>
      <pubDate>5 Feb 2013</pubDate>
      <link>http://psychedeli.ca/2013/02/05/who-needs-docs-when-you-have-ctags</link>
      <guid>http://psychedeli.ca/2013/02/05/who-needs-docs-when-you-have-ctags</guid>
      <description>&lt;p&gt;Ever since I watched &lt;a href="https://peepcode.com/products/play-by-play-tenderlove-ruby-on-rails"&gt;Aaron Patterson&amp;#39;s Peepcode Play-by-Play&lt;/a&gt;,
I&amp;#39;ve been absolutely fascinated with the use of CTags to jump around
the various codebases you have installed (if you use Ruby, you know
how much of a maze it can be to figure out exactly where an error
is coming from!). As the name would imply, CTags were created for
C programmers dealing with massive codebases that typically had
minimal to no documentation. Developed during the first boon
of open source distribution, and created by some of the people
on the BSD UNIX project (it was originally released with BSD UNIX),
it was championed as a quick, easy and light-weight way of moving
around a codebase.&lt;/p&gt;

&lt;h2&gt;required equipment&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ve &lt;a href="http://www.psychedeli.ca/2012/03/18/weaning-off-oh-my-zsh"&gt;written about my setup in the past&lt;/a&gt;, and I created a &lt;a href="https://github.com/tubbo/dots"&gt;shell
framework for zsh users&lt;/a&gt; that implements all of the concepts I&amp;#39;m
talking about here. This technique requires that you&amp;#39;re editing your
code with &lt;a href="http://www.vim.org/"&gt;Vim&lt;/a&gt; (and any derivatives thereof) and managing your
&lt;a href="http://www.rubygems.org/"&gt;RubyGems&lt;/a&gt; with &lt;a href="http://gembundler.com/"&gt;Bundler&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;vim for the win&lt;/h3&gt;

&lt;p&gt;CTags was designed for Vim, and since I&amp;#39;m a Vim user I&amp;#39;m going to mostly
talk about &lt;a href="http://freecode.com/projects/exuberantctags"&gt;Exuberant CTags&lt;/a&gt;. If you&amp;#39;re an Emacs user, you might
have to do some extra customization in your editor, but the concept of
CTags is still relevant and in my opinion, still useful for any modern
programmer.&lt;/p&gt;

&lt;h3&gt;bundler-managed gemsets&lt;/h3&gt;

&lt;p&gt;If you&amp;#39;re a Rubyist, this probably won&amp;#39;t work as intended unless you
manage your application&amp;#39;s gems with &lt;a href="http://gembundler.com/"&gt;Bundler&lt;/a&gt; and don&amp;#39;t use
&lt;a href="http://rvm.io"&gt;RVM&lt;/a&gt; to manage gemsets/rubies. The reason for this is that
Bundler stores your gem&amp;#39;s code inside your application&amp;#39;s root
directory (I have it configured to use &lt;code&gt;vendor/gems&lt;/code&gt;, but most people
use &lt;code&gt;vendor/bundle&lt;/code&gt; or something...I think that&amp;#39;s the default), and
when you generate your &lt;code&gt;tags&lt;/code&gt; file, it will only look at code under
the given root directory, so if you&amp;#39;re only using Bundler to manage
your gem dependencies, you&amp;#39;ll be able to access not only your
application&amp;#39;s code, but the code of the entire Rails framework as well
as every other gem you&amp;#39;re using. From what &lt;a href="https://twitter.com/mpapis"&gt;Michael Papis&lt;/a&gt; and
&lt;a href="https://plus.google.com/114407361520857511779/about"&gt;Deryl&lt;/a&gt; have been saying on &lt;a href="irc://irc.freenode.net/rvm"&gt;IRC&lt;/a&gt;, RVM2 will have support
for custom gem directories, so you can use RVM and Bundler to manage
dependencies in subdirectories of your project, rather than &lt;code&gt;~/.rvm&lt;/code&gt;,
which makes it a pain for CTags to function (though I have seen Rake
tasks where this becomes a possibility).&lt;/p&gt;

&lt;h2&gt;let&amp;#39;s get it started&lt;/h2&gt;

&lt;p&gt;To set up CTags, we first need to install &lt;a href="http://freecode.com/projects/exuberantctags"&gt;Exuberant CTags&lt;/a&gt; and
get it working with Vim. Thankfully, Exuberant CTags used to be included
with Vim, so they compliment each other quite nicely. It&amp;#39;s a separate
project, now,&lt;/p&gt;

&lt;h3&gt;OS X USERS!!!&lt;/h3&gt;

&lt;p&gt;I&amp;#39;m on OS X, so I actually had to rename a built-in binary bundled along
with my OS to use Exuberant CTags. OS X comes bundled with &lt;a href="http://www.emacswiki.org/BuildTags"&gt;Emacs CTags&lt;/a&gt;,
which are not compatible with Vim (or practically anything else that uses
CTags, for that matter). Not sure if people on Linux-based OSes or other
flavors of UNIX also have to do this, but before installing Exuberant
CTags, I had to do the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo mv /usr/bin/ctags /usr/bin/etags
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This still kept the Emacs binary around, but renames it to something that
won&amp;#39;t conflict with the &lt;code&gt;ctags&lt;/code&gt; binary you&amp;#39;re about to install.&lt;/p&gt;

&lt;p&gt;On OS X, you can just do the following to install Exuberant CTags:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew install ctags
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will place the binary in &lt;code&gt;/usr/local/bin/ctags&lt;/code&gt;. Regardless of your
shell setup, I think it&amp;#39;s just easier if you rename the Emacs CTags binary
and install from Homebrew or some other package manager, if you have to.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m not going to tell you how to install [Homebrew][brew] because you
should already know how or have it on your system. What are you waiting
for???&lt;/p&gt;

&lt;h2&gt;use the tags, luke&lt;/h2&gt;

&lt;p&gt;CTags is just as easy to use as it is to install. Go to the root directory
of your project and create the &lt;code&gt;tags&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Code/very_important_application
&lt;span class="nv"&gt;$ &lt;/span&gt;ctags -R .
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, open your application code back up. Browse to a method definition,
it would be best if this method was one you knew had only one place it
was defined. Highlight the &lt;code&gt;method_name&lt;/code&gt; in visual mode and hit &lt;strong&gt;Ctrl+]&lt;/strong&gt;
to jump to it&amp;#39;s tag definition. Did you notice how your buffer snapped
to the file where that method was defined? You can also go back to
previous definitions of a method by doing &lt;strong&gt;Ctrl-[&lt;/strong&gt;, if the method has
been overridden numerous times. This is especially useful in Rails,
where lots of abstraction and overriding is taking place, and in such
a big codebase it&amp;#39;s terribly useful to be able to quickly move between
the different method definitions, showing the evolution of the code
that you will eventually run as you call that method from a higher level.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s so much easier to get work done when leaving the editor is only done
when you&amp;#39;re &lt;em&gt;really&lt;/em&gt; done coding or you need to look up something that
maybe isn&amp;#39;t explained quite well in the documentation, as is the case
with many of Rails&amp;#39; lesser-known methods (especially those nice little
helpers in the view layer).&lt;/p&gt;

&lt;h2&gt;keep it ignant&lt;/h2&gt;

&lt;p&gt;Remember to keep your &lt;code&gt;tags&lt;/code&gt; file in your &lt;a href="http://robots.thoughtbot.com/post/18739402579/global-gitignore"&gt;global gitignore&lt;/a&gt; file,
&lt;code&gt;~/.gitignore&lt;/code&gt;, in order to keep it out of your repos. It&amp;#39;s not terribly
useful to have in there and generally, each developer is going to have
to generate their own tags index every time they download your code
anyway, so it&amp;#39;s kinda pointless to version control the index.&lt;/p&gt;

&lt;p&gt;I hope that this was an informative crash course on installing, building
and using CTags in your daily life. It would be even better if CTags makes
at least your work life a bit easier to deal with every day.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>blogging from scratch</title>
      <pubDate>25 Nov 2012</pubDate>
      <link>http://psychedeli.ca/2012/11/25/blogging-from-scratch</link>
      <guid>http://psychedeli.ca/2012/11/25/blogging-from-scratch</guid>
      <description>&lt;p&gt;In case you haven&amp;#39;t already figured this out, I am a Ruby programmer. It took me a while
before I was really comfortable with calling myself a &amp;quot;programmer&amp;quot; when dealing with Ruby,
because I did something most people advise against. I learned Ruby by learning Ruby on
Rails. So I learned the framework before I learned the language. Generally, this is
frowned upon and causes some very bad habits to develop eearly on. However, learning Ruby
this way turned out to not be so bad (even though it took me a bit longer to dive in to
Ruby itself), and I continue to make the argument that having quick, tangible results and
an emphasis on rapid prototyping allowed me to quickly and easily pick up some of the more
advanced concepts of not only Ruby, but HTTP and web development in general. As it is my
day job, I do enjoy working in Rails, but sometimes its paradigm just doesn&amp;#39;t fit in
(well) with what I&amp;#39;m trying to do. So I wanted to use something different.&lt;/p&gt;

&lt;p&gt;I tried a &lt;a href="http://sinatrarb.com"&gt;number&lt;/a&gt; &lt;a href="http://camping.rubyforge.org/"&gt;of&lt;/a&gt; &lt;a href="http://typosphere.org"&gt;alternatives&lt;/a&gt; to simplify the development
process, but I wasn&amp;#39;t really feeling any of them. Early readers will remember &lt;a href="http://typosphere.org"&gt;Typo&lt;/a&gt;
as one alternative I used for quite a while because it was the only one that had XML-RPC
connectivity. The main way I blogged back then was through &lt;a href="http://macromates.com"&gt;TextMate&lt;/a&gt;, so I could
simply push the post to the server after I was finished with it, and keep the text copy on
my computer as a backup. I gave up attempting to construct an XML-RPC interface to any of
the existing blogging platforms, and basically settled on Typo because it already had that
in place. Everything else about it sucked though, it still used Rails 2.2 (Rails 3 was
out!), Prototype.JS for the JavaScript, and an antiquated themeing framework that just
made everything harder to comprehend.&lt;/p&gt;

&lt;p&gt;Then, I came across this new thing that &lt;a href="http://tom.preston-werner.com/"&gt;Tom Preston-Werner&lt;/a&gt; (one of the founders of
GitHub) built as the engine that runs GitHub Pages. It&amp;#39;s called &lt;a href="http://jekyllrb.com"&gt;Jekyll&lt;/a&gt; and it&amp;#39;s
well, awesome. Jekyll merges HTML layouts with Liquid templates and Markdown text content
to build a site that&amp;#39;s simple and fast. Since it&amp;#39;s just static HTML, there&amp;#39;s no waiting
around for the database to return with the proper data, nor is there any extra time while
the data is parsed to be human readable. Everything is &amp;quot;just there&amp;quot;. But Jekyll isn&amp;#39;t a
complete solution. Designed for GitHub pages, a huge userbase, it&amp;#39;s of no surprise that
the program isn&amp;#39;t all that configurable. For example, you can&amp;#39;t change the directory where
posts and layouts and plugins are read from, nor can you change the location/filename of
the YAML config. Until now, that is.&lt;/p&gt;

&lt;h2&gt;hacking jekyll&lt;/h2&gt;

&lt;p&gt;I wanted to design &lt;a href="http://github.com/tubbo/psychedeli.ca"&gt;my blog&amp;#39;s folder structure&lt;/a&gt; in a certain way. For starters, I&amp;#39;m
already using 3-character folder names for any custom directories that weren&amp;#39;t being
preprocessed by Jekyll. I wanted the content rendering engine to be just one part of how
the entire app operates, as I have also added &lt;a href="https://github.com/sstephenson/sprockets"&gt;Sprockets&lt;/a&gt; for asset preprocessing and
a Rack app or two for some realtime custom content. Using &lt;a href="https://github.com/gmarik/rack-try_static"&gt;TryStatic&lt;/a&gt;, the static
content on &lt;a href="http://psychedeli.ca"&gt;http://psychedeli.ca&lt;/a&gt; can be served on the Rack stack alongside
&lt;a href="https://github.com/tubbo/psychedeli.ca/blob/master/lib/status_exchange.rb"&gt;StatusExchange&lt;/a&gt;, my status update feed(s) parser. Rack middleware allows me to handle
each request that comes in with a set number of classes. So for example, StatusExchange is
only meant to respond on requests to &lt;strong&gt;/status&lt;/strong&gt;, and any other requests just gets sent to
the next middleware, which in this case is TryStatic. TryStatic will simply read the
request and try to find a matching file in the &lt;strong&gt;pub/&lt;/strong&gt; directory, which is where Jekyll
is storing the site.&lt;/p&gt;

&lt;h2&gt;back to your roots&lt;/h2&gt;

&lt;p&gt;After attempting this setup, I was poised to find out that &amp;quot;fighting the framework&amp;quot; against
all of Jekyll&amp;#39;s better judgment was a bad idea. As I continued to experiment more with my blog,
Jekyll became simply an obstacle rather than a solution in my quest to make my blog better and
more powerful. In addition, my folder structure a few years ago looked very similar to your
typical Rails application, with some minor renaming differences. So I decided to swallow my
pride and return to the Rails ecosystem.&lt;/p&gt;

&lt;p&gt;Doing so provided a number of significant advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It comes with a test suite built-in, so I can not only test the custom Markdown processor
I wrote, but also the other libraries that are used to build the content on this site.&lt;/li&gt;
&lt;li&gt;Deployment with Capistrano and on Heroku is easier than wrangling static sites to work
inside a Rack environment. This was probably the &lt;strong&gt;biggest&lt;/strong&gt; reason, as updating the
blog frequently became somewhat of an issue using my cobbled-together Jekyll site on Rack.&lt;/li&gt;
&lt;li&gt;Rails has the ability to cache entire pages to HTML, just like how Jekyll compiled my Markdown
to static HTML. Using a custom library for parsing out YAML front matter and Markdown
content with ActionView, we can implement pretty much the same thing that Jekyll was doing,
with the obvious advantage of being inside the Rails stack and having access to the
entire ecosystem of tools built for use with this framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I&amp;#39;ve become more and more comfortable with Rails 3, I&amp;#39;ve also noticed a huge push
towards modularity in the Rails framework. Now that I don&amp;#39;t have to include ActiveRecord
and other gems I&amp;#39;m not using, Rails becomes a much lighter framework, and still retains
its ease of use. And with the new fragment caching and page caching features coming in the
new Rails 4 release, I&amp;#39;m confident that my choice will not only replicate any benefits I
would&amp;#39;ve had from Jekyll, it will mitigate future development headaches when creating
simple features and experiments for the blog.&lt;/p&gt;

&lt;h2&gt;getting it done&lt;/h2&gt;

&lt;p&gt;Using the &lt;code&gt;ActionView&lt;/code&gt; template handling system, I simply passed in Markdown as if it was
a Rails view at first. However, Jekyll source files are not merely Markdown. They are a
combination of YAML front matter and Github-flavored Markdown, which means not only am I
going to have to parse the YAML configuration out of this Markdown source, I&amp;#39;m also going
to have to implement some sort of syntax highlighting with Pygments in order to replicate
the beauty and simplicity of Jekyll.&lt;/p&gt;

&lt;p&gt;For starters, I used &lt;a href="https://github.com/vmg/redcarpet"&gt;Redcarpet&lt;/a&gt; to parse Markdown. I like Redcarpet the best out of all
the Markdown gems for Ruby, particularly because of its extensible rendering
architecture, allowing me to (like I just did) override the directive for parsing a block
of code and running a syntax highlighter through it. This one is the easy step: tons of
guides exist online to use &lt;code&gt;Pygments.rb&lt;/code&gt; and a Redcarpet renderer to highlight your code
blocks in Markdown.&lt;/p&gt;

&lt;p&gt;Next came the problem of the YAML front matter. Rails&amp;#39; templating system is not advanced
enough to parse &lt;em&gt;two&lt;/em&gt; templating languages in the same file, sending data from one to the
model and data from the other as the actual view. Jekyll source files are in fact used
for two separate things, and since my blog articles are all written with Jekyll&amp;#39;s YAML
front matter at the top, I needed a way to parse out that metadata and display it on the
page.&lt;/p&gt;

&lt;p&gt;So I created a library called &lt;a href="https://github.com/tubbo/psychedeli.ca/tree/master/lib/active_copy"&gt;ActiveCopy&lt;/a&gt; that allowed me to define a subfolder of my
view directories called &lt;code&gt;content/&lt;/code&gt;. Here, I can place Markdown files with YAML front
matter instructions, and expect them to be compiled into metadata-rich articles that
looked exactly like (or better than) my Jekyll transformations.&lt;/p&gt;

&lt;h2&gt;give it to me&lt;/h2&gt;

&lt;p&gt;ActiveCopy has not yet been extracted from my blog, but it was designed from the ground up
with the intention of becoming its own gem someday, since I&amp;#39;d like to use the concepts I
built on my own blogging app with future clients and ideas that I may encounter.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>making private methods private</title>
      <pubDate>24 Nov 2012</pubDate>
      <link>http://psychedeli.ca/2012/11/24/making-private-methods-private</link>
      <guid>http://psychedeli.ca/2012/11/24/making-private-methods-private</guid>
      <description>&lt;p&gt;So it&amp;#39;s a well-known Rubyism that you can actually circumvent private and
protected restrictions on instance methods if you simply use the &lt;code&gt;send()&lt;/code&gt;
method to access them. I wanted to see if it was possible to rewrite
&lt;code&gt;send()&lt;/code&gt; on a particular class to throw an exception if the method attempting
to be accessed was a private method on the class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oh yeah, this post is probably not safe for work...&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;how i did it&lt;/h2&gt;

&lt;p&gt;I started out with a simple class:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PrivateParts&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@boobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;( . )( . )&amp;quot;&lt;/span&gt;
    &lt;span class="vi"&gt;@butts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;(  )(  )&amp;quot;&lt;/span&gt;
    &lt;span class="vi"&gt;@balls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;( )( )&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kp"&gt;private&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;peep_show&lt;/span&gt;
    &lt;span class="vi"&gt;@boobs&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@butts&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@balls&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my test, I am asserting that a &lt;code&gt;NoMethodError&lt;/code&gt; will be thrown if I attempt to
access the method, even with &lt;code&gt;send()&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test/unit&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PrivatePartsTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_peep_show_cannot_be_called_outside_of_the_class&lt;/span&gt;
    &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PrivateParts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;

    &lt;span class="n"&gt;assert_raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peep_show&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;assert_raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:peep_show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This fails, until I overrode &lt;code&gt;PrivateParts.send()&lt;/code&gt;...&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;private_methods&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include?&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;private method &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; called for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What &lt;code&gt;send()&lt;/code&gt; is doing here is checking against &lt;code&gt;Object.private_methods&lt;/code&gt;, a collection of
method names that are all private. If a match is found, an error is thrown, because
somebody outside of the class wanted the data returned by &lt;code&gt;PrivateParts.peep_show&lt;/code&gt;. Due to
Ruby&amp;#39;s own clever scoping of the &amp;quot;actual&amp;quot; send method, overriding &lt;code&gt;send()&lt;/code&gt; does not affect
the classes own internal behavior, as the private method can still be called as a private
member within the class. This is illustrated by the following test:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_peep_show_can_be_exposed_by_exposure&lt;/span&gt;
    &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PrivateParts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;

    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;( . )( . )(  )(  )( )( )&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exposure&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And accompanying public method &lt;strong&gt;PrivateParts.exposure&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exposure&lt;/span&gt;
    &lt;span class="n"&gt;peep_show&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These tests both pass, since &lt;code&gt;peep_show&lt;/code&gt; is not using &lt;code&gt;PrivateParts.send()&lt;/code&gt; to do its bidding.
This override, being done in the &amp;quot;public-facing API&amp;quot; of the class, was scoped to just that
portion of the codebase. While this overrides Ruby&amp;#39;s &amp;quot;code-as-documentation&amp;quot; appraoch and
enforces strict private members in a class, it actually takes advantage of such an approach
to provide the functionality in a language that does not provide it out-of-the-box.&lt;/p&gt;

&lt;h2&gt;conclusion&lt;/h2&gt;

&lt;p&gt;This whole demonstration is available &lt;a href="https://gist.github.com/4141173"&gt;as a Gist&lt;/a&gt;. As this is more of a demonstration
in meta-programming, if anything, I wouldn&amp;#39;t recommend actually using it. This is of course
not an example of how I actually write my code. My personal beliefe is that such enforced
rules are unnecessary in the real world, and private/protected methods are simply there to
tell developers of an intended purpose for the method. It is almost never necessary to call
these methods in a test nor in an outside class, so a case such as this should probably never
come up, otherwise I think you may have bigger problems on your hands...&lt;/p&gt;
</description>
    </item>
    <item>
      <title>simplifying my ruby life</title>
      <pubDate>23 Nov 2012</pubDate>
      <link>http://psychedeli.ca/2012/11/23/simplifying-my-ruby-life</link>
      <guid>http://psychedeli.ca/2012/11/23/simplifying-my-ruby-life</guid>
      <description>&lt;p&gt;Ruby is all about simplicity. Make simple things simple, right? So how come we have to deal with all
this complexity when we run Ruby? This is how I made my life slightly easier and got some really
&lt;a href="/2013/02/05/who-needs-docs-when-you-have-ctags"&gt;sweet benefits&lt;/a&gt; as a result.&lt;/p&gt;

&lt;h2&gt;how i learned to stop worrying and uninstall rvm&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ve been a loyal &lt;a href="http://rvm.io"&gt;RVM&lt;/a&gt; user for years, practically ever since it came out. When it
first started, it was a simple way to manage the different versions of Ruby you had installed.
Simple, right? But then, as the project grew its scope became larger. RVM became more about managing
your Rubies, it now had integration with all kinds of software and &amp;quot;gemsets&amp;quot;, a way to organize each
project&amp;#39;s gems in their own separate, sandboxed environments that is still an unmatched, all-in-one
way to handle dependencies and Ruby version management.&lt;/p&gt;

&lt;p&gt;But RVM has its problems. For starters, it can be very annoying to manage paths in the middle of
working on a project because either RVM or you fucked something up. Being made of shellscripts, RVM
is incredibly brittle and at one point was under such active development that it was easier to just
keep up with the Git repo than keep downloading new stable versions every day. RVM was constantly
being forked to keep up with its growing list of strange issues that came with the territory of its
quite revolutionary/obscure methods of solving the problems of multiple Ruby installs and projects
on the same machine.&lt;/p&gt;

&lt;p&gt;Secondly, and this is most of the reason why I switched, as RVM increases in size the time my shells
take to open up increases dramatically. As they must load the entire RVM codebase each time, my
shells take an exorbitantly long time to open, even when my ZSH configs are optimized to an extreme.
The real bottleneck is, and always has been, RVM.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://www.engineyard.com/blog/2012/ruby-1-8-7-and-ree-end-of-life/"&gt;Ruby 1.8 began to sunset&lt;/a&gt;,
 I felt as though my time with RVM was coming to an end. I hesitated for a moment, then typed
&lt;code&gt;rm -rf ~/.rvm&lt;/code&gt; into iTerm and hit enter.&lt;/p&gt;

&lt;p&gt;I didn&amp;#39;t see the prompt again for another 20 minutes.&lt;/p&gt;

&lt;h2&gt;entering the 21st century&lt;/h2&gt;

&lt;p&gt;With that said, it was time to actually install Ruby. Knowing that I no longer need 1.8, have no use
for 2.0, Rubinius or JRuby (right now), and don&amp;#39;t want to lock my projects into older versions of Ruby, I installed
the language like I install anything else on my Mac, with Homebrew:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;brew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;ruby&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I use the Ruby in /usr/local/bin because I can test against the latest 1.9 for all my apps, and
because the Homebrew Ruby is typically quite up-to-date. Using this as your only Ruby does pose a
number of problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using 1 directory for all of your gems may prove a bit haphazard, since many of my projects are
on older versions of Rails or other gems and require different versions to be installed in different
places.&lt;/li&gt;
&lt;li&gt;Upgrading to a newer version of Ruby requires reinstalling your whole &lt;code&gt;gem list --local&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you change your &lt;code&gt;$GEM_HOME&lt;/code&gt;, you have to remember to clear it or change it back to access the
gems you installed in this &amp;quot;global&amp;quot; path.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;bundler to the rescue...&lt;/h2&gt;

&lt;p&gt;Of all the great Ruby projects out there, Bundler&amp;#39;s got my vote for the hands-down best maintained
Ruby project. Not only is it mostly error-free, it&amp;#39;s fast, beautiful, has sensible defaults, and
generally just &lt;strong&gt;makes fucking sense to me&lt;/strong&gt;. Bundler, the reason for Bundler&amp;#39;s creation, and the
philosophies that went into its design, are what makes Ruby such an amazing language to work with.
In my mind, Bundler and &lt;a href="http://rubygems.org"&gt;RubyGems&lt;/a&gt; serve as golden examples for how
dependencies and project-specific dependency management should be implemented in a language, and few
others even come close to replicating its symbiotic beauty.&lt;/p&gt;

&lt;p&gt;While Bundler is somewhat tedious and confusing to use, I&amp;#39;ve found it perfect for managing my
projects gem dependencies on a conventional basis. It solves all of the problems posed from using a
single Ruby, since it installs gems locally to &lt;code&gt;./vendor/gems&lt;/code&gt;. This is a sensible default location,
in with the rest of my vendored code, and easy to remember and type. I can write
&lt;code&gt;PATH=vendor/gems/bin:$PATH&lt;/code&gt; in my ZSH config to always have binaries in vendor/gems available to
execute. However, this again poses a problem that Bundler cannot solve...&lt;/p&gt;

&lt;h2&gt;with his trusty sidekick, autoenv!&lt;/h2&gt;

&lt;p&gt;RubyGems has a variable called &lt;code&gt;$GEM_HOME&lt;/code&gt; that is blank by default. If this variable is not set,
RubyGems looks in the default location (&lt;code&gt;/usr/local/lib/ruby...&lt;/code&gt;) for your installed gems.
Otherwise, it looks in the path provided by &lt;code&gt;$GEM_HOME&lt;/code&gt;. In order to only use Bundler as a
dependency manager, you must manage this shell variable yourself. I use &lt;a href="http://github.com/kennethreitz/autoenv"&gt;Autoenv&lt;/a&gt; to do
this for me. Autoenv is a simple shellscript that overrides &lt;code&gt;cd&lt;/code&gt; (just like RVM) and runs a file
called &lt;code&gt;.env&lt;/code&gt; local to the current directory. Right before &lt;code&gt;cd&lt;/code&gt;ing into the dir, the &lt;code&gt;.env&lt;/code&gt; file is
sourced and the code inside is executed. Typically, these files are used for configuring sensitive
data that you may not want in a repo anywhere, but you can also use them to build &amp;quot;pseudo-gemsets&amp;quot;
localized to your app&amp;#39;s directory. A perk of Autoenv is you can also add other configuration to this
file and not worry about Autoenv clashing with RVM, since they both override the same program.&lt;/p&gt;

&lt;p&gt;In order to make your bundle recognizable by RubyGems, you have to execute the following line upon
entering the directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;GEM_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;vendor/gems&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Whether you do this with Autoenv or by other means is up to you, but it must be done. &lt;code&gt;$GEM_HOME&lt;/code&gt; can not
take multiple values, it is used as a prefix and can only be one directory. I found Autoenv to be
the perfect companion, especially for Heroku applications. Autoenv has a special convention by which
adding a ~/.env file will be executed upon every &lt;code&gt;cd&lt;/code&gt;, no matter where the destination. By
symlinking &lt;code&gt;~/vendor/gems&lt;/code&gt; to my actual gems directory in &lt;code&gt;/usr/local&lt;/code&gt;, I no longer need
project-specific files to tell where my gems are located.&lt;/p&gt;

&lt;h2&gt;that&amp;#39;s all folks&lt;/h2&gt;

&lt;p&gt;Well, that&amp;#39;s how I set up my Ruby environment. All of this stuff is pre-configured for you (if you install
Bundler and Ruby 1.9, of course) in my ZSH framework called &lt;a href="http://github.com/tubbo/dots"&gt;DOTS&lt;/a&gt;. I&amp;#39;ll do a whole
write-up in the future, but to install it all you have to do is run the following line in ZSH:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;zsh_dots&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;dots&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will create ~/.dots from the Gem dir, link all of the dotfiles in ~/.dots/config, and reload the shell.
When your prompt comes back, you should have a ~/.bundle/config and ~/.env all ready to go, along with Autoenv
and the rest of my ZSH goodies. Note: Any dotfiles that aren&amp;#39;t already synced will NOT be touched,
but it will load configuration for any dotfiles you don&amp;#39;t have. So keep that in mind.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>declaring war on the framework</title>
      <pubDate>17 Aug 2012</pubDate>
      <link>http://psychedeli.ca/2012/08/17/declaring-war-on-the-framework</link>
      <guid>http://psychedeli.ca/2012/08/17/declaring-war-on-the-framework</guid>
      <description>&lt;p&gt;Most of my time at my current job has been spent refactoring our
affiliates API. When I started, it was a series of disorganized Rails
apps in a single Git repo, one solely for the backend and meant to push
sales leads to our main web application, and the other solely as a
frontend &amp;quot;dashboard&amp;quot; to that API, where the affiliates and the folks
working in operations can see statistics on and make changes to
affiliate accounts. In order to accomplish this, the past programmer had
the genius idea of separating out the entire model structure into a gem,
which further complicated the matter, leading to strange errors,
security flaws, and flat-out unimplemented garbage code.&lt;/p&gt;

&lt;h2&gt;The Pre-Game Show&lt;/h2&gt;

&lt;p&gt;Before I began reworking the API, I was told to completely rewrite the
email parser engine (from scratch, &lt;a href="http://www.joelonsoftware.com/articles/fog0000000069.html"&gt;don&amp;#39;t ever fucking do this&lt;/a&gt;). 
It was originally written in C++, but I had to implement in Ruby ostensibly 
so other developers could help out with adding features down the road.
This never happened, of course, because every time there needed to be something
added or a bug needed to be fixed, nobody wanted to tackle the problem
based on bad experiences in the past with this codebase. It took months
of agony before we finally had a stable, working version that didn&amp;#39;t
crap out all the time or send everyone 100 alert emails a day. For the
same reasons as Joel points out in the article I linked, rewriting a
codebase from scratch is always going to be painful. Most likely, the
bugs and misunderstandings that took me a lot of stress and energy to
work out were already taken care of in the C++ version of the parser.&lt;/p&gt;

&lt;h2&gt;Don&amp;#39;t fight the framework, declare war on it.&lt;/h2&gt;

&lt;p&gt;A lot of the confusion and deployment difficulties we had while working
with this API could have probably been averted if the developer who
worked on this project previous to me heard this simple phrase: &amp;quot;don&amp;#39;t
fight the framework&amp;quot;.&lt;/p&gt;

&lt;p&gt;When working with frameworks such as Rails, which change the way you
code in Ruby, your choices become more limited as to how you can (or
should) implement something. For example, it&amp;#39;s against the ethos of MVC
and Rails to perform database saves and complex logic in the view layer
of your application. It&amp;#39;s very common for developers to ignore this, and
simply go on hacking away at something where a much more elegant,
test-able and robust solution can be found by simply learning a bit more
about how their whole ecosystem works.&lt;/p&gt;

&lt;p&gt;I think this doomed strategy of solving small issues has its roots in a
larger, more psychological problem...&lt;/p&gt;

&lt;h2&gt;Being &amp;quot;that guy&amp;quot;&lt;/h2&gt;

&lt;p&gt;As a musician, I tend to think of my relationship with co-workers on a
creative team in similar ways to how I treat the members of my band. As
the bandleader, I&amp;#39;m responsible for coordinating rehearsals/gigs and
managing the operations of the band as well as conducting performances
and sometimes cueing parts to be played. Sometimes, there&amp;#39;s a guy in the
band who simply doesn&amp;#39;t &amp;quot;get it&amp;quot;. He can&amp;#39;t seem to fit himself in to the
sound of the whole band, and blend the sound of his instrument with that
of everyone else. And by the way, for the P.C. crowd...I am purposely not 
representing the female gender, because I rarely meet women who do this.
I&amp;#39;m not sure if that&amp;#39;s because there are typically more men than women
who play jazz instruments, which is the kind of musician I recruit for
&lt;a href="http://thewonderbars.com"&gt;The Wonder Bars&lt;/a&gt;, or if it has something to do with how women
approach this problem. But anyw, it&amp;#39;s been 100% men who do this in my
own personal experience.&lt;/p&gt;

&lt;p&gt;&amp;quot;That guy&amp;quot; is not a good guy to be. When push comes to shove, a guy like
that can&amp;#39;t be in a musical project that relies on the group being tight
and having a specific sound. He is typically unaware of his
actions, and is typically quite butthurt by his forced departure and
hearing of how he&amp;#39;s been behaving. In bands which don&amp;#39;t cycle through
performers, this is an even bigger problem because it is much more
expensive to fire someone and replace them than it is to mend a
relationship between two band members, from a logistical standpoint. In
other words, it&amp;#39;s a lot less work on &lt;em&gt;my&lt;/em&gt; part if the entire band works
with &amp;quot;that guy&amp;quot; to help him blend his sound in. But sometimes, it just
doesn&amp;#39;t work.&lt;/p&gt;

&lt;p&gt;Why am I telling you this? &lt;strong&gt;Because the former developer that built this
API didn&amp;#39;t know how to be a part of a team.&lt;/strong&gt; He built things that only he
knew how to fix. He wrote in languages that no one else on the team
understood, or understood to a point that they would feel comfortable
writing (or even worse, debugging) an application of some kind.&lt;/p&gt;

&lt;p&gt;The big kicker to all this? &amp;quot;That guy&amp;quot; decided, in his infinite wisdom,
that email parsing wasn&amp;#39;t possible with standard Ruby, and so he
utilized C++ and the &lt;a href="http://www.chilkatsoft.com/cpp_libraries.asp"&gt;chilkat&lt;/a&gt; library to do all the parsing. While
it did run quite fast, no one else on the team before or since knows C++
enough to debug someone else&amp;#39;s (probably horrible) codebase. This is the
only reason I was introduced to the project in the first place, and it
turns out that an email parser is &lt;strong&gt;really, really easy&lt;/strong&gt; to write in
Ruby. So whatever bullshit was spewing out of his mouth was just that,
and most likely his real motivation for writing it in C++ is just
&amp;quot;because he could&amp;quot;. We must remember, however, that &lt;strong&gt;just because you can, 
doesn&amp;#39;t mean you should&lt;/strong&gt;. In this case, this motivator for his
decision-making cost the company thousands of dollars and backtracked
our entire development effort a bit, because I can&amp;#39;t work on the main
app while I&amp;#39;m banging out bugs, developing new features, or refactoring
the API&amp;#39;s existing codebase.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s an excerpt of his CoffeeScript code that took me two days to
debug. For reference, I rewrote this code in about an afternoon:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;bt = (f) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapibutton&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapibutton_&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapisubmit&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;\&amp;quot;javascript:e_&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;f&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;&amp;quot;_();\&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;nbsp;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&amp;quot;
czti = (f) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;\&amp;quot;display:none;\&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;quot;
imt = (fa, fi) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapipoweredby&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + fa + &amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;_blank&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;/images/pixel.gif&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&amp;quot;
img = (f) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;border=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;quot;
lmid = (f) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&amp;quot;
anc = (f,v) -&amp;gt;
  w &amp;quot;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;elapi&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot; + ak + f + &amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;quot; + v + &amp;quot;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&amp;quot;
lti = (f, v) -&amp;gt;
  @zts = -1
  f.attr &amp;quot;src&amp;quot;, &amp;quot;http://&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;/v1/&amp;quot; + fv(apk) + &amp;quot;/zipvalidate/&amp;quot; + v
rmvc = (f) -&amp;gt;
  fe(f).css &amp;quot;background-color&amp;quot;, &amp;quot;#FFFFFF&amp;quot;
pf = (v) -&amp;gt;
  tv = v
  tv.replace(/\(/g, &amp;quot;&amp;quot;).replace(/\)/g, &amp;quot;&amp;quot;).replace(/-/g, &amp;quot;&amp;quot;).replace(/\./g, &amp;quot;&amp;quot;).replace &amp;quot; &amp;quot;, &amp;quot;&amp;quot;
vp = (v) -&amp;gt;
  l(v) == 10 and isnm(v)
cpops = -&amp;gt;
  w gops()
gops = -&amp;gt;
  hm = &amp;quot;&amp;quot;
  catid=&amp;quot;&amp;quot;
  $ea.each aks.it, -&amp;gt;
    catid = @ci if @k is fv apk
    #catid = aks.it[0].ci if catid is &amp;quot;&amp;quot;
  hm += &amp;quot;&lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Select Need&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;&amp;quot;
  $ea.each cps.it, -&amp;gt;
    hm += (&amp;quot;&lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;#{@oi}&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#{@n}&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;&amp;quot;) if @ci == catid
  return hm
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seriously, who the fuck wants to go through that and figure out, line by
line, what it does? All because of an idiotic, non-informed decision to
keep everything &amp;quot;terse&amp;quot; for &amp;quot;smaller file size&amp;quot;. These kinds of
decisions, made entirely inside one programmers head, are signs that the
developer in question is not aware of or doesn&amp;#39;t understand how to work
with a team. Perhaps he didn&amp;#39;t feel comfortable with his team, or there
were other reasons why he chose to code this way, but in any case they
are causing massive problems for me. Because it would take far too
much time to go through this code and refactor its potential issues, 
I can only hope that it continues to work as we continue development on 
the API.&lt;/p&gt;

&lt;p&gt;Before I [touched the code][dtmc], the JavaScript that controlled this
was building the HTML form from scratch, and was about 170 lines of
code. By not fighting the framework, and rather letting Rails take care
of asset packaging and template rendering (you know, the shit it&amp;#39;s good
at?), I was able to reduce the code footprint to about 35. That means
that the code I was working with was ~4x bigger than it could have been.
Not only that, but simply making an Ajax call to an HTML endpoint
instead of building everything in JS is less buggy, and it allows us to
take advantage of the nice server-side view layer stuff like Haml,
helper methods, and Rails&amp;#39; ActionView module. Working in Rails is just
depressing if you can&amp;#39;t use this shit.&lt;/p&gt;

&lt;p&gt;Oh, did I mention that &lt;em&gt;all&lt;/em&gt; of the static assets previously used in this 
widget were in &lt;strong&gt;app/views/script&lt;/strong&gt;, and they were all ERb so he could 
interpolate &lt;code&gt;&amp;lt;%= request.host %&amp;gt;&lt;/code&gt; into the code. Yup.&lt;/p&gt;

&lt;h2&gt;Reversing This Hell&lt;/h2&gt;

&lt;p&gt;So as I continued to toil on the API, I decided that my ultimate goal on
this project is to refactor it so the entire team could simply jump in
and begin working. In order to do this, a few things had to happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Everything needs to be combined into a single Rails app. &lt;/li&gt;
&lt;li&gt;Data from the MongoDB collection(s) that formerly powered the API
must be converted to PostgreSQL, with preserved relationships.&lt;/li&gt;
&lt;li&gt;Must integrate with Jenkins, our CI server, and our other
development tools Airbrake, Pivotal Tracker and Flowdock.&lt;/li&gt;
&lt;li&gt;Implement a tag-based release system and deploy based on
those tags, so we can better manage API versioning and the user can
always see what version of the API we&amp;#39;re working off of (with
documentation and an affiliate-centric changelog to boot)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;The Big Squeeze&lt;/h3&gt;

&lt;p&gt;We like to follow the &amp;quot;Pattern Of Least Expectation&amp;quot;, and since most of our
repos contain single Rails or Rack apps, why would we break from that
convention for the API? Thankfully, the 3 apps in the repo were
themselves Rails apps, or meant to work with a Rails app, so it was
simply a tedious process of moving code around and running the test
suite. It was quite easy, actually, to move everything into a single
app since we used the same model structure (in a Gem) for both apps.
Almost as easy as, you know, DOING IT IN THE FUCKING FIRST PLACE.&lt;/p&gt;

&lt;p&gt;This was accomplished in a fairly clever way. @iotr and I created a Rake
task that looked at the MongoMapper model definitions, found where the
attributes were declared, and executed &lt;code&gt;rails generate model&lt;/code&gt; for the
downcased name of the class. We also use these definitions to generate
the temporary table schema, since it also holds crucial database field
=&amp;gt; type mapping information...&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;%x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;grep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Rl&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;MongoMapper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;elocal_affiliates_data&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;egrep&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="err"&gt;$&amp;#39;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt; &lt;span class="n"&gt;$f&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;egrep&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;$f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;awk&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;$2&lt;/span&gt; &lt;span class="n"&gt;$3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sed&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,]&lt;/span&gt;&lt;span class="c1"&gt;//g&amp;#39;`; done)&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;270171&lt;/span&gt;
&lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;?????&amp;quot;&lt;/span&gt;

&lt;span class="cp"&gt;# Create temporary tables of Mongo data &lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="cp"&gt;# print the last model on each new model name encounter&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="cp"&gt;# translate mongo class into attribute type&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ObjectId&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; VARCHAR(255),&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; INTEGER,&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; DECIMAL,&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; TIMESTAMP,&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; BOOLEAN,&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;

    &lt;span class="nf"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="n"&gt;full_body&lt;/span&gt; &lt;span class="n"&gt;raw_post&lt;/span&gt; &lt;span class="n"&gt;questions&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;text_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;#{text_attr} VARCHAR(255)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s"&gt;&amp;quot;#{text_attr} TEXT&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;DROP TABLE IF EXISTS tmp_#{model_name.pluralize}; CREATE TABLE tmp_#{model_name.pluralize} ( #{line.chop}, _id VARCHAR(255), created_at TIMESTAMP, updated_at TIMESTAMP );&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
    &lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="cp"&gt;# Generate Rails models&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="cp"&gt;# print the last model on each new model name encounter&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="cp"&gt;# translate mongo class into attribute type&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ObjectId&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;:string &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;:integer &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;:float &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;:datetime &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; :boolean &amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;:references &amp;quot;&lt;/span&gt;

    &lt;span class="nf"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="n"&gt;full_body&lt;/span&gt; &lt;span class="n"&gt;raw_post&lt;/span&gt; &lt;span class="n"&gt;questions&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;text_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;#{text_attr}:string&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s"&gt;&amp;quot;#{text_attr}:text&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;rails generate model #{model_name} #{line}&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This script will build temporary tables based on every MongoMapper model
you have in a certain directory. It will then generate Rails models for
each of those MongoMapper models. In short, these two loops are what
translates MongoMapper class information into a database schema and
model structure. Doing this requires that your MongoMapper models are in
a different directory from app/models, so it may be a good idea to &lt;code&gt;mv
app/models vendor/models &amp;amp;&amp;amp; mkdir -p app/models&lt;/code&gt; before running this
script. At eLocal, we ran this in a Rake task.&lt;/p&gt;

&lt;h3&gt;The Data Translation&lt;/h3&gt;

&lt;p&gt;I&amp;#39;ll spare you guys the entire code for the &amp;quot;real import&amp;quot; task, because
it is rather long and tedious. We ran a SQL query that &lt;code&gt;INSERT&lt;/code&gt;ed into
the &amp;quot;app table&amp;quot; (that is, the table generated by the model which we will
be using in the application) the contents of our temporary tables, which
are prefixed with &amp;quot;tmp_&amp;quot;. It turns the &lt;code&gt;_id&lt;/code&gt; column on all tables into
&lt;code&gt;bson_id&lt;/code&gt;, and sets up the reference columns for other models by their
relational ID. It is important to run these scripts in a specific order,
from the least amount (or 0) of associations to the model dependent on
the most associations. We wrote similar queries for each model, and ran
them all in a Rake task.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s the formula for all of the SQL queries which performed this task:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;TRUNCATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="vg"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;models&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;relationship_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bson_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;tmp_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;relation_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;tmp_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;tmp_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="vg"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;tmp_models&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="vg"&gt;LEFT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;relation_models&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;relation_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;bson_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;tmp_models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;relationship_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When that task is written, the database will be magically populated with
all of the information from Mongo, except instead of tying everything
together with the &lt;code&gt;BSON::ObjectId&lt;/code&gt;, we are using numerical IDs generated
by Postgres. This lets the Mongo database once again &amp;quot;fit in&amp;quot; with our
Rails app.&lt;/p&gt;

&lt;p&gt;When these Rake tasks are run side by side, they do a complete
conversion of the MongoDB collection into a Rails-ready SQL database.
Because the API will be live when we&amp;#39;re migrating to the new server, we
need to make sure we&amp;#39;re dropping as little data as possible. &lt;/p&gt;

&lt;h2&gt;Migrating a Live API&lt;/h2&gt;

&lt;p&gt;Our API gets a good bit of usage, and what&amp;#39;s worse is that we didn&amp;#39;t
have monitoring tools set up to track when leads were coming through
and when they&amp;#39;re not (we do now, thanks to @fromonesrc&amp;#39;s Graphite/StatsD
skillz). So we had to assume a few things about the big API move:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We will probably lose some data in the transition.&lt;/li&gt;
&lt;li&gt;There will be clients attempting to connect to the old server when we
make the call to move DNS to the new box.&lt;/li&gt;
&lt;li&gt;There will be bugs when moving to the new infrastructure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Putting The Pieces Back Together&lt;/h3&gt;

&lt;p&gt;To effectively launch the new API, I had to sit with &lt;a href="http://www.opscode.com/products/"&gt;Chef&lt;/a&gt; for about
2 and a half weeks and figure that shit out. It&amp;#39;s not very simple, but
Chef is an incredibly powerful tool for managing server configuration
and launching new server instances. With our extensive use of
&lt;a href="http://aws.amazon.com"&gt;Amazon Web Services&lt;/a&gt;, Chef has proven to be a perfect companion in
DevOps, like when EC2 instances randomly terminate or an availability
zone goes down. But perhaps its most powerful asset is it&amp;#39;s introduced
us to a whole new realm of knowledge about how all this stuff is being
deployed behind-the-scenes. Chef makes us all aware of the way our
servers are set up, and may shine some light into potential design flaws
or inconsistencies with our network.&lt;/p&gt;

&lt;p&gt;With all the complex systems happening here, it&amp;#39;s nice to know that
someone, somewhere has simplicity in mind. The &lt;strong&gt;Amazon Elastic Load
Balancer&lt;/strong&gt; is an incredibly simple means of creating a load balancer,
and essentially enables 0-downtime deployments at all times (even in
fatal failure situations). Not only that, but the load balancer allows
us to experiment with horizontal scaling of our EC2 infrastructure.&lt;/p&gt;

&lt;p&gt;So in order to deploy the API, I set up its infrastructure to use a
single load balancer and API server. Since we don&amp;#39;t get &lt;em&gt;that&lt;/em&gt; much API
traffic right now, I kept it simple and only put one EC2 instance on the
load balancer. With the load balancer and Chef EC2 instance in place, it
was time to test the API. To do this, I used &lt;code&gt;/etc/hosts&lt;/code&gt; to &amp;quot;trick&amp;quot; my
machine into thinking &lt;code&gt;live.api.elocal.com&lt;/code&gt; had a DNS configuration that
pointed to the load balancer. When I loaded the page locally, I was
greeted by the new API, with a version tag number displayed in the
footer for good measure.&lt;/p&gt;

&lt;p&gt;With Rails&amp;#39; testing framework, Cucumber and RSpec, I was able to
effectively make sure that our clients would not notice any sort of
downtime or difference when posting their leads to our backend.&lt;/p&gt;

&lt;h3&gt;They&amp;#39;ll Never Know What Hit Them&lt;/h3&gt;

&lt;p&gt;Losing data is never a good thing. So when moving the API over, we
wanted to make sure that ideally 0% of the data gets lost. That&amp;#39;s
(probably) not going to happen, but it&amp;#39;s still a good idea to shoot for 
that. Our data loss was pretty much negligable because of our deployment
speed and the fact that everything was &amp;quot;set in place&amp;quot; before the actual
movement happened, so basically all we needed to do was to &amp;quot;flip a
switch&amp;quot;. But there&amp;#39;s still an elephant in the room: DNS.&lt;/p&gt;

&lt;p&gt;DNS is a tricky thing. It&amp;#39;s never quite certain how long it will take
for all of the nameservers to propagate changes across the Internet, and
different locations may yield different results. To get around this
problem, we used Apache&amp;#39;s &lt;code&gt;mod_proxy&lt;/code&gt; to silently forward requests from
&lt;code&gt;api.elocal.com&lt;/code&gt; to the new EC2 load balancer box. Simultaneously, we
wrote a new &lt;code&gt;CNAME&lt;/code&gt; record for the api subdomain that points to the new
load balancer. When both are in place, all API requests, new and old,
are forwarded to the new load-balanced API server, which is running the
new codebase.&lt;/p&gt;

&lt;h2&gt;What&amp;#39;s Next?&lt;/h2&gt;

&lt;p&gt;After the widget rewrite, we&amp;#39;re going to take a second look at the email
parser. We may even implement some kind of &lt;a href="http://en.wikipedia.org/wiki/Bayes%27_theorem"&gt;Bayesian&lt;/a&gt; filtering to
increase our chances of the parser mapping legal need to the proper
fields in our backend. But perhaps the most integral of all this is to
deprecate a direct relationship between the IMAP inbox and the Rails
app. By taking advantage of &lt;a href="http://docs.sendgrid.com/documentation/api/parse-api-2/"&gt;Sendgrid&amp;#39;s Parse API&lt;/a&gt;, we can simply
create an &lt;code&gt;EmailLeadsController&lt;/code&gt; to handle incoming emails, which will
pass off the Hash to a &lt;code&gt;Mail::Message&lt;/code&gt; that the &lt;code&gt;EmailParser&lt;/code&gt; can
accept.&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;This process, while kinda scary, was a complete success. In fact,
everything was done in the moment, so the least amount of data was lost
in transit. Meaning that, all in one big command, we imported Mongo to
Postgres, converted the schema to something Rails could understand, and
restarted the Nginx server with the new configuration. (Thanks
Capistrano) At the same time, the COO updated the DNS configuration to
point to the ELB, and the conversion was complete.&lt;/p&gt;

&lt;p&gt;All in all, I learned a LOT about how to properly do maintenence on
systems while they&amp;#39;re still operational, and I learned a bunch of what
NOT to do with a Rails app. Namely...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don&amp;#39;t rewrite anything until it becomes a last-resort option (i.e.,
debugging would take more time than rewriting)&lt;/li&gt;
&lt;li&gt;Don&amp;#39;t fight the framework. If you&amp;#39;re hacking too much at Rails to get
your code working, you&amp;#39;re probably doing it wrong.&lt;/li&gt;
&lt;li&gt;Chef is annoying sometimes, and difficult to debug, but it&amp;#39;s an
indispensable tool for managing server configuration.&lt;/li&gt;
&lt;li&gt;There are companies that actually sell C++ libraries. Libraries! And
what&amp;#39;s worse, &lt;strong&gt;there are companies that BUY these libraries!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>meet blue_velvet</title>
      <pubDate>2 Aug 2012</pubDate>
      <link>http://psychedeli.ca/2012/08/02/meet-blue-velvet</link>
      <guid>http://psychedeli.ca/2012/08/02/meet-blue-velvet</guid>
      <description>&lt;h1&gt;use your facebook page as a cms&lt;/h1&gt;

&lt;p&gt;It&amp;#39;s certainly been a while, hasn&amp;#39;t it? I&amp;#39;ve been busy with gigs and
vacation, so there&amp;#39;s been little time to blog. I &lt;em&gt;have&lt;/em&gt; been working on
stuff...including the foundation of a record label (which I&amp;#39;ll talk about
in a future post) and maintaining the Wonder Bars&amp;#39; official website.&lt;/p&gt;

&lt;p&gt;In the time it&amp;#39;s taken me to maintain that site, I&amp;#39;ve been quietly
developing a solution to a problem I think most small-scale developers
have, &lt;strong&gt;content duplication&lt;/strong&gt;. In other words, we&amp;#39;ve all run into the
problem of a company&amp;#39;s Facebook page saying one thing and their website
another. Who wants to log into 2 different accounts just to paste the
same paragraph of text? Furthermore, what if each CMS has its own input
format...say one lets you do Markdown but the others force you to be
either text-only or HTML-only. Now you&amp;#39;re looking at converting content,
and for non-programmers this may just not be a reality, or if it is it&amp;#39;s
a nightmare at best.&lt;/p&gt;

&lt;p&gt;Something needs to be done. This is the 21st century, after all. With the 
power of &lt;a href="http://rubyonrails.org"&gt;Ruby on Rails&lt;/a&gt; and &lt;a href="http://edgeguides.rubyonrails.org/engines.html"&gt;Rails engines&lt;/a&gt;, however, there
&lt;em&gt;is&lt;/em&gt; a solution.&lt;/p&gt;

&lt;h2&gt;introducing blue_velvet&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://github.com/tubbo/blue_velvet"&gt;blue_velvet&lt;/a&gt; is a gem I extracted from working code on 
&lt;a href="http://thewonderbars.com"&gt;TheWonderBars.com&lt;/a&gt;. The live production codebase uses
the gem with all of its default settings. You probably didn&amp;#39;t 
notice, which was the whole point. The gem code is an exact 
duplicate of the code that previously powered this functionality 
on the site, so you&amp;#39;re getting what I was working with; a powerful,
convention-over-configuration engine for displaying Facebook attributes
on your own, hosted, well-designed site.&lt;/p&gt;

&lt;h2&gt;making it work&lt;/h2&gt;

&lt;p&gt;Sound fun? It&amp;#39;s real easy to get started!&lt;/p&gt;

&lt;p&gt;Just add &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;blue_velvet&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to your Gemfile, run &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;bundle&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and generate the configuration using&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;rails&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;facebook:&lt;/span&gt;&lt;span class="vg"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Generate a new Facebook app on &lt;a href="http://developers.facebook.com"&gt;http://developers.facebook.com&lt;/a&gt;. Enter
in your &lt;strong&gt;App ID&lt;/strong&gt; and &lt;strong&gt;App Secret&lt;/strong&gt; keys to the proper YAML
attributes, then find the Facebook page you want to look for and look
for the number after your page&amp;#39;s hyphenated name in the URL. That&amp;#39;s your
&lt;strong&gt;page_id&lt;/strong&gt;, which you need to put into YAML as well.&lt;/p&gt;

&lt;p&gt;Now that you&amp;#39;re set up to access a Facebook page, you can build routes
to your Facebook page&amp;#39;s attributes like so:&lt;/p&gt;

&lt;p&gt;(in &lt;code&gt;routes.rb&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/about&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;facebook/page#description&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now type &lt;code&gt;rails server&lt;/code&gt; and visit &lt;a href="http://localhost:3000/about"&gt;http://localhost:3000/about&lt;/a&gt;, and you
should see the content of your page&amp;#39;s &amp;quot;Description&amp;quot; field. Since this
was designed to be used in a [PJAX][pj]-style environment, the
attributes are served as partials. &lt;/p&gt;

&lt;h2&gt;advanced usage&lt;/h2&gt;

&lt;p&gt;You can also do some cool stuff on the Ruby side to create better views
of your Facebook content. For example, The Wonder Bars&amp;#39; &lt;code&gt;/about&lt;/code&gt; page
uses the following Facebook page information to get all of its content
together:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;FacebookController&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Facebook:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="vg"&gt;PageController&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Accesses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;about&amp;#39;, &amp;#39;description&amp;#39; and &amp;#39;bio&amp;#39; for a complete &amp;quot;About Us&amp;quot; page.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;about_us&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="vg"&gt;tagline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;about&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="vg"&gt;elevator_pitch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;description&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="vg"&gt;long_form_bio&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;bio&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="vg"&gt;render&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;layout:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;xhr&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;end&lt;/span&gt;
&lt;span class="vg"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can have any controller access that &lt;code&gt;facebook&lt;/code&gt; object by simply
inheriting from &lt;code&gt;Facebook::PageController&lt;/code&gt;. You must cache values from
the Facebook page into instance variables for them to become available
in the view layer. Any attribute that can be obtained via the Page Graph API 
can be referenced here in some way. Use the &lt;code&gt;rails console&lt;/code&gt; to explore
more about the &lt;code&gt;facebook&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;As described above, since the default templates use layout-less
partials to serve content, you can create static pages by extending
&lt;code&gt;Facebook::PageController&lt;/code&gt; and defining custom actions, complete with
static views, to serve static Facebook page content on your hosted site.&lt;/p&gt;

&lt;h2&gt;missing something?&lt;/h2&gt;

&lt;p&gt;Did you expect &lt;strong&gt;blue_velvet&lt;/strong&gt; to do something that I missed? If so, let
me know in the &lt;a href="https://github.com/tubbo/blue_velvet/issues"&gt;GitHub Issues&lt;/a&gt; tracker. Or, you can fork the code
and contribute a pull request, I welcome all kinds!&lt;/p&gt;
</description>
    </item>
    <item>
      <title>research and development</title>
      <pubDate>1 May 2012</pubDate>
      <link>http://psychedeli.ca/2012/05/01/research-and-development</link>
      <guid>http://psychedeli.ca/2012/05/01/research-and-development</guid>
      <description>&lt;p&gt;I feel like I&amp;#39;ve been posting a lot about code on this blog. It&amp;#39;s mostly what I find myself writing about inside &lt;a href="http://www.sublimetext.com/2"&gt;my text editor&lt;/a&gt;, but today I feel like I should change the subject a bit. I&amp;#39;ve been feverishly working on both &lt;a href="http://thewonderbars.com"&gt;The Wonder Bars&lt;/a&gt;&amp;#39; debut album as well as side projects with some of my friends here in the Philadelphia electronic music scene (in its various forms). One of the most fruitful collaborations has been with &lt;a href="http://soundcloud.com/the-architech-music/trust-me-im-an-architect-sort"&gt;The Architech&lt;/a&gt;, a DJ I&amp;#39;ve known about for quite a while but which Philly is just beginning to get introduced to. He was one of the core guys behind the early raves at The Vaudeville Theater, where influential rave DJs like &lt;a href="http://soundcloud.com/udachi"&gt;Brak (now Udachi)&lt;/a&gt; and &lt;a href="http://facebook.com/jenmasdj"&gt;Jen Mas&lt;/a&gt; performed in what seemed like uninhabitable conditions. This was all before my time as a raver, though, so if you really want to hear the full story you&amp;#39;ll just have to come out to one of his shows and ask him yourself. He&amp;#39;s a resident at &lt;strong&gt;Propaganda&lt;/strong&gt; and the &lt;strong&gt;Bangarang! 4th Fridays&lt;/strong&gt; monthly parties at The HeadHouse, and frequently plays the legendary &lt;a href="http://thephiladelphiaexperiment.org/"&gt;PEX&lt;/a&gt; parties, including &lt;a href="http://soundcloud.com/the-architech-music/trust-me-im-an-architect-sort"&gt;the most recent Heartburn at the Electric Factory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We&amp;#39;ve been making tracks together since the start of 2012 as &lt;a href="http://soundcloud.com/resndev"&gt;Research and Development&lt;/a&gt;. The tracks are harder edged than my work with the Wonder Bars, and that&amp;#39;s intentional. I definitely wanted to do something different than what I&amp;#39;ve been doing with the &amp;#39;Bars, especially musically. This is a chance for both of us to break out of our shells, and explore some of these less-travelled paths in dance music.&lt;/p&gt;

&lt;p&gt;But enough about that. Here&amp;#39;s what we&amp;#39;ve been working on...&lt;/p&gt;

&lt;h2&gt;Beardyman - Vampire Skank (R&amp;amp;D remix)&lt;/h2&gt;

&lt;iframe width="100%" height="166" scrolling="no" frameborder="no" src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38726145&amp;amp;auto_play=false&amp;amp;show_artwork=false&amp;amp;color=9800ff"&gt;&lt;/iframe&gt;

&lt;p&gt;An entry for the Beardyman remix competition on JunoDownload, this track was made almost entirely using Beardyman&amp;#39;s vocal samples. Our initial goal was to use as much of the sample pack as we could, but we ended up adding some bass stabs and drums to &amp;quot;beef it up&amp;quot; a bit.&lt;/p&gt;

&lt;h2&gt;I&amp;#39;ll Be Your Baby&lt;/h2&gt;

&lt;iframe width="100%" height="166" scrolling="no" frameborder="no" src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38627388&amp;amp;auto_play=false&amp;amp;show_artwork=false&amp;amp;color=0018ff"&gt;&lt;/iframe&gt;

&lt;p&gt;This was an &lt;a href="http://endoftime.beyonceonline.com"&gt;entry for the Beyonce End of Time remix competition&lt;/a&gt;. We had already been working on a remix that had a harder edge and was more &amp;quot;bumpy&amp;quot;. But after experimenting one weekend like good little scientists, we came up with this rhythmic, pulsating tune that emphasizes the bass and completely changes the vibe of the original track.&lt;/p&gt;

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

&lt;p&gt;We have a few new ones in the works, including AN ORIGINAL as well as a remix of &lt;a href="http://www.beatport.com/track/disappear-original-mix/278013"&gt;Ross D&amp;#39;s Disappear&lt;/a&gt;. We&amp;#39;re trying some new (old?) tricks in these next couple tracks, so expect them to sound radically different from the music you just heard!&lt;/p&gt;
</description>
    </item>
    <item>
      <title>kick out the jams, motherfuckers</title>
      <pubDate>30 Apr 2012</pubDate>
      <link>http://psychedeli.ca/2012/04/30/kick-out-the-jams</link>
      <guid>http://psychedeli.ca/2012/04/30/kick-out-the-jams</guid>
      <description>&lt;p&gt;Well, I finally broke down and integrated &lt;a href="http://twitter.github.com/bootstrap"&gt;Twitter Bootstrap&lt;/a&gt; with the existing UI of
my blog. To be fair, it DEFINITELY needed some work, and I just didn&amp;#39;t have the time to get into the existing &lt;a href="http://sass-lang.org"&gt;Sass SCSS&lt;/a&gt; framework and figure everything out. But as Bootstrap &lt;a href="http://scripting.com/stories/2012/03/14/movingToBootstrap20.html"&gt;turned 2.0&lt;/a&gt;, I found myself longing for a responsive UI (so I wouldn&amp;#39;t have to &amp;quot;deal with&amp;quot; mobile), a standard reset, great typography defaults, and nice buttons/form elements to play with should I need them. The answer was simple. I &lt;em&gt;needed&lt;/em&gt; Bootstrap.&lt;/p&gt;

&lt;p&gt;Bootstrap is written in the &lt;a href="http://lesscss.org/"&gt;LESS&lt;/a&gt; framework, which kinda sucks because I prefer SCSS since I work with &lt;a href="http://rubyonrails.org"&gt;Rails apps all day&lt;/a&gt;. Thankfully, someone made &lt;a href="https://github.com/thomas-mcdonald/bootstrap-sass"&gt;a gem&lt;/a&gt; that ports the Bootstrap framework over to Sass for easy modification. Now, if I want to modify the very variables and mixins that power the framework, I can do so. That&amp;#39;s really cool.&lt;/p&gt;

&lt;p&gt;Another sort-of invisible addition that I made that actually makes all this possible is I am now compiling all assets on the server side automatically using &lt;a href="https://github.com/sstephenson/sprockets"&gt;Sprockets&lt;/a&gt;, better known as &amp;quot;the asset pipeline&amp;quot; in Rails. It has all the same benefits as the asset pipeline...and all of its shortcomings as well (and then some!). My &lt;code&gt;config.ru&lt;/code&gt; has gone through a heavy transformation based on &lt;a href="https://gist.github.com/2143990"&gt;this gist I found&lt;/a&gt; for loading Sprockets and Bootstrap onto a non-Rails
application. Because I&amp;#39;m using Sprockets to dynamically load stylesheet, JavaScript and image assets, I can develop without recompiling the stylesheets every time. My JavaScript files are minified and compressed before going into production for optimal performance. All of this is happening with the power of Ruby and Rack. Since this static site is being served as a small Rack application, I can take advantage of the stack for logging purposes, compiling static assets, and possibly &lt;a href="https://github.com/tubbo/psychedeli.ca/tree/master/lib"&gt;other things coming soon down the pipeline&lt;/a&gt;...&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s &lt;a href="https://github.com/tubbo/psychedeli.ca/commit/10d39bd71e83aaa9e8b57f2b1b3f53b686bd94bd"&gt;a more detailed version&lt;/a&gt; of what was changed...&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;Bootstrap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Sass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;provides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;advantages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;previous&lt;/span&gt;
&lt;span class="vg"&gt;buggy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;global&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;standard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;place&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;well&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;typographic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;changes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;spacing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;We&lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;re also taking advantage of&lt;/span&gt;
&lt;span class="vg"&gt;Bootstrap&lt;/span&gt;&lt;span class="mf"&gt;-2.0&lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;s &amp;quot;responsive&amp;quot; grid, and the site looks great in&lt;/span&gt;
&lt;span class="vg"&gt;both&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;desktop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;mobile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;browsers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;practically&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="vg"&gt;I&lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;ve also completely refactored the aging CSS framework into one&lt;/span&gt;
&lt;span class="vg"&gt;based&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;elements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;roles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;It&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;complete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;yet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="vg"&gt;There&lt;/span&gt;&lt;span class="c1"&gt;&amp;#39;s an additional file called &amp;quot;support&amp;quot; which is responsible&lt;/span&gt;
&lt;span class="vg"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;holding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;mixins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;variables&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="vg"&gt;We&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;also&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;loading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Bootstrap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;through&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;Sprockets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;thanks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;a&lt;/span&gt;
&lt;span class="vg"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;ru&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;ripped&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="vg"&gt;gist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="il"&gt;2143990&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="vg"&gt;CHANGELOG&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;fixed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;nonexistant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;task&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;refactored&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;assets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;group&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;refactored&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;rackup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bootstrap&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="vg"&gt;sass&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;assets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bundler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;setup&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;rid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="vg"&gt;framework&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;status_exchange&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;rackup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="vg"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;now&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;framework&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;gems&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;integrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;css&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;framework&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;emphasizing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;classes&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;roles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;markup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;has&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;been&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;modified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;to&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="vg"&gt;suit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;responsive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bootstrap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;grid&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;removed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;octopress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;folder&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;support&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;partial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;mixins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;variables&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;colors&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;removed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;bootstrap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;CSS&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;based&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;changes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;aside&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gotta give some shoutouts @mdo and @fat for building such an awesome CSS framework, Thomas McDonald for porting it to Sass, and @sstephenson for the amazingly useful Sprockets framework. Much love.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>weaning off oh my zsh</title>
      <pubDate>18 Mar 2012</pubDate>
      <link>http://psychedeli.ca/2012/03/18/weaning-off-oh-my-zsh</link>
      <guid>http://psychedeli.ca/2012/03/18/weaning-off-oh-my-zsh</guid>
      <description>&lt;p&gt;Since December 2011, I&amp;#39;ve been working with &lt;a href="http://www.zsh.org/"&gt;ZSH&lt;/a&gt;, an alternate shell for *nix-based operating systems which has conventions similar to &lt;a href="http://www.gnu.org/software/bash/"&gt;BASH&lt;/a&gt;, ZSH adds a number of more modern features to the standard shell fare, such as more customization options for your prompt and extendable autocompletion. To get started on it, I&amp;#39;ve employed the lovely &lt;a href="https://github.com/robbyrussell/oh-my-zsh"&gt;Oh My ZSH&lt;/a&gt; framework which helps to organize your ZSH settings (&lt;code&gt;.zshrc&lt;/code&gt;) and use functionality developed by others so you can explore the wonderful possibilities of this awesome shell.&lt;/p&gt;

&lt;p&gt;Oh My ZSH was designed for new users, and is meant to be replaced at some point in the future by a &lt;code&gt;.zshrc&lt;/code&gt; that handles everything. This was also my eventual goal, but after getting more comfortable with Oh My ZSH, I began realizing that I would be missing out on a number of enhancements it gives my shell experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; A big part of my love for Oh My ZSH is its plugin architecture. With a shitload of premade plugins and the ability to easily add your own, incorporating new programs/functionality into my current shell workflow is trivial. For example, I began using &lt;a href="https://github.com/nvie/gitflow"&gt;git flow&lt;/a&gt; yesterday, a plugin based on &lt;a href="http://nvie.com/posts/a-successful-git-branching-model/"&gt;Nvie&amp;#39;s &amp;quot;A successful git branching model&amp;quot; blog post&lt;/a&gt; and after enabling the plugin found that it was incredibly easy to work with. Through subsequent trial and error, this same functionality would have taken days to implement (making small changes/additions here and there), but with the plugin I was able to just start using git-flow using conventional 3-character aliases, just like my interface to git, with the same level of autocompletion I&amp;#39;ve come to expect from ZSH&amp;#39;s powerful engine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrency:&lt;/strong&gt; Oh My ZSH has an update function that it fires each week to keep the plugins directory up to date. When new technologies are made available, it doesn&amp;#39;t take very long before a plugin for that software is added to the Oh My ZSH repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built-in functionality:&lt;/strong&gt; In addition to its massive plugin library, Oh My ZSH also comes with a collection of aliases, functions and variables for use in your scripts and everyday use. This useful built-in functionality is stuff I use on an everyday basis for prompt display, general hackery, and other fun shell tasks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I need a framework for ZSH that can accomplish these goals, but doesn&amp;#39;t bother with the theming or tricks designed to enable newbies to use ZSH. As someone mildly comfortable with this shell already, I want something a little more powerful but maybe not so easy to use.&lt;/p&gt;

&lt;h2&gt;Introducing DOTS&lt;/h2&gt;

&lt;p&gt;The features of Oh My ZSH I highlighted above make it a possibility to use as a power user of ZSH. But as the aim of the Oh My ZSH project is to help newer users get acquainted with the shell, I&amp;#39;ve decided to start my own project, forked from Oh My ZSH but without the newbie sugar like themes and installation management tasks. I figure everyone can figure that out on their own. The idea behind this framework is for you to fork it, and maintain that fork with your own &amp;quot;dot files&amp;quot;, scripts and other home-dir tools you need for general hackery. Once again, it&amp;#39;s meant as a starting point but it strips away unnecessary shit that you&amp;#39;re never, ever going to use.&lt;/p&gt;

&lt;h3&gt;Git it!&lt;/h3&gt;

&lt;p&gt;So you wanna try it out? First, uninstall Oh My ZSH! (&lt;code&gt;rm -rf ~/.oh-my-zsh&lt;/code&gt;) and run this little diddy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="vg"&gt;L&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="vg"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;tubbo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;dots&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;master&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="vg"&gt;install&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="vg"&gt;sh&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Persisting your dot files&lt;/h3&gt;

&lt;p&gt;Not only is DOTS designed to take care of your basic ZSH tasks, it also persists your home directory configuration files (&amp;quot;dot files&amp;quot;) across your machines. To invoke this feature, simply type the following in your home directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;persist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;gemrc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(or whatever file you want persisted)&lt;/p&gt;

&lt;p&gt;This will move the file to &lt;code&gt;~/.dots/config/gemrc&lt;/code&gt;, add it to the git repository, and symlink &lt;code&gt;~/.gemrc&lt;/code&gt; to &lt;code&gt;~/.dots/config/gemrc&lt;/code&gt;. You can now commit this file into Git and synchronize it across machines when you update dots!&lt;/p&gt;

&lt;p&gt;To stop persisting a file, type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="vg"&gt;forget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vg"&gt;gemrc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will replace the symlink with the file it&amp;#39;s linked to and remove it from the Git repository. You will have to make a commit to confirm this change.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>the role of the ajax call</title>
      <pubDate>11 Dec 2011</pubDate>
      <link>http://psychedeli.ca/2011/12/11/the-role-of-the-ajax-call</link>
      <guid>http://psychedeli.ca/2011/12/11/the-role-of-the-ajax-call</guid>
      <description>&lt;p&gt;I wanted to touch a little on this topic in public because I feel it&amp;#39;s something many Rails developers don&amp;#39;t get about JavaScript. This was inspired by an email I got, as well as countless discussions I&amp;#39;ve had with both my co-workers and fellow programmers I&amp;#39;ve helped out on IRC. I think a lot of programmers could benefit from this information so you don&amp;#39;t run into this issue yourself.&lt;/p&gt;

&lt;h2&gt;The Ajax request.&lt;/h2&gt;

&lt;p&gt;It&amp;#39;s really nice, isn&amp;#39;t it? You can do a lot of things with it, you can even download other JavaScript code asynchronously and execute it. This has proven, however, to be somewhat dangerous. While reviewing my co-workers&amp;#39; CMS code to find out why it was spitting errors out all the time, I noticed that he was constantly passing JavaScript in Ajax requests back and forth and expecting them to execute properly. While at one time they may have, for some reason now they get errors like &lt;code&gt;$ is not defined&lt;/code&gt;, even though &lt;code&gt;jquery.js&lt;/code&gt; is right there in the Net panel of Firebug. What it boiled down to was that our browser (Firefox) was refusing to allow access to previously loaded libraries on the page to Ajax-requested JavaScript.&lt;/p&gt;

&lt;p&gt;This was an example in PHP, but Ruby on Rails also suffers from this potential disaster. Rails developers can create &lt;code&gt;.js&lt;/code&gt; files that their views respond Ajax requests to. Typically, these files are JavaScript code segments that are supposed to be executed when they run. But they don&amp;#39;t always get executed like that. Sometimes, the browser refuses to load the library, and other times the JavaScript simply fails to run, even though it&amp;#39;s in the page. It&amp;#39;s as if it was plain text, but not being displayed because it&amp;#39;s in a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. This entire post was inspired by an email I got from a Rails developer attempting to pass JavaScript code and HTML simultaneously in a modal dialog. He was using the Rails JavaScript view system, a now deprecated means of transferring data between the Rails application&amp;#39;s controller and helper layers and the JavaScript logic on the view layer.&lt;/p&gt;

&lt;h2&gt;Our Solution&lt;/h2&gt;

&lt;p&gt;We decided to solve this by changing the way we wrote Ajax requests in the CMS. It was much more efficient to use Ajax as a static data transfer mechanism, rather than a means of transferring logic code between files. So instead of getting back &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags with code in it, we got back JSON data and used that to execute that segment of JavaScript code. PHP makes this easy, as it allows any Array to be encoded into valid JSON. So what we did was respond with something like this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Cache-Control: no-cache, must-revalidate&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-type: application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;status&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;success&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;markup&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;div class=&amp;quot;success&amp;quot;&amp;gt;Successfully saved changes to the file.&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instead of merely &lt;code&gt;echo&lt;/code&gt;ing that HTML in a String, we are wrapping it with JSON and returning that. Notice that you need &lt;a href="http://snippets.dzone.com/posts/show/5882"&gt;special HTTP headers&lt;/a&gt; to return a valid JSON response, some browsers attempt to guess based on the content but you can&amp;#39;t really rely on that. To ensure that the browser is interpreting this response as JSON, you must specify the HTTP &lt;code&gt;Content-Type&lt;/code&gt; as &lt;strong&gt;application/json&lt;/strong&gt;. I&amp;#39;ve also included a &lt;code&gt;Cache-Control&lt;/code&gt; directive which forces the browser to reload the content every time it loads. This ensures that browsers won&amp;#39;t cache these requests, because your data is always changing.&lt;/p&gt;

&lt;p&gt;So now, we can write some JavaScript to process that data. We like to use the &lt;a href="http://jquery.malsup.com/form/"&gt;jQuery.form&lt;/a&gt; plugin &lt;a href="http://aplusldesign.com/"&gt;at the office&lt;/a&gt;...&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#saveForm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;ajaxSubmit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ajax/saveChanges.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;dataType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#status&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;markup&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slideDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#status&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slideUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That extension to the &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; library simply submits a form asynchronously, and its &lt;code&gt;options&lt;/code&gt; Object lets you bind actions to the various &lt;code&gt;jQuery.ajax&lt;/code&gt; callbacks.&lt;/p&gt;

&lt;h2&gt;A little philosophy&lt;/h2&gt;

&lt;p&gt;So now you know the code, but it&amp;#39;s time to learn about why exactly I chose to do it this way.&lt;/p&gt;

&lt;h3&gt;Ajax is for transferring data, not logic&lt;/h3&gt;

&lt;p&gt;You can boil every Ajax call down to one formula: send request, receive response, execute callback(s). This is, after all, the basic format of an HTTP request. Knowing this, you can design your Ajax requests to simply be informational, then when a response is received you execute the JavaScript inside its success callback. This may be a bit confusing to debug, but it&amp;#39;s a little easier if you extrapolate every call to a function in the same external .js file, and name your functions by the action they perform. This ensures an application that performs exactly as you expect it. You&amp;#39;ll never have to hunt through HTML code in an Ajax response, nor will you ever have a question as to what type of content you&amp;#39;re getting from this particular HTTP request.&lt;/p&gt;

&lt;h3&gt;Standardize your JSON response&lt;/h3&gt;

&lt;p&gt;Once you&amp;#39;ve gotten this pattern down, it&amp;#39;s important to keep a standard practice when creating your JSON responses. Lets say you want to &lt;code&gt;GET&lt;/code&gt; an object, like a Post, from your blog. Fortunately, you&amp;#39;ve written a small PHP script that will return it from the database. Let&amp;#39;s just say, for shits and giggles (and because it&amp;#39;s almost 2:00am and I don&amp;#39;t feel like writing it out), that this PHP script works and returns the following JSON response:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;SELECT title, body FROM `posts` WHERE `id` = &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysql_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;mysql_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;database&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Error: Shit don&amp;#39;t work!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Right now, this doesn&amp;#39;t follow a standard practice. &lt;code&gt;response.message&lt;/code&gt; would have to be tested on the client side to see if this is an error or not. That&amp;#39;s no way to do business, especially if you may need multiple messages or styles for each message. A better way to create this JSON would be to do&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;SELECT title, body FROM `posts` WHERE `id` = &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysql_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;mysql_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;database&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;type&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;success&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;post&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;type&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;warning&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Post not found&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;type&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No ID passed&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Cache-Control: no-cache, must-revalidate&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-type: application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We know that if &lt;code&gt;response.type&lt;/code&gt; is &amp;quot;success&amp;quot;, then &lt;code&gt;response.post&lt;/code&gt; will be defined and we can work with it. But if &lt;code&gt;response.type&lt;/code&gt; is &amp;quot;error&amp;quot;, we will know that &lt;code&gt;response.message&lt;/code&gt; is defined and we need to display it. The JavaScript can use a &lt;code&gt;switch&lt;/code&gt; statement to parse other types of messages like &amp;quot;warning&amp;quot; or &amp;quot;info&amp;quot;, which we may use in the future. Altering your JSON responses to be standard now will save you much testing and coding time in the future. Observe how much more informative these error messages are, and how much more flexible your code is after this alteration.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>innovators with the biggest impact on society</title>
      <pubDate>24 Nov 2011</pubDate>
      <link>http://psychedeli.ca/2011/11/24/innovators-with-the-biggest-impact-on-society</link>
      <guid>http://psychedeli.ca/2011/11/24/innovators-with-the-biggest-impact-on-society</guid>
      <description>&lt;p&gt;A response I made to &lt;a href="http://forums.somethingawful.com"&gt;a thread on the Something Awful forums&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tim Berners-Lee&lt;/strong&gt; is the innovator who made the biggest impact on society. He created the Web and laid out guidelines to ensure that it would never become the 
capitalist nickel-and-dime cesspool that the Mobile Web was created to be. Instead, he built the Web to enforce open-source principles (go ahead, try and hide your 
JavaScript code from me...), and released it to academia first to ensure it would grow as an information hub rather than a marketing tool. While others have taken the 
Web and warped it for their own financial interests, Tim Berners-Lee has contented to teach and further the concept of a place where humanity could finally be free to 
experience anything they wanted, or learn about anything they wanted, in seconds.&lt;/p&gt;

&lt;p&gt;In my opinion, the Web is still the only 24/7 place in the world where you can really say and do anything you want. It&amp;#39;s the reason why most of the music industry has 
come to terms with the fact that doing your own thing and doing what you love to do is the ONLY reason to be a musician these days, because the Internet and the 
principles of the WWW have made it so the labels can&amp;#39;t control the industry anymore. It&amp;#39;s no longer a legal monopoly. Web connectivity is the major reason why the Arab 
Spring protests could even happen in the first place, without government control they were able to access new ideas and organize effectively. The anger has been in 
their blood since the 60&amp;#39;s, but the Web made it all coalesce so it could drive their oppressors out of the country.&lt;/p&gt;

&lt;p&gt;Not only that, but Tim continues to contribute to the Web&amp;#39;s ecosystem and publishes papers and articles commenting on the state of the Web, how certain companies are 
furthering its intended purpose and how some of them are actually diminishing it.&lt;/p&gt;

&lt;p&gt;So yeah. Have any of the people mentioned thus far built technology that allowed a revolution to happen? Not a revolution involving the exchange of money, but a REAL one?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Interesting how much advertising affects our life that we miss some of the great innovators simply because they didn&amp;#39;t want to/have to market their product.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>a new beginning</title>
      <pubDate>20 Aug 2011</pubDate>
      <link>http://psychedeli.ca/2011/08/20/a-new-beginning</link>
      <guid>http://psychedeli.ca/2011/08/20/a-new-beginning</guid>
      <description>&lt;p&gt;So here we go, another new layout and another re-hash of this blog&amp;#39;s content. I threw away the last two iterations (still have the data, though) of this blog, because I was unsatisfied with the poor content on it. So let&amp;#39;s start again.&lt;/p&gt;

&lt;p&gt;This will be a blog about programming, music, philosophy, and everything in between.&lt;/p&gt;

&lt;h2&gt;first of all, the blog&lt;/h2&gt;

&lt;p&gt;This blog is not in its final design. I just felt like I needed a place online to express my feelings and my experiences throughout life, and regardless of what it looks like I feel as though it needs to be on my domain, at all costs. That&amp;#39;s why I&amp;#39;ve made deployment as easy as possible. All I have to do is a &lt;code&gt;git push&lt;/code&gt; to my remote server, and the hook on the remote will generate the &lt;a href="http://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; site on &lt;a href="http://psychedeli.ca"&gt;http://psychedeli.ca&lt;/a&gt;, which will then push the update directly to the userbase. Pretty nifty, I think! &lt;/p&gt;

&lt;h2&gt;burning man&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ll be attending &lt;a href="http://burningman.com/"&gt;Burning Man&lt;/a&gt; this year, but I will not be performing. Instead of gifting music to the playa, I&amp;#39;ve decided to make this year my vacation. Sometimes I tend to get rather stressed out before and after performing, and I don&amp;#39;t want that to encroach on my good time this year on the playa. This year, I&amp;#39;ll be gifting something very different to the denizens of Black Rock City. In exchange for a free ride to and from the playa, I&amp;#39;ll be driving a 24&amp;#39; Budget truck for another camp, Club Verboten, out of Reno. This is interesting on two levels: First of all, while I have driven rental trucks I&amp;#39;ve never driven one this big, so that&amp;#39;s going to be an adventure in itself getting onto the desert in this thing. Second, I&amp;#39;m going to arrive in Black Rock City about two days before the festival starts. I hear it&amp;#39;s a great time, and a unique experience in and of itself, to see the playa before it&amp;#39;s really built up. &lt;/p&gt;

&lt;h2&gt;the wonder bars&lt;/h2&gt;

&lt;p&gt;We&amp;#39;re currently recording our first album! Aaron and Jules and I are prepared to do live recordings of the instruments and finally realize a project that&amp;#39;s been literally two years in the making. We have not decided on how we are going to distribute this album. We also have not determined the length of the album just yet, as I&amp;#39;ve begun to collaborate with other members of the band on a few more tracks than the initial planned 12 that I&amp;#39;ve written entirely. A full post about that is coming soon.&lt;/p&gt;

&lt;h2&gt;i&amp;#39;ll be seeing you&lt;/h2&gt;

&lt;p&gt;Well, that&amp;#39;s about it. I&amp;#39;m committed to writing more in this thing about my future experiences, as I think it would be a good idea for my own mental health if I could get a lot of these feelings off my chest.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>incorporating ultrabeat into my workflow</title>
      <pubDate>26 Jun 2011</pubDate>
      <link>http://psychedeli.ca/2011/06/26/incorporating-ultrabeat</link>
      <guid>http://psychedeli.ca/2011/06/26/incorporating-ultrabeat</guid>
      <description>&lt;p&gt;Thanks to &lt;a href="http://www.facebook.com/pages/The-Architech/207961419245874"&gt;The Architech&lt;/a&gt; coming over and showing me some of the more interesting features of Ultrabeat, my drum composition has changed tremendously. I used to use ReDrum, a noble and wonderful little drum machine packaged into Reason, because of its familiar look-and-feel (its UI is modeled after the TR-909) and dead-simple feature set that was not only easy to comprehend, but easy to manipulate in a live setting. But composing in ReDrum has its drawbacks, and composing in Ultrabeat works better with the way I think drums ought to be composed in electronic music. However, this presents an interesting problem: since my live setup relies on Reason for drum beats, how am I going to get Ultrabeat patterns and sounds in Reason?&lt;/p&gt;

&lt;h2&gt;a little evangelism&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://starkey-music.com"&gt;Starkey&lt;/a&gt; turned me onto Ultrabeat at my last semester of UArts during a L.A.C.E. (Laptop And Controller Ensemble, a short-lived ensemble group established by Starkey and composed of UArts students who had an interest in live electronic performance) rehearsal one Tuesday night. He builds all his beats with the plugin, but the way he introduced it to me was describing a bug he had where it CRASHED Logic! Not a really good place to start...leaving me a little prejudice against its reliability until I had a conversation with &lt;a href="http://www.facebook.com/pages/The-Architech/207961419245874"&gt;Architech&lt;/a&gt; a few months ago at an Arts Garage party. It eventually led to him coming over to check out the empty room in my house (which he didn&amp;#39;t take) and us educating each other about music. One of the most interesting things he taught me was some of the concepts of Ultrabeat that are really, really cool, and basically devalue my earlier reasons for not using the plugin.&lt;/p&gt;

&lt;h2&gt;the old-fashioned way&lt;/h2&gt;

&lt;p&gt;I&amp;#39;d like to illustrate my former workflow for dealing with drums. The major problem with drums, and this is why they can&amp;#39;t just be bounced and used like any other track, is that the sound of all the other tracks revolve around the sidechain compression of the kick and/or snare. So these tracks need to be extrapolated at all times so the compressors can use them as keys for the sidechain. This is a major component of the house sound in general (plus, it sounds cool), and thus needs to be carried over into live performance from the studio. While screwing around during a rehearsal, I discovered that Reason files can be opened/closed at will &lt;em&gt;without affecting the sequencer&lt;/em&gt;, so when I have one .rns file open and open another one simultaneously, I can close the first one without affecting the sound of the sequencer. Hopefully. There have been times where the computer simply gets overloaded and can&amp;#39;t handle all that instruction at once, wherein the sound &amp;quot;hiccups&amp;quot; a little. To date, this has never happened to me in a live performance, but I still don&amp;#39;t want to risk it. There must be a cleaner way to do this...&lt;/p&gt;

&lt;h2&gt;the new hotness&lt;/h2&gt;

&lt;p&gt;Ultrabeat is like any other drum machine. It&amp;#39;s got a 32-square pattern sequencer and 16 separate sample tracks, each with their own dynamics control (as if they were just normal Logic tracks), and additional options for crafting the drum sound like a drum synth, filters and envelope definition. There can be an unlimited amount of patterns stored inside the plugin itself, but I almost never save my patterns, instead opting to click the grid icon next to the pattern chooser and dragging the current pattern into Logic&amp;#39;s arrangement window, where it is added to the Ultrabeat track as MIDI. This MIDI controls the entire drum machine, allowing you to create &amp;quot;evolving&amp;quot; beats that can change every 2 bars (or longer), and so you can easily see which patterns are being invoked on each measure. By using Ultrabeat, and adopting a more MIDI-centric workflow, my &lt;a href="http://soundcloud.com/wonderbars/just-the-start"&gt;new&lt;/a&gt; &lt;a href="http://soundcloud.com/wonderbars/spokes-on-a-wheel"&gt;songs&lt;/a&gt; have taken on quite a different character in the drum track. Since it&amp;#39;s so much easier now to create different types of beats in my drum machine, I&amp;#39;m able to push further and explore more variants of beats.&lt;/p&gt;

&lt;p&gt;One of the things I like about Ultrabeat&amp;#39;s UI is that it can be altered to fit your current workflow. What if you have the sounds you&amp;#39;re looking for, but you want to actually sit down and write the pattern? Hit &amp;quot;Pattern view&amp;quot; and the sound-editing options will disappear, leaving you with a huge grid to play with. But what if that kick is filtered a little too high? No problem, just click the track and hit &amp;quot;Full view&amp;quot; to bring up the sound editing options, where you can alter the filter. Notice that below the editor, you can edit the pattern for just this track. Reason users may find this interface to be a little more at-home ( I know I did) because you&amp;#39;re used to editing one track at a time. But I strongly recommend moving over to the pattern view way of composing, it&amp;#39;s much easier to create cleaner drum tracks that don&amp;#39;t collide with each other. &lt;/p&gt;

&lt;p&gt;So Ultrabeat is a great interface for working with drums, but how about controlling the sound after the drums have been synthesized? 99% of the time, I have to apply some mastering plugins to get the drum sound I want out of Ultrabeat and my TR-808/909 samples. With Reason, I was able to totally control the routing of each drum track and establish compression/filtering for each separate drum sound. This gave each of my tracks a professional, heavy and floor-filling sound that was quite malleable yet easy to deal with. My father once told me that production-wise, the foundation of the track, drums and bass normally, may be the most important elements of the whole song, and I&amp;#39;ve always strived to make this foundation both interesting and prominent, regardless of the genre I&amp;#39;m working with. It may also be a reason for why I enjoy creating electronic music, and house/dance specifically, because of this attention paid on the foundation. It&amp;#39;s just not House without a booming kick &amp;amp; funky bass line!&lt;/p&gt;

&lt;p&gt;This is where it gets interesting. Because Ultrabeat is built into Logic, we can actually create Aux tracks from the drum kit itself, and extrapolate some of the drums into their own separate mono tracks. From here, we can EQ, add effects and generally craft each drum sound just the same as we could with Reason. You can even apply separate automation for each drum aux and really get down-and-dirty with controlling the sound. After learning all of this, I decided it was time to finally abandon ReDrum for composing, and totally immerse myself into this new plugin that greatly accelerated my workflow and taught me a LOT about Logic.&lt;/p&gt;

&lt;h2&gt;bringing it all back home&lt;/h2&gt;

&lt;p&gt;So now I have these new tunes created in Ultrabeat, but how do I play them live? This question plagued me for weeks after I realized a month ago I would need to somehow extract these drum parts and use them in Ableton. But Ableton doesn&amp;#39;t support Ultrabeat, so a major disconnect was taking place. My old workflow used Reason for the drums, so it was easy to just open the file in ReWired Ableton and play it through a couple audio tracks. But now that I no longer use Reason to compose drums in, I need to figure out a way to migrate the drum patterns I come up with into a sequences I can trigger easily and efficiently.&lt;/p&gt;

&lt;p&gt;After doing some tests, I discovered that Ultrabeat&amp;#39;s MIDI output is standardized General MIDI for drums, and therefore can be imported directly into Ableton Live (each region even becomes its own clip!) and pumped via ReWire to the Reason instance. My Reason files are now simply used for saving the preset sounds of each song&amp;#39;s drum kit, and Ableton will now sequence the patterns like it was meant to do originally.&lt;/p&gt;

&lt;p&gt;This part is actually a little confusing, but it makes sense in the end. What you have to do is select the MIDI regions you want in Logic (I usually group by song form: verse beats, chorus beats, etc.) and go to &lt;strong&gt;File &amp;gt; Export.. &amp;gt; Selection as MIDI File&lt;/strong&gt;, and then create a new directory called &amp;quot;MIDI Files&amp;quot; in your Logic project folder. Name the file after its form name, so &amp;quot;drums-verse.mid&amp;quot;, etc. This allows you to use MIDI in other ways, like for example if you use a VST you can simply open the VST in Ableton and pump in MIDI/presets you created in Logic. This allows you to alter the sound on the fly for your particular PA system (they&amp;#39;re all different, I find myself doing a lot of audio engineering work at the beginning of a set to make the speakers react to my music properly). &lt;/p&gt;

&lt;p&gt;To import this MIDI into Ableton, create a new MIDI track for holding drum patterns (I called mine &amp;quot;Drums&amp;quot;), and simply track the &lt;code&gt;.mid&lt;/code&gt; file into the track. The clips will show up horizontally, simply drag them into subsequent vertical rows in your Live Set to establish a proper order for the drums to go in. By clicking these clips directly, you can invoke the MIDI for each drum pattern.&lt;/p&gt;

&lt;p&gt;In Reason, create a new file and remove the mixer. Add in a ReDrum plugin instance and set up the drums in exactly the same order as you have them in Ultrabeat. So for example, if your drum sample order looks like: &lt;code&gt;kick, snare, claps, open hat, closed hat, ride&lt;/code&gt; in Ultrabeat, that&amp;#39;s what you&amp;#39;d want in Reason. Mute out the tracks that aren&amp;#39;t pre-set this way to avoid wayward notes triggering drums that aren&amp;#39;t set up properly. Hit &amp;quot;Tab&amp;quot; to get the routing panel, and route the kick &amp;amp; snare into separate aux channels in Reason&amp;#39;s hardware interface patchbay, then take those channels as input into Ableton for your kick &amp;amp; snare tracks. This will extract just the kick &amp;amp; snare into separate tracks so you can set sidechains for them in other instruments. Ableton&amp;#39;s compressor has sidechain built in now, so no need for extra VSTs taking up your memory!&lt;/p&gt;

&lt;p&gt;So now you have Reason set up to read MIDI from Ableton, and to pump drum audio back into the sequencer through 3 separate tracks. This is the way I do things live and at home, and I hope it helps your workflow because it&amp;#39;s certainly helped mine!&lt;/p&gt;
</description>
    </item>
    <item>
      <title>decisions, decisions</title>
      <pubDate>9 Apr 2011</pubDate>
      <link>http://psychedeli.ca/2011/04/09/decisions-decisions</link>
      <guid>http://psychedeli.ca/2011/04/09/decisions-decisions</guid>
      <description>&lt;p&gt;Well I&amp;#39;m stuck in a bind. I can&amp;#39;t seem to decide which operating system I want to run my all-powerful file server. A few days ago, my &lt;a href="http://geekwitch.livejournal.com/"&gt;wonderful sister&lt;/a&gt; gifted me two computers, the Dell OptiPlex &lt;a href="http://support.dell.com/support/edocs/systems/opgx270/en/ug/index.htm"&gt;GX270&lt;/a&gt; and &lt;a href="http://support.dell.com/support/edocs/systems/opgx280/en/ug/index.htm"&gt;GX280&lt;/a&gt;. The basic difference between these two tried-and-true workhorses is the graphics card interface-the GX280 includes a PCI Express x16 slot whereas the GX270 is still using AGP-and of course the model number. Other than that, they use the same motherboard, same case design, and same basic layout. PERFECT for general hackery purposes...and running a Boxee...&lt;/p&gt;

&lt;p&gt;So my first endeavor with these machines is something I&amp;#39;ve been needing for a long time: a file server to host all of the house&amp;#39;s media. Everyone who lives in my house utilizes the internet or computers mostly for their media needs, and we&amp;#39;ve been longing for a way to experience it on a bigger screen. But a problem arises: These machines do not have the ability to pump S-Video to my regular TV, so I&amp;#39;m gonna need to wait a couple days before actually going ahead and opening up the boxes. I also need SATA cables and a SATA-to-IDE converter because the Dell OptiPlex motherboards come with IDE by default! By using both the SATA connector and the IDE connector adapted to a SATA connection, I&amp;#39;ll be able to run a software RAID-0 array, mirroring the contents of the 1TB of space inside the box and therefore providing a greater level of security and stability to the system as a whole. With all of the hits it will be getting, this is a crucial step in extending the server&amp;#39;s lifespan. &lt;/p&gt;

&lt;p&gt;This is actually a good thing, because it gives me a bit more time to decide on an operating system. What I need is very simple, I&amp;#39;ve boiled it down to only a few requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I want ZFS.&lt;/strong&gt; It&amp;#39;s amazing, the technology we have today. ZFS is this wonderful file system developed by the good ol&amp;#39; boys over at &lt;a href="http://support.dell.com/support/edocs/systems/opgx280/en/ug/index.htm"&gt;Sun Microsystems&lt;/a&gt; (now &lt;a href="http://sun.com"&gt;Oracle&lt;/a&gt;) that addresses many of the problems of former filesystems and even some of the problems of magnetic hard drives themselves. ZFS even introduces new features like built-in SMB/Netatalk capabilities, making it a lot easier to transfer data from the server to the computers where it will actually be useful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I want complete Boxee transparency.&lt;/strong&gt; The Boxee will be the major customer of this server, constantly pulling data from the media drive &amp;quot;/Zappa&amp;quot; to fulfill its users demands of the music library. Now that all music can be accessed from the living room&amp;#39;s 3-way stereo system, I&amp;#39;m predicting that my roommates will be hitting the Boxee a lot more, and thus the fileserver.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right now, my best option is &lt;strong&gt;&lt;a href="http://freenas.org"&gt;FreeNAS&lt;/a&gt;&lt;/strong&gt;, it&amp;#39;s a distribution of &lt;a href="http://en.wikipedia.org/wiki/Firefly_Media_Server"&gt;FreeBSD&lt;/a&gt; (an OS I know and love) that&amp;#39;s specially formulated to act as a network storage device. Precisely what I&amp;#39;m looking for! It&amp;#39;s even bundled with a &lt;a href="http://en.wikipedia.org/wiki/Firefly_Media_Server"&gt;DAAP server&lt;/a&gt; and &lt;a href="http://psychedeli.ca/code/2011/09/25/hell-yeah-freenas"&gt;NFS&lt;/a&gt; so the Boxee can be &amp;quot;tricked&amp;quot; into thinking /Zappa &lt;em&gt;is actually a part of its own local filesystem&lt;/em&gt;. The possibilities are endless, allowing for seamless integration of the data on these disks to the entire network here at 1913.&lt;/p&gt;

&lt;p&gt;I think my choice has been made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; My FreeNAS file server is running smoothly, fully jailed. Story at 11.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technorati Claim ID:&lt;/strong&gt; NFGKYZ5CMSY2&lt;/p&gt;
</description>
    </item>
  </channel>
</rss>
