<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[NoMethodError]]></title>
  <link href="http://nomethoderror.com//atom.xml" rel="self"/>
  <link href="http://nomethoderror.com//"/>
  <updated>2015-05-30T13:15:52-05:00</updated>
  <id>http://nomethoderror.com//</id>
  <author>
    <name><![CDATA[Travis Roberts]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[ActiveAdmin: Redirect to Index on Create/Update]]></title>
    <link href="http://nomethoderror.com//blog/2014/03/10/activeadmin-redirect-to-index-on-create-update/"/>
    <updated>2014-03-10T21:46:18-05:00</updated>
    <id>http://nomethoderror.com//blog/2014/03/10/activeadmin-redirect-to-index-on-create-update</id>
    <content type="html"><![CDATA[<p>By default, <a href="http://activeadmin.info/">ActiveAdmin</a> will display the <code>:show</code> action on create or update of a resource. Personally, I&rsquo;d rather redirect to the <code>:index</code> action as long as the resource is valid.</p>

<p>You can overwrite ActiveAdmin&rsquo;s default behavior using the <code>controller</code> block.</p>

<div><script src='https://gist.github.com/9478684.js'></script>
<noscript><pre><code>ActiveAdmin.register User do
  
  # ...truncated code...
  
  controller do
    def create
      super do |format|
        redirect_to collection_url and return if resource.valid?
      end
    end

    def update
      super do |format|
        redirect_to collection_url and return if resource.valid?
      end
    end
  end

end</code></pre></noscript></div>


<p>Notice, I&rsquo;m adding &ldquo;if resource.valid?&rdquo; to make sure we only redirect when there are no validation errors. If we didn&rsquo;t have that extra bit, the actions would <strong>always</strong> redirect to the <code>:index</code> action regardless.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Simple Rails Form Honeypot]]></title>
    <link href="http://nomethoderror.com//blog/2014/02/26/simple-rails-form-honeypot/"/>
    <updated>2014-02-26T20:48:48-06:00</updated>
    <id>http://nomethoderror.com//blog/2014/02/26/simple-rails-form-honeypot</id>
    <content type="html"><![CDATA[<p>If you have a form on your Rails site, chances are you get a fair amount of spam submissions from automated bots. One solution for preventing spam is by using a captcha field. They usually work very well to prevent spam, but they add a burden to human users. Another, less intrusive solution is to use a honeypot. A honeypot is a field that only bots can see, so you can know a form submission is spam if that field has a value.</p>

<p>There are gems available that will add a honeypot for you, but if you prefer to implement it yourself, it&rsquo;s very straightforward.</p>

<p>In your form, just add an extra field that you&rsquo;ll use to detect unauthorized submissions. Make sure to name it something normal so spam bots will populate it. I prefer to use the name &ldquo;content&rdquo;. Notice that the field has its tabindex attribute set to -1. This will prevent the field from being selected if a user tabs through the field. I&rsquo;ve also added some inline hint text in case a user with a screen reader fills out the form.</p>

<div><script src='https://gist.github.com/9201887.js?file=1_form.erb'></script>
<noscript><pre><code>&lt;%= form_tag form_submit_path do %&gt;
  &lt;fieldset&gt;
    &lt;legend&gt;Contact Info&lt;/legend&gt;

    &lt;div class=&quot;form-group&quot;&gt;
      &lt;%= label_tag :name %&gt;
      &lt;%= text_field_tag :name %&gt;
    &lt;/div&gt;

    &lt;div class=&quot;form-group&quot;&gt;
      &lt;%= label_tag :email %&gt;
      &lt;%= text_field_tag :email %&gt;
    &lt;/div&gt;

    &lt;div class=&quot;form-group&quot;&gt;
      &lt;%= label_tag :phone %&gt;
      &lt;%= text_field_tag :phone %&gt;
    &lt;/div&gt;

    &lt;div class=&quot;form-group honeypot&quot;&gt;
      &lt;%= label_tag :content %&gt;
      &lt;%= text_field_tag :content %&gt;
      &lt;span class=&quot;help&quot;&gt;Do not fill in this field. It is an anti-spam measure.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/fieldset&gt;

  &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
&lt;%- end -%&gt;</code></pre></noscript></div>


<p>In your stylesheet, just add some styles to make sure that a human won&rsquo;t see the field on a desktop or mobile device.</p>

<div><script src='https://gist.github.com/9201887.js?file=2_styles.scss'></script>
<noscript><pre><code>.form-group {
  margin-bottom: 1em;
  width: 100%;

  &amp;.honeypot {
    position: absolute;
    left: -9999px;
  }
}</code></pre></noscript></div>


<p>The final step is to add a check in your controller to only process the form if the value of the field is blank. For me, I&rsquo;m only sending a notification email if the form submission is certified anti-spam.</p>

<div><script src='https://gist.github.com/9201887.js?file=3_controller.rb'></script>
<noscript><pre><code>class FormController &lt; ApplicationController

  def submit
    SiteMailer.contact(params).deliver unless params[:content].present? # honeypot check
    flash[:success] = &quot;Your message has been submitted. Thank you!&quot;
    redirect_to root_url
  end

end
</code></pre></noscript></div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ActiveAdmin: Custom MetaSearch Filter]]></title>
    <link href="http://nomethoderror.com//blog/2014/02/23/activeadmin-custom-metasearch-filter/"/>
    <updated>2014-02-23T17:06:00-06:00</updated>
    <id>http://nomethoderror.com//blog/2014/02/23/activeadmin-custom-metasearch-filter</id>
    <content type="html"><![CDATA[<p>Recently, I had the need to create a custom ActiveAdmin filter for a site I was working on. I couldn&rsquo;t find much information on the subject, but after digging around, it turns out that it&rsquo;s pretty easy.</p>

<p>Here are my (admittedly contrived) models. You can see that a User belongs to an Account and an Account belongs to a Group. For this example, let&rsquo;s say I want a filter in ActiveAdmin on the User resource that lists all the Groups.</p>

<div><script src='https://gist.github.com/fdae2afefe12dd888633.js?file=1_models.rb'></script>
<noscript><pre><code>class Group &lt; ActiveRecord::Base
  has_many :accounts
end

class Account &lt; ActiveRecord::Base
  has_many :users
  belongs_to :group
end

class User &lt; ActiveRecord::Base
  belongs_to :account
end</code></pre></noscript></div>


<p>Here&rsquo;s my simplified ActiveAdmin resource, with the added filter.</p>

<div><script src='https://gist.github.com/fdae2afefe12dd888633.js?file=2_user_resource.rb'></script>
<noscript><pre><code>ActiveAdmin.register User do
  index do
    column :id
    column :name
    column :email
    default_actions
  end

  filter :id
  filter :name
  filter :email
  filter :group, as: :select, collection: Group.order(:name)
end</code></pre></noscript></div>


<p>To hook it up to the model, I just need to add a scope and a call to the built-in MetaSearch method <code>search_methods</code>.</p>

<div><script src='https://gist.github.com/fdae2afefe12dd888633.js?file=3_user_model.rb'></script>
<noscript><pre><code>class User &lt; ActiveRecord::Base
  belongs_to :account

  search_methods :address # tells meta_search to use this method as a filter

  scope :group, -&gt;(group_id) { joins(:account =&gt; :group).where(&quot;groups.id = ?&quot;, group_id) }
end</code></pre></noscript></div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ActiveRecord Random Ordering with Pagination]]></title>
    <link href="http://nomethoderror.com//blog/2014/02/05/activerecord-random-ordering-with-pagination/"/>
    <updated>2014-02-05T21:18:00-06:00</updated>
    <id>http://nomethoderror.com//blog/2014/02/05/activerecord-random-ordering-with-pagination</id>
    <content type="html"><![CDATA[<p>When I created <a href="http://nshvll.org/">nshvll.org</a>, I wanted the ability to show the user a randomly ordered list of members. I also wanted to paginate the results, and I didn&rsquo;t know if it was possible to have both. After a little research, I found that you can pass a seed to the mySQL <code>RAND()</code> function and have it return an identical list each time it&rsquo;s called.</p>

<h2>mySQL</h2>

<p>Since I want each person to get a uniquely randomized list of members, I set a cookie with a seed which is randomly generated (1-100).</p>

<p>I set the seed in a <code>before_filter</code> in my <code>ApplicationController</code>.</p>

<div><script src='https://gist.github.com/8838030.js?file=application_controller_mysql.rb'></script>
<noscript><pre><code>class ApplicationController &lt; ActionController::Base
  before_filter :set_rand_cookie

  private
  
  def set_rand_cookie
    return if cookies[:rand_seed].present?
    cookies[:rand_seed] = {value: rand(100), expires: Time.now + 900}
  end
end</code></pre></noscript></div>


<p>Notice, I only set the cookie if it doesn&rsquo;t exist. I also set the expiration of the cookie to 15 minutes because I don&rsquo;t want the user to get the same list of members <em>all</em> the time.</p>

<p>Now, in the <code>MembersController</code>, I can pass that seed to mySQL and get a repeatable sequence of random records.</p>

<div><script src='https://gist.github.com/8838030.js?file=members_controller_mysql.rb'></script>
<noscript><pre><code>class MembersController &lt; ApplicationController

  def index
    @members = Member.order(&quot;RAND(#{cookies[:rand_seed]})&quot;).page(params[:page]).per(15)
  end
  
end</code></pre></noscript></div>


<h2>PostgreSQL</h2>

<p>A little while after I built the site, I decided to move it from a personal VPS to <a href="https://www.heroku.com/">Heroku</a>. To do that, I needed to convert the database to PostgreSQL (or pay for a mySQL option). After a little research, I found out that PostgreSQL is a bit trickier than mySQL when it comes to using a seed with the <code>random()</code> function. You have to run a separate select query to set the seed before the query that gets the list of records.</p>

<div><script src='https://gist.github.com/8838030.js?file=members_controller_postgres.rb'></script>
<noscript><pre><code>class MembersController &lt; ApplicationController

  def index
    Member.connection.execute(&quot;select setseed(#{cookies[:rand_seed]})&quot;)
    @members = Member.order(&#39;random()&#39;).page(params[:page]).per(15)
  end

end</code></pre></noscript></div>


<p>PostgreSQL&rsquo;s <code>setseed()</code> function requires a number between -1 and 1, so we need to switch to a random float instead of an integer in the <code>ApplicationController</code></p>

<div><script src='https://gist.github.com/8838030.js?file=application_controller_postgres.rb'></script>
<noscript><pre><code>class ApplicationController &lt; ActionController::Base
  before_filter :set_rand_cookie

  private
  
  def set_rand_cookie
    return if cookies[:rand_seed].present?
    cookies[:rand_seed] = {value: rand, expires: Time.now + 900}
  end
end</code></pre></noscript></div>


<p>There we go. A repeatable, randomized set of records in mySQL or PostgreSQL.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Track Backbone.js Page Views with Google Analytics]]></title>
    <link href="http://nomethoderror.com//blog/2013/11/19/track-backbone-dot-js-page-views-with-google-analytics/"/>
    <updated>2013-11-19T19:42:00-06:00</updated>
    <id>http://nomethoderror.com//blog/2013/11/19/track-backbone-dot-js-page-views-with-google-analytics</id>
    <content type="html"><![CDATA[<p>Google Analytics tracks page views based on evaluating the tracking code on page load. Backbone.js makes this difficult because the page never reloads. Fortunately, it&rsquo;s super easy to add a function to the Backbone router to manually track each route.</p>

<h2>Newer Analytics Code</h2>

<p>If your tracking code looks like below, then you have the newer Analytics tracking code that uses the <code>ga</code> function instead of the <code>_gaq</code> array.</p>

<div><script src='https://gist.github.com/9d05cb3d9c6d90408325.js?file=analytics_new.js'></script>
<noscript><pre><code>(function(i,s,o,g,r,a,m){i[&#39;GoogleAnalyticsObject&#39;]=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,&#39;script&#39;,&#39;//www.google-analytics.com/analytics.js&#39;,&#39;ga&#39;);

ga(&#39;create&#39;, &#39;UA-0000000-1&#39;, &#39;mysite.com&#39;);
ga(&#39;send&#39;, &#39;pageview&#39;);</code></pre></noscript></div>


<p>Add the following code to your router:</p>

<div><script src='https://gist.github.com/9d05cb3d9c6d90408325.js?file=router_new.js'></script>
<noscript><pre><code>initialize: function() {
  this.bind(&#39;route&#39;, this._pageView);
},

_pageView: function() {
  var path = Backbone.history.getFragment();
  ga(&#39;send&#39;, &#39;pageview&#39;, {page: path});
}</code></pre></noscript></div>


<h2>Old Analytics Code</h2>

<p>If your tracking code looks like this:</p>

<div><script src='https://gist.github.com/9d05cb3d9c6d90408325.js?file=analytics_old.js'></script>
<noscript><pre><code>var _gaq = _gaq || [];
_gaq.push([&#39;_setAccount&#39;, &#39;UA-0000000-1&#39;]);
_gaq.push([&#39;_trackPageview&#39;]);

(function() {
  var ga = document.createElement(&#39;script&#39;);
      ga.type = &#39;text/javascript&#39;;
      ga.async = true;
      ga.src = (&#39;https:&#39; == document.location.protocol ? &#39;https://ssl&#39; : &#39;http://www&#39;) + &#39;.google-analytics.com/ga.js&#39;;
  var s = document.getElementsByTagName(&#39;script&#39;)[0];
      s.parentNode.insertBefore(ga, s);
})();</code></pre></noscript></div>


<p>Add the following code to your router:</p>

<div><script src='https://gist.github.com/9d05cb3d9c6d90408325.js?file=router_old.js'></script>
<noscript><pre><code>initialize: function() {
  this.bind(&#39;route&#39;, this._pageView);
},

_pageView: function() {
  var path = Backbone.history.getFragment();
  _gaq.push([&#39;_trackPageview&#39;, &quot;/&quot; + path])
}</code></pre></noscript></div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using PhoneGap FileTransfer to Download Multiple Files to the Device]]></title>
    <link href="http://nomethoderror.com//blog/2013/11/17/using-phonegap-filetransfer-to-download-multiple-files-to-the-device/"/>
    <updated>2013-11-17T18:46:00-06:00</updated>
    <id>http://nomethoderror.com//blog/2013/11/17/using-phonegap-filetransfer-to-download-multiple-files-to-the-device</id>
    <content type="html"><![CDATA[<p>I&rsquo;ve been working recently on a <a href="http://phonegap.com/">PhoneGap</a> app that is designed to operate offline, and receives incremental data updates from an API when the user has an Internet connection. These incremental updates also include new/updated product images. Since the app needs to operate offline, I have to download the files to the device when they are updated or added so they can be shown offline.</p>

<p>PhoneGap has <a href="http://docs.phonegap.com/en/3.1.0/cordova_file_file.md.html">File and FileTransfer</a> plugins that allow you to access the device&rsquo;s file system and even upload/download files. The problem with these plugin are, almost all of the actions trigger callbacks, so it&rsquo;s hard to keep the thread of what is happening. The PhoneGap documentation for these plugins are slightly lacking, so it was difficult to figure out how to accomplish what I needed. Through a lot of Googling and trial &amp; error, I was finally able to get the following code working.</p>

<div><script src='https://gist.github.com/9c8c9f1cc8d8d002dd5e.js?file=image_download.js'></script>
<noscript><pre><code>imageDownloader = {
  updateImages: function() {
    this.remoteImages = [];
    // ...code to get all of the images we need to download...
    // in my app, it&#39;s a `SELECT DISTINCT(image) FROM products;` query
    // example: [http://www.example.com/image1.jpg, http://www.example.com/image2.jpg, http://www.example.com/image3.jpg]
    this.downloadImages();
  },

  downloadImages: function() {
    var _this = this; // for use in the callbacks

    // stop if we&#39;ve processed all of the images
    if (this.remoteImages.length === 0) {
      return;
    }

    // get the next image from the array
    var image = this.remoteImages.pop();
    var imageName = image.split(&#39;/&#39;).pop(); // just the image name (eg image1.jpg)

    // access the filesystem
    // &quot;LocalFileSystem.PERSISTENT&quot; means it is permanent and not temporary
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
      // the &quot;create: true&quot; option will create the file if it doesn&#39;t exist
      // the &quot;exclusive: true&quot; option will skip the file if it already exists instead of re-downloading it
      fileSystem.root.getFile(imageName, {create: true, exclusive: true}, function(fileEntry) {
        // get the full path to the newly created file on the device
        var localPath = fileEntry.fullPath;

        // massage the path for android devices (not tested)
        if (device.platform === &quot;Android&quot; &amp;&amp; localPath.indexOf(&quot;file://&quot;) === 0) {
          localPath = localPath.substring(7);
        }

        // download the remote file and save it
        var remoteFile = encodeURI(image.ProductImage);
        var fileTransfer = new FileTransfer();
        fileTransfer.download(remoteFile, localPath, function(newFileEntry) {
          // successful download, continue to the next image
          _this.downloadImages();
        },
        function(error) { // error callback for #download
          console.log(&#39;Error with #download method.&#39;, error);
          _this.downloadImages(); // continue working
        });
      },
      function(error) { // error callback for #getFile
        console.log(&#39;Error with #getFile method.&#39;, error);
        _this.downloadImages(); // continue working
      });
    },
    function(error) { // error callback for #requestFileSystem
      console.log(&#39;Error with #requestFileSystem method.&#39;, error);
    });
  }
};</code></pre></noscript></div>


<p>Ok, we have the files downloaded, but how to we show them in our app. As far as I could find, you can&rsquo;t refence images on the device&rsquo;s filesystem form the PhoneGap app.</p>

<p>Luckily, the PhoneGap File plugin has a way to read files from the filesystem. It includes a method to read the file as a data url which converts it to a base64-encoded string.</p>

<p>My app was written using Backbone with Handlebars templates. So, to display the image, I wrote a Handlebars helper to get the image from the file system and return it as a base64-encoded string. You&rsquo;ll notice that the helper actually gets an element via jQuery and sets it <code>src</code> attribute. I had to do it this way since all of the File plugin methods are asynchronous and handled with callback.</p>

<div><script src='https://gist.github.com/9c8c9f1cc8d8d002dd5e.js?file=handlebars.js'></script>
<noscript><pre><code>// product is a json object
// ex: {id: 5, image: &#39;image1.jpg&#39;}
Handlebars.registerHelper(&#39;base64ProductImage&#39;, function(product, options) {
  var productID = product.id;
  var imageName = product.image.split(&#39;/&#39;).pop();
  window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
    fileSystem.root.getFile(imageName, {create: false}, function(fileEntry) {
      var reader = new FileReader();
      reader.onloadend = function(event) { // callback for when file is read
        $(&quot;#base64-image-#{productID}&quot;).attr(&#39;src&#39;, event.target.result);
      };
      fileEntry.file(function(file) {
        reader.readAsDataURL(file);
      }, null);
    }, null);
  }, null);

  return &#39;&#39;;
});</code></pre></noscript></div>


<p>The helper can be called like so:</p>

<div><script src='https://gist.github.com/9c8c9f1cc8d8d002dd5e.js?file=template.hbs'></script>
<noscript><pre><code>&lt;img src=&quot;{{base64ProductImage product}}&quot; id=&quot;base64-image-{{product.id}}&quot; /&gt;</code></pre></noscript></div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Git Essentials - Hack &amp; Ship]]></title>
    <link href="http://nomethoderror.com//blog/2013/10/12/git-essentials-hack-and-ship/"/>
    <updated>2013-10-12T11:44:00-05:00</updated>
    <id>http://nomethoderror.com//blog/2013/10/12/git-essentials-hack-and-ship</id>
    <content type="html"><![CDATA[<p>If you&rsquo;re like me, your normal git workflow looks something like this:</p>

<ol>
<li>Do some work in a topic branch and need to rebase master into the branch.</li>
<li><code>git checkout master</code></li>
<li><code>git pull origin master</code> (or <code>fetch</code> and <code>merge</code>)</li>
<li><code>git checkout topic-branch</code></li>
<li><code>git rebase master</code></li>
</ol>


<p>Once you&rsquo;re done with your topic branch, it might look something like this:</p>

<ol>
<li><code>git checkout master</code></li>
<li><code>git merge topic-branch</code></li>
<li><code>git push origin master</code></li>
</ol>


<p>That&rsquo;s a lot of work, and as a developer we can definitely make that process easier. About 4 years ago, I came across a set of bash scripts that simplified this workflow greatly. The creator, <a href="http://reinh.com/">Rein Henrichs</a>, named them <a href="http://reinh.com/blog/2008/08/27/hack-and-and-ship.html">Hack &amp;&amp; Ship</a>.</p>

<p>These tools worked great, but weren&rsquo;t flexible enough for me. They assumed that you would always be rebasing and pushing to the master branch. If this wasn&rsquo;t the case, you had to do everything by hand.</p>

<p>Here are my updated versions of Hack &amp;&amp; Ship that allow you to rebase and push to any branch (such as <code>staging</code> or <code>qa</code>):</p>

<h2>Hack</h2>

<div><script src='https://gist.github.com/6952241.js?file=hack.sh'></script>
<noscript><pre><code>#!/bin/sh
# git name-rev is fail
CURRENT=`git branch | grep &#39;\*&#39; | awk &#39;{print $2}&#39;`
TARGET=$1
: ${TARGET:=&quot;master&quot;}

echo &quot;=&gt; git checkout ${TARGET}&quot;
git checkout ${TARGET}

echo &quot;=&gt; git pull origin ${TARGET}&quot;
git pull origin ${TARGET}

echo &quot;=&gt; git checkout ${CURRENT}&quot;
git checkout ${CURRENT}

echo &quot;=&gt; git rebase ${TARGET}&quot;
git rebase ${TARGET}
</code></pre></noscript></div>


<h2>Ship</h2>

<div><script src='https://gist.github.com/6952241.js?file=ship.sh'></script>
<noscript><pre><code>#!/bin/sh
# git name-rev is fail
CURRENT=`git branch | grep &#39;\*&#39; | awk &#39;{print $2}&#39;`
TARGET=$1
: ${TARGET:=&quot;master&quot;}

echo &quot;=&gt; git checkout ${TARGET}&quot;
git checkout ${TARGET}

echo &quot;=&gt; git merge ${CURRENT}&quot;
git merge ${CURRENT}

echo &quot;=&gt; git push origin ${TARGET}&quot;
git push origin ${TARGET}

echo &quot;=&gt; git checkout ${CURRENT}&quot;
git checkout ${CURRENT}
</code></pre></noscript></div>


<p>To use them, create two files named <code>hack</code> and <code>ship</code> somewhere in your path (like <code>/usr/local/bin</code> maybe) and make them executable. Then, you can invoke them like so:</p>

<p><code>hack</code> or <code>hack staging</code></p>

<p><code>push</code> or <code>push qa</code></p>

<p><code>hack &amp;&amp; ship</code></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Converting a Rails Database from mySQL to PostgreSQL]]></title>
    <link href="http://nomethoderror.com//blog/2013/10/03/converting-a-rails-database-from-mysql-to-postgresql/"/>
    <updated>2013-10-03T18:18:00-05:00</updated>
    <id>http://nomethoderror.com//blog/2013/10/03/converting-a-rails-database-from-mysql-to-postgresql</id>
    <content type="html"><![CDATA[<p>The <a href="https://github.com/ricardochimal/taps">taps</a> gem allows you to transfer database structure and data easily between db types.</p>

<h2>Add the necessary gems to your Gemfile</h2>

<div><script src='https://gist.github.com/6818918.js?file=1_gemfile.rb'></script>
<noscript><pre><code>gem &#39;taps&#39;
gem &#39;sqlite3&#39; # dependency of taps</code></pre></noscript></div>


<p>Make sure you have the gems for both db types you&rsquo;ll be accessing.</p>

<div><script src='https://gist.github.com/6818918.js?file=2_gemfile.rb'></script>
<noscript><pre><code>gem &#39;mysql2&#39;
gem &#39;pg&#39;</code></pre></noscript></div>


<h2>Start the taps server</h2>

<p>This will connect to the database that you are copying structure/date <em>from</em>.</p>

<div><script src='https://gist.github.com/6818918.js?file=3_taps.sh'></script>
<noscript><pre><code>taps server mysql2://username:password@localhost/dbname authusername authpassword</code></pre></noscript></div>


<p><code>authusername</code> and <code>authpassword</code> can be whatever you want. This will be used to authenticate when pulling from this db server.</p>

<h2>Pull the data into your new database</h2>

<p>Make sure the new database has been created.</p>

<div><script src='https://gist.github.com/6818918.js?file=4_taps.sh'></script>
<noscript><pre><code>taps pull postgres://username:password@localhost/dbname http://authusername:authpassword@localhost:5000</code></pre></noscript></div>


<p>Done!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Shoulda Matcher Model Extras]]></title>
    <link href="http://nomethoderror.com//blog/2013/02/20/shoulda-matchers-model-extras/"/>
    <updated>2013-02-20T18:00:00-06:00</updated>
    <id>http://nomethoderror.com//blog/2013/02/20/shoulda-matchers-model-extras</id>
    <content type="html"><![CDATA[<p>If you use RSpec with your Rails projects, chances are you also use <a href="https://github.com/thoughtbot/shoulda-matchers">shoulda_matchers</a> (and if you don&rsquo;t, what are you doing with your life?!). You probably already know all about the basic model matchers, like the ones below.</p>

<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=1_user.rb'></script>
<noscript><pre><code>class User &lt; ActiveRecord::Base
  belongs_to :organization
  has_many :projects

  validates :name, :presence =&gt; true
  validates :email, :uniqueness =&gt; true
end</code></pre></noscript></div>




<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=2_user_spec.rb'></script>
<noscript><pre><code>require &#39;spec_helper&#39;
describe User do
  context &#39;associations&#39; do
    it { should belong_to(:organization) }
    it { should have_many(:projects) }
  end

  context &#39;validations&#39; do
    it { should validate_presence_of(:name) }
    it { should validate_uniqueness_of(:email) }
  end
end</code></pre></noscript></div>


<h3>Association Extras</h3>

<p>There are a ton of extra options you can use with the association matchers (pretty much any option you can pass to an association). Below are just a few.</p>

<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=3_user.rb'></script>
<noscript><pre><code>class User &lt; ActiveRecord::Base
  belongs_to :organization, :class_name =&gt; &#39;UserOrganization&#39;
  has_many :contracts
  has_many :jobs, :through =&gt; :contracts
  has_many :projects, :order =&gt; &#39;date DESC&#39;, :dependent =&gt; :destroy

  accepts_nested_attributes_for :projects, :limit =&gt; 3
end</code></pre></noscript></div>




<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=4_user_spec.rb'></script>
<noscript><pre><code>require &#39;spec_helper&#39;

describe User do
  context &#39;associations&#39; do
    it { should belong_to(:organization).class_name(&#39;UserOrganization&#39;) }
    it { should have_many(:contracts) }
    it { should have_many(:jobs).through(:contracts) }
    it { should have_many(:projects).order(&#39;date DESC&#39;).dependent(:destroy) }
    it { should accept_nested_attributes_for(:projects).limit(3) }
  end
end</code></pre></noscript></div>


<h3>Validation Extras</h3>

<p>There are even more options for use with the validation matchers. Here&rsquo;s a small sampling (including some mass assignment matchers).</p>

<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=5_user.rb'></script>
<noscript><pre><code>class User &lt; ActiveRecord::Base
  validates :name, :length =&gt; { :minimum =&gt; 10, :maximum =&gt; 100 }
  validates :email, :format =&gt; { :with =&gt; /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/ }
  validates :status, :inclusion =&gt; { :in =&gt; %w(active inactive suspended) }

  attr_accessible :name, :email
  attr_accessible :name, :email, :status, :as =&gt; :admin
end</code></pre></noscript></div>




<div><script src='https://gist.github.com/a3cb3677eb764b5cd365.js?file=6_user_spec.rb'></script>
<noscript><pre><code>require &#39;spec_helper&#39;
describe User do
  context &#39;validations&#39; do
    it { should ensure_length_of(:name).is_at_least(10).is_at_most(100) }
    it { should validate_format_of(:email).with(&#39;user@email.com&#39;) }
    it { should validate_format_of(:email).not_with(&#39;user@email&#39;) }
    it { should ensure_inclusion_of(:status).in_array([&#39;active&#39;, &#39;inactive&#39;, &#39;suspended&#39;]) }
  end

  context &#39;mass assignment&#39; do
    it { should allow_mass_assignment_of(:name) }
    it { should allow_mass_assignment_of(:email) }
    it { should_not allow_mass_assignment_of(:status) }
    it { should allow_mass_assignment_of(:status).as(:admin) }
  end
end</code></pre></noscript></div>


<p>These are just a few of the extras that <kbd>shoulda_matchers</kbd> offers. I would highly recommend that you read through the <a href="http://rubydoc.info/github/thoughtbot/shoulda-matchers/master/frames">documentation</a> to discover all the things you can do.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using God Gem to Monitor mySQL]]></title>
    <link href="http://nomethoderror.com//blog/2011/10/02/using-god-gem-to-monitor-mysql/"/>
    <updated>2011-10-02T12:00:00-05:00</updated>
    <id>http://nomethoderror.com//blog/2011/10/02/using-god-gem-to-monitor-mysql</id>
    <content type="html"><![CDATA[<p>I recently ran into a problem on a client server where the <code>msyqld</code> process died, and neither of us noticed it for almost 24 hours. That meant that the site was completely useless that entire time. Needless to say, the client wasn&rsquo;t thrilled about this.</p>

<p>I told him that I&rsquo;d look into setting up a monitoring service to, at the very least, notify me if <code>msyqld</code> ever crashed. During my research, I stumbled upon the god gem (which I&rsquo;d used in the past to monitor mongrel processes back in the days before Passenger). I didn&rsquo;t realize it could be used to monitor other processes as well, such as <code>msyqld</code>.</p>

<p>God is a rubygem, so it&rsquo;s easy to install on any *nix operating system. It&rsquo;s config files are also written in Ruby, so that makes it even better.</p>

<p>What you&rsquo;ll need to get the script running:</p>

<ol>
<li><p>Install the god gem (as root).</p>

<p><pre>sudo gem install god</pre></p></li>
<li><p>Find the location of your <code>msyqld</code> pid file.</p>

<p><pre>mysqladmin -u root -p variables | grep pid_file</pre></p></li>
<li><p>Determine the command to start/stop/restart the <code>msyqld</code> service. Usually <code>/etc/init.d/mysqld</code></p></li>
</ol>


<p>Here is the config file I wrote to watch my mysqld process:</p>

<div><script src='https://gist.github.com/c1f96cfc74a73316c35b.js?file=mysql.rb'></script>
<noscript><pre><code>  # run in non-daemonized mode (so you can monitor it) with `god -c /path/to/mysql.god -D`
  # run normally with `god -c /path/to/mysql.god`

  # Settings for email notifications (optional)
  God::Contacts::Email.defaults do |d|
    d.from_email = &#39;god@my-app.com&#39;
    d.from_name = &#39;God&#39;
    d.delivery_method = :smtp # this can also be :sendmail
    d.server_host = &#39;smtp.myapp.com&#39;
    d.server_port = 25
    d.server_auth = true
    d.server_domain = &#39;myapp.com&#39;
    d.server_user = &#39;smtp_user@myapp.com&#39;
    d.server_password = &#39;password&#39;
  end

  # you can create as many email entries as you&#39;d like
  God.contact(:email) do |c|
    c.name = &#39;me&#39;
    c.to_email = &#39;me@email.com&#39;
  end

  God.watch do |w|
    # you can name this whatever you want
    w.name = &quot;mySQL Server&quot;

    # polling interval
    w.interval = 30.seconds

    # command to start service
    w.start = &quot;/etc/init.d/mysqld start &amp;&amp; /etc/init.d/httpd restart&quot;

    # command to stop service
    w.stop = &quot;/etc/init.d/mysqld stop&quot;

    # command to restart service
    w.restart = &quot;/etc/init.d/mysqld restart &amp;&amp; /etc/init.d/httpd restart&quot;

    # how long to wait after starting service before monitoring resumes
    w.start_grace = 20.seconds

    # how long to wait after restarting service before monitoring resumes
    w.restart_grace = 20.seconds

    # location of pid file
    w.pid_file = &quot;/var/run/mysqld/mysqld.pid&quot;

    # tell god to delete the pid file when mysqld crashes
    w.behavior(:clean_pid_file)

    # determine the state on startup
    w.transition(:init, { true =&gt; :up, false =&gt; :start }) do |on|
      on.condition(:process_running) do |c|
        c.running = true
      end
    end

    # determine when process has finished starting
    w.transition([:start, :restart], :up) do |on|
      on.condition(:process_running) do |c|
        c.running = true
      end
      # failsafe
      on.condition(:tries) do |c|
        c.times = 8
        c.within = 2.minutes
        c.transition = :start
      end
    end

    # start if process is not running
    w.transition(:up, :start) do |on|
      on.condition(:process_exits) do |c|
        # send an email to me to notify me that the service has crashed
        c.notify = &#39;me&#39;
      end
    end

    # lifecycle
    w.lifecycle do |on|
      # If the service keeps triggering a restart over and over, it is considered to be &quot;flapping&quot;.
      on.condition(:flapping) do |c|
        c.to_state = [:start, :restart]
        c.times = 5
        c.within = 1.minute
        c.transition = :unmonitored
        # If the service is flapping, wait 10 minutes, then try to start/restart again.
        c.retry_in = 10.minutes
        c.retry_times = 5
        c.retry_within = 2.hours
      end
    end
  end</code></pre></noscript></div>


<p>A few things to note about my script:</p>

<ol>
<li>In my start and restart commands, I also restart Apache. Running my site with Passenger, I would get a Rack error when <code>mysqld</code> restarted, but apache hadn&rsquo;t. YMMV.</li>
<li>I&rsquo;m using an SMTP server for my email notification. You can also use <code>sendmail</code>, or you can exclude the email notifications altogether.</li>
<li>When running the script for the first time, it&rsquo;s a good idea to add the <code>-D</code> flag. This runs god in non-daemonized mode so all output is piped to STDOUT. That way, you can watch what it&rsquo;s doing to ensure everything is working correctly.</li>
</ol>


<p>For more information about the god gem, see their site: <a href="http://god.rubyforge.org/">god.rubyforge.org</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Wildcard Domains with Rails]]></title>
    <link href="http://nomethoderror.com//blog/2011/09/13/using-wildcard-domains-with-rails/"/>
    <updated>2011-09-13T12:00:00-05:00</updated>
    <id>http://nomethoderror.com//blog/2011/09/13/using-wildcard-domains-with-rails</id>
    <content type="html"><![CDATA[<p>Working on a recent project, I needed to allow users to set custom domains to point to their account pages on my server. They would set their domain when they registered, then set an A Record with their DNS to point to my server. The only problem was, I didn&rsquo;t know how to get Rails to do this.</p>

<p>The domain is already saved in the database, but I needed to tell the router to look for any incoming requests to a domain that doesn&rsquo;t match my primary domain (in this example, we&rsquo;ll say my primary domain is example.com). Thanks to Rails 3, I could just add a routing constraint (which can take a class as argument), like so</p>

<div><script src='https://gist.github.com/739001cc5a3274f3da03.js?file=routes.rb'></script>
<noscript><pre><code>MyApp::Application.routes.draw do

  # domain routes (THIS IS THE IMPORTANT PART)
  constraints(Domain) do
    match &#39;/&#39; =&gt; &#39;user#show&#39;, :as =&gt; :user_domain

    resources :tasks
    resources :projects

    # any other routes that are domain-specific
  end

  # this needs to be below the &quot;domain&quot; section
  root :to =&gt; &#39;site#index&#39;

end</code></pre></noscript></div>


<p>Notice that the root path is below the domain routes. This is important because it will get triggered <em>before</em> the domain routes otherwise (because routes are first come, first served). With these routes in place, it&rsquo;s as easy as finding the user by domain when we get a request.</p>

<p>We added the Domain class as a constraints argument, now we need to add that file. You can add the following <code>domain.rb</code> to your lib folder and make sure it&rsquo;s getting loaded on application boot.</p>

<div><script src='https://gist.github.com/739001cc5a3274f3da03.js?file=domain.rb'></script>
<noscript><pre><code>class Domain
  def self.matches?(request)
    request.domain.present? &amp;&amp; request.domain != &#39;example.com&#39;
  end
end</code></pre></noscript></div>


<p>It&rsquo;s as easy as that. We just check to make sure the domain is present and that it doesn&rsquo;t match our primary domain. This constraint will match <em>any</em> domain other than our primary domain.</p>

<p>As for server configuration, you have to tell your server to accept all incoming requests, regardless of domain. Below is a sample Apache virtualhost to accomplish this. Notice that we don&rsquo;t specify a <code>ServerName</code> or <code>ServerAlias</code>, we want it to match everything.</p>

<div><script src='https://gist.github.com/739001cc5a3274f3da03.js?file=vhost.conf'></script>
<noscript><pre><code>&lt;VirtualHost *:80&gt;
  DocumentRoot /path/to/my_app/public

  &lt;Directory /path/to/my_app/public&gt;
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  &lt;/Directory&gt;
&lt;/VirtualHost&gt;</code></pre></noscript></div>


<p><strong>IMPORTANT</strong>: You need to ensure that this virtualhost entry is loaded <em>last</em>. If you have any other virtualhosts that specify a <code>ServerName</code>, then they need to be loaded before this one. We&rsquo;re using this entry as a catch-all to route to our rails app. If you have all of your virtualhosts in one file, just put this entry last. If each entry is in its own file, just make sure this file is loaded last (you might add a zzz_ to the start of the filename to make sure).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Deploy a Sinatra Application with Capistrano]]></title>
    <link href="http://nomethoderror.com//blog/2010/05/25/deploy-a-sinatra-application-with-capistrano/"/>
    <updated>2010-05-25T12:00:00-05:00</updated>
    <id>http://nomethoderror.com//blog/2010/05/25/deploy-a-sinatra-application-with-capistrano</id>
    <content type="html"><![CDATA[<h3>Step 0: Vendor the sinatra gem (optional).</h3>

<div><script src='https://gist.github.com/667a83dbbf9a883f02ca.js?file=vendor.sh'></script>
<noscript><pre><code>mkdir vendor
cd vendor
gem unpack sinatra
mv sinatra-* sinatra</code></pre></noscript></div>


<h3>Step 1: Create a <kbd>config.ru</kbd> Rack file in your project&rsquo;s root directory.</h3>

<div><script src='https://gist.github.com/667a83dbbf9a883f02ca.js?file=config.ru'></script>
<noscript><pre><code>require &#39;rubygems&#39;
require &#39;vendor/sinatra/lib/sinatra.rb&#39;

set :public, File.expand_path(File.dirname(__FILE__) + &#39;/public&#39;) # Include your public folder
set :views, File.expand_path(File.dirname(__FILE__) + &#39;/views&#39;)  # Include the views

set :environment, :production

disable :run, :reload

require &#39;app_file&#39; # replace this with your sinatra app file
run Sinatra::Application</code></pre></noscript></div>


<h3>Step 2: Create a Capistrano deploy file.</h3>

<p>This file should live at <kbd>config/deploy.rb</kbd>.</p>

<div><script src='https://gist.github.com/667a83dbbf9a883f02ca.js?file=deploy.rb'></script>
<noscript><pre><code>set :domain, &quot;yourdomain.com&quot;
set :application, &quot;app_name&quot;
set :deploy_to, &quot;/var/www/apps/#{domain}&quot;

set :user, &quot;your_deploy_user&quot;
set :use_sudo, false

set :scm, :git
set :repository,  &quot;git@github.com:you/application.git&quot;
set :branch, &#39;master&#39;
set :git_shallow_clone, 1

role :web, domain
role :app, domain
role :db,  domain, :primary =&gt; true

set :deploy_via, :remote_cache

namespace :deploy do
  task :start do ; end
  task :stop do ; end
  # Assumes you are using Passenger
  task :restart, :roles =&gt; :app, :except =&gt; { :no_release =&gt; true } do
    run &quot;#{try_sudo} touch #{File.join(current_path,&#39;tmp&#39;,&#39;restart.txt&#39;)}&quot;
  end

  task :finalize_update, :except =&gt; { :no_release =&gt; true } do
    run &quot;chmod -R g+w #{latest_release}&quot; if fetch(:group_writable, true)

    # mkdir -p is making sure that the directories are there for some SCM&#39;s that don&#39;t save empty folders
    run &lt;&lt;-CMD
      rm -rf #{latest_release}/log &amp;&amp;
      mkdir -p #{latest_release}/public &amp;&amp;
      mkdir -p #{latest_release}/tmp &amp;&amp;
      ln -s #{shared_path}/log #{latest_release}/log
    CMD

    if fetch(:normalize_asset_timestamps, true)
      stamp = Time.now.utc.strftime(&quot;%Y%m%d%H%M.%S&quot;)
      asset_paths = %w(images css).map { |p| &quot;#{latest_release}/public/#{p}&quot; }.join(&quot; &quot;)
      run &quot;find #{asset_paths} -exec touch -t #{stamp} {} &#39;;&#39;; true&quot;, :env =&gt; { &quot;TZ&quot; =&gt; &quot;UTC&quot; }
    end
  end
end</code></pre></noscript></div>


<h3>Step 3: Deploy the app.</h3>

<div><script src='https://gist.github.com/667a83dbbf9a883f02ca.js?file=deploy.sh'></script>
<noscript><pre><code>cap deploy:setup
cap deploy</code></pre></noscript></div>


<h3>Step 4: Get a beer, you&rsquo;re done!</h3>
]]></content>
  </entry>
  
</feed>
