<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Daddy Fixes Everything</title>
	
	<link>http://blog.spoolz.com</link>
	<description>A father and programmer's skewed view of the world</description>
	<lastBuildDate>Fri, 11 Jan 2013 14:59:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/DaddyFixesEverything" /><feedburner:info uri="daddyfixeseverything" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Rails Nested Attributes with Scoped Uniqueness Validation of Association</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/OHyLOKUeHMg/</link>
		<comments>http://blog.spoolz.com/2012/12/21/rails-nested-attributes-with-scoped-uniqueness-validation-of-association/#comments</comments>
		<pubDate>Sat, 22 Dec 2012 00:49:46 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[nested attributes]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=330</guid>
		<description><![CDATA[This is going to be a long one, so grab your favorite beverage&#8230; Problem I have a fairly standard[crayon-519613d17326e-i/]  and has_many model association. And I want to save nested attributes along with the parent when creating a new parent record. But, I don&#8217;t want the user to be able to submit duplicate values for the child records. Sounds easy. That&#8217;s what I thought when I started. My Solution  Models We have an Organization and a SubUnit models, pretty standard stuff here. [crayon-519613d173655/] [crayon-519613d173a3c/] Controller The controller is simple (standard actions removed). Keep scrolling down. [crayon-519613d173e24/] View Now it&#8217;s getting interesting. [crayon-519613d17420c/] [crayon-519613d1745f3/] Your form should look like this. Polluting Links &#8230; <p><a href="http://blog.spoolz.com/2012/12/21/rails-nested-attributes-with-scoped-uniqueness-validation-of-association/#more-330" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>This is going to be a long one, so grab your favorite beverage&#8230;</p>
<h2>Problem</h2>
<p>I have a fairly standard<pre class="crayon-plain-tag">belongs_to</pre>  and has_many model association. And I want to save nested attributes along with the parent when creating a new parent record. But, I don&#8217;t want the user to be able to submit duplicate values for the child records.</p>
<p>Sounds easy. That&#8217;s what I thought when I started.</p>
<h2>My Solution</h2>
<h3> Models</h3>
<p>We have an Organization and a SubUnit models, pretty standard stuff here.</p><pre class="crayon-plain-tag">lass SubUnit &lt; ActiveRecord::Base
  attr_accessible :name, :organization_id
  belongs_to :organization

  validates :name,
            presence: true,
            uniqueness: { scope: :organization_id }
end</pre><p></p><pre class="crayon-plain-tag">class Organization &lt; ActiveRecord::Base
  attr_accessible :name, :sub_units_attributes
  has_many :sub_units, dependent: :destroy
  accepts_nested_attributes_for :sub_units, allow_destroy: true, reject_if: proc { |a| a["name"].blank? }
  validates_presence_of :name
end</pre><p></p>
<h3>Controller</h3>
<p>The controller is simple (standard actions removed). Keep scrolling down.</p><pre class="crayon-plain-tag"># controllers/organizations_controller.rb
class OrganizationsController &lt; ApplicationController
  def new
    @organization = Organization.new
    @organization.sub_units.build
  end

  def create
    @organization = Organization.new(params[:organization])

    if @organization.save
      redirect_to @organization, notice: 'Organization was successfully created.'
    else
      render :new
    end
  end
end</pre><p></p>
<h3>View</h3>
<p>Now it&#8217;s getting interesting.</p><pre class="crayon-plain-tag"># organizations/new.html.haml
= form_for @organization, :html =&gt; { :class =&gt; 'form-horizontal' } do |f|
  .row-fluid
    .span6
      .well
        %h2 Organization Info
        .control-group
          = f.label :name, :class =&gt; 'control-label'
          .controls
            = f.text_field :name, :class =&gt; 'text_field input-medium'

    .span6
      .well.sub-units
        %h2 SubUnit Info
        = f.fields_for :sub_units do |f_sub|
          = render 'sub_unit_fields', f: f_sub

        .control-group.add-sub-unit
          .controls
            = link_to 'add a SubUnit', '#', class: 'btn btn-primary add-sub-unit-button'

        #new-sub-unit-fields.hidden
          = f.fields_for :sub_units, SubUnit.new, child_index: 'new_sub_unit' do |f_sub|
            = render 'sub_unit_fields', f: f_sub

    .span12
      .form-actions
        = link_to 'Create Organization', '#', class: 'btn btn-primary create-organization-button'
        = link_to t('.cancel', :default =&gt; t("helpers.links.cancel")), organizations_path, :class =&gt; 'btn'</pre><p></p><pre class="crayon-plain-tag"># _sub_unit_fields.html.haml
.control-group
  = f.label :name, class: 'control-label'
  .controls.sub-unit
    = f.text_field :name, class: 'input-mini'
    = f.hidden_field :_destroy
    = link_to "remove", '#', class: 'btn btn-warning btn-mini remove-sub-unit-button'</pre><p>Your form should look like this.</p>
<p><a href="http://blog.spoolz.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-21-at-4.09.14-PM.png"><img class="size-medium wp-image-313     alignnone" alt="/organizations/new" src="http://blog.spoolz.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-21-at-4.09.14-PM-300x201.png" width="300" height="201" /></a></p>
<h4>Polluting Links with Javascript</h4>
<p>Like everyone else who has started down the road to nested attribute bliss, you have watched <a href="http://railscasts.com/episodes/197-nested-model-form-part-2">Ryan Bates&#8217; Railscast on Complex Forms</a>. It&#8217;s superlative.</p>
<p>But there&#8217;s one thing I didn&#8217;t like&#8230; the heavy handed approach of using link_to_function. Especially when including a fair amount of escaped html into an onclick script. I&#8217;m not saying it&#8217;s wrong, just that I believe html should stay where it belongs… in the DOM. Heck, they even created a gem <a href="https://github.com/ryanb/nested_form">nested_form</a>.</p>
<p>I think we can make it simpler, painless, elementary.</p>
<p>That&#8217;s where the following little ditty comes in handy. We are creating the exact same field structure that is used for entering a SubUnit, but hiding the html so that we can use JavaScript to <em>copy-and-append</em> to the <em>visible</em> entry area.</p><pre class="crayon-plain-tag">#new-sub-unit-fields.hidden
  = f.fields_for :sub_units, SubUnit.new, child_index: 'new_sub_unit' do |f_sub|
    = render 'sub_unit_fields', f: f_sub</pre><p><strong>Line #1</strong>: hide the div.</p>
<p><strong>Line #2</strong>: use fields_for to generate the proper field id and name attributes so that it is submitted as a child object to our Organization. Notice the SubUnit.new? That prevents this block from iterating over all the @organization.sub_units that may be built, either as a new object (controller line #5), or when re-rendered due to a validation error with @organization.</p>
<p><strong>Line #2</strong>: don&#8217;t forget the child_index: &#8216;new_sub_unit&#8217; option! Without it, rails will attempt to index the fields id and name attributes with numbers, which in this case would be 0 (zero), and mess up the prior sub_unit fields. IOW, you will end up with two params[:organization][:sub_units_attributes][0] elements.</p>
<p>If you don&#8217;t understand all the details, take a few minutes and read the <a href="http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html">ActiveRecord::NestedAttributes::ClassMethods</a>.</p>
<p>Now for some JS magic:</p><pre class="crayon-plain-tag">jQuery -&gt;
  $('.well.sub-units').on('click', 'a.remove-sub-unit-button', -&gt;
      remove_sub_unit(@)
    )

  $('.add-sub-unit-button').click -&gt;
    add_sub_unit(@)

  add_sub_unit = (link) -&gt;
    new_sub_unit = $(".hidden#new-sub-unit-fields").html()
    new_id = new Date().getTime()
    regexp = new RegExp("new_sub_unit", "g")
    $(link).closest('.add-sub-unit').before(new_sub_unit.replace(regexp, new_id))
    $(link).closest('.add-sub-unit').prev().find('input[type=text]').focus()

  remove_sub_unit = (link) -&gt;
    $(link).prev("input[type=hidden]").val("1")
    $(link).closest(".control-group").hide()</pre><p>Pretty simple, bind to the click events of the add-sub-unit-button and remove-sub-unit-button to functions.</p>
<p><strong>add_sub_unit</strong> function copies the new-sub-unit-fields div, replacing the text of &#8216;new-sub-unit&#8217; in the id and name attributes of the input/label elements with an integer.</p>
<p><strong>remove_sub_unit</strong> function hides the input field group, and set the &#8216;_destroy&#8217; hidden field to &#8220;1&#8243; (&#8216;true&#8217; also works) so that it will not be created when the form is submitted.</p>
<p>Inspiration for this JavaScript goes to <a href="http://railscasts.com/episodes/197-nested-model-form-part-2">Ryan Bates</a>.</p>
<h3><em>Status Check</em></h3>
<p>At this point we have a parent model, Organizations, with nested attributes for children SubUnits. When creating a new Organization, you can add and remove SubUnits. The entire relationship is submitted with a single form post.</p>
<h3>Eliminate Duplicates in the DOM</h3>
<p><a href="https://github.com/rails/rails/issues/4568#issuecomment-10343810">Everyone</a> <a href="http://stackoverflow.com/questions/2772236/validates-uniqueness-of-in-nested-model-rails#answers-header">else</a> does it in model validations, manipulation of the params hash, or some other convoluted way. But I decided to eliminate duplicates <em>before</em> the submission of the parent form. Pretty easy, actually.</p><pre class="crayon-plain-tag">jQuery -&gt;
  $('a.create-organization-button').click -&gt;
    # remove duplicate form values, then submit the form
    uniqueNames = []
    $.each($('.controls.sub-unit input[type=text]'), (i, el) -&gt;
        if $.inArray($(@).val(), uniqueNames) == -1
          uniqueNames.push($(@).val())
        else
          $(@).parent().find('input[type=hidden]').val("true")
      )
    $(@).closest('form').submit()</pre><p>When the Create Organization button is clicked, the above JavaScript loops through all the SubUnit form field elements, marking duplicate entries hidden &#8216;_destroy&#8217; field with &#8216;true&#8217;, thus preventing them from being saved. Could you just remove the elements? Sure.</p>
<p>Inspiration for the JavaScript remove duplicates in an array to <a href="http://stackoverflow.com/users/73432/roman-bataev">Roman Bataev</a> in <a href="http://stackoverflow.com/questions/9229645/remove-duplicates-from-javascript-array/9229932#9229932">this post</a>.</p>
<p><a href="http://blog.spoolz.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-21-at-4.38.21-PM.png"><img class="alignnone size-medium wp-image-318" alt="Screen Shot 2012-12-21 at 4.38.21 PM" src="http://blog.spoolz.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-21-at-4.38.21-PM-300x214.png" width="300" height="214" /></a></p>
<p>If you watch your logs, you&#8217;ll see that all the SubUnits attributes are submitted, but only those marked with the hidden field &#8216;_destroy&#8217; == &#8216;false&#8217; will be created.</p><pre class="crayon-plain-tag">Started POST "/organizations" for 127.0.0.1 at 2012-12-21 16:32:39 -0700
Processing by OrganizationsController#create as HTML
  Parameters: {"utf8"=&gt;"✓", "authenticity_token"=&gt;"Dkphnf9nkc+5cxqRgo7mkQLcz2nvxHIUxezlOPA85cA=", "organization"=&gt;{"name"=&gt;"My Org", "sub_units_attributes"=&gt;{"0"=&gt;{"name"=&gt;"Unit1", "_destroy"=&gt;"false"}, "1356132751848"=&gt;{"name"=&gt;"Unit1", "_destroy"=&gt;"true"}, "1356132755193"=&gt;{"name"=&gt;"Unit2", "_destroy"=&gt;"false"}, "new_sub_unit"=&gt;{"name"=&gt;"", "_destroy"=&gt;"false"}}}}
   (3.5ms)  begin transaction
  SubUnit Exists (0.4ms)  SELECT 1 AS one FROM "sub_units" WHERE ("sub_units"."name" = 'Unit1' AND "sub_units"."organization_id" IS NULL) LIMIT 1
  SubUnit Exists (0.1ms)  SELECT 1 AS one FROM "sub_units" WHERE ("sub_units"."name" = 'Unit2' AND "sub_units"."organization_id" IS NULL) LIMIT 1
  SQL (28.4ms)  INSERT INTO "organizations" ("created_at", "name", "updated_at") VALUES (?, ?, ?)  [["created_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00], ["name", "My Org"], ["updated_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00]]
  SQL (2.1ms)  INSERT INTO "sub_units" ("created_at", "name", "organization_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00], ["name", "Unit1"], ["organization_id", 6], ["updated_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00]]
  SQL (0.2ms)  INSERT INTO "sub_units" ("created_at", "name", "organization_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00], ["name", "Unit2"], ["organization_id", 6], ["updated_at", Fri, 21 Dec 2012 23:32:39 UTC +00:00]]
   (48.5ms)  commit transaction</pre><p>The astute reader will also notice that the SubUnit model is attempting to validate the uniqueness of the name attribute, scoping it to a non-existant Organization. I admit it would be best to skip this validation, but I will leave that exercise to you, humble reader.</p>
<h2>Sample App</h2>
<p>What? You wanted a demo app on the GitHubs? <a href="http://github.com/threadhead/complex_nested_form">You shall be rewarded</a>, post haste.</p>
<h2>Synopsis</h2>
<p>The Good</p>
<ul>
<li>Submission of a parent Organization with children SubUnits utilizing nested attributes.</li>
<li>Duplicate SubUnits are removed.</li>
<li>Darn simple, easy to reproduce. Pretty darn unobtrusive, too.</li>
<li>No funky helpers to jack some html into a link element.</li>
<li>Is it better than Ryan Bates&#8217; solution? No. Just simpler.</li>
</ul>
<p>The Bad</p>
<ul>
<li>Only works on creating a new Organization. Does not work for editing an Organization with the ability to add additional SubUnits or destroy existing SubUnits. Future post?</li>
<li>My JavaScript is not abstracted to make it easily reusable. Fork it, and submit a patch if you so desire.</li>
<li>The SubUnit validation should be skipped when creating through an Organization.</li>
<li>No fallback if JavaScript is disabled.</li>
</ul>
<p>Additional Reading</p>
<ul>
<li>StackOverflow: <a href="http://stackoverflow.com/questions/2772236/validates-uniqueness-of-in-nested-model-rails">validates_uniqueness_of in nested model rails</a>, a great discussion of how to handle scoped validation when editing existing child attributes.</li>
<li>Rails issue: <a href="https://github.com/rails/rails/issues/4568#issuecomment-10343810"><code>validates_uniqueness_of</code> and <code>accepts_nested_attributes_for</code> only validates existing records</a>, <a href="https://github.com/macfanatic">macfanatic</a> shows a nice way to handle the same issue.</li>
<li>Rails pull request: <a href="https://github.com/rails/rails/pull/8308">Validates associated uniqueness for nested attributes</a>. The paint is still wet on this one. Hopefully is stirs some discussion.</li>
<li>Ryan Bates&#8217; gem: <a href="https://github.com/ryanb/nested_form">nested_form</a>.</li>
</ul>
<p>&nbsp;</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=OHyLOKUeHMg:tcw_KG3mprk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=OHyLOKUeHMg:tcw_KG3mprk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=OHyLOKUeHMg:tcw_KG3mprk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=OHyLOKUeHMg:tcw_KG3mprk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=OHyLOKUeHMg:tcw_KG3mprk:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/OHyLOKUeHMg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2012/12/21/rails-nested-attributes-with-scoped-uniqueness-validation-of-association/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2012/12/21/rails-nested-attributes-with-scoped-uniqueness-validation-of-association/</feedburner:origLink></item>
		<item>
		<title>Small Revelation – FactoryGirl, build_stubbed, associations, and let</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/llZf53c4OVw/</link>
		<comments>http://blog.spoolz.com/2012/07/09/small-revelation-factorygirl-build_stubbed-associations-and-let/#comments</comments>
		<pubDate>Mon, 09 Jul 2012 17:26:05 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[factory girl]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=246</guid>
		<description><![CDATA[Not really a problem, but something I didn&#8217;t really look out for because all my tests were passing&#8230; and hey, if tests are passing, I sleep well. TL;DR Dumped let{}, removed FactoryGirl associations, back to before(:all) and instance variable/FG.build pattern = super speedy tests.  TL;DR.1 And read the docs. Background I need to test a fairly complex permission matrix at the model level. To properly test it, I need to build out several complete company structures, with a multitude of users at various authorization levels. And 200+ actual tests. Being a fan of rspec&#8217;s let{}, I decide to use it copiously. 40 lines worth. In these tests, I don&#8217;t really need to have &#8230; <p><a href="http://blog.spoolz.com/2012/07/09/small-revelation-factorygirl-build_stubbed-associations-and-let/#more-246" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>Not really a problem, but something I didn&#8217;t really look out for because all my tests were passing&#8230; and hey, if tests are passing, I sleep well.</p>
<h5><strong>TL;DR Dumped let{}, removed FactoryGirl associations, back to before(:all) and instance variable/FG.build pattern = super speedy tests. </strong></h5>
<h5><strong>TL;DR.1 And read the docs.</strong></h5>
<h3></h3>
<h3><strong>Background</strong></h3>
<p>I need to test a fairly complex permission matrix at the model level. To properly test it, I need to build out several complete company structures, with a multitude of users at various authorization levels. And 200+ actual tests.</p>
<p>Being a fan of rspec&#8217;s let{}, I decide to use it copiously. 40 lines worth.</p>
<p>In these tests, I don&#8217;t really need to have persisted records, so using <span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed</span> fits the bill here.</p>
<blockquote>
<div><span style="font-family: 'courier new', monospace;">let(:company) { FactoryGirl.build_stubbed(:company)</span>}</div>
</blockquote>
<blockquote>
<div><span style="font-family: 'courier new', monospace;">&#8230; an so on, 39 times. </span></div>
</blockquote>
<h3></h3>
<h3><strong>What I Found</strong></h3>
<p>I thought one particular spec was running a little slow. So I converted the <span style="font-family: 'courier new', monospace;">FactoryGirl.build</span> to the shiny new <span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed</span>. No difference in time. So I decided to watch the test.log. Well, I quickly saw what was happening&#8230; it was persisting <em>thousands</em> of records.</p>
<p>But wait. I was using <span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed.</span> Where were all these records coming from?</p>
<h3></h3>
<h3><strong>Problem #1</strong></h3>
<p>In most of my FactoryGirl factories, I was using &#8216;<span style="font-family: 'courier new', monospace;">association :area</span>&#8216;, &#8216;<span style="font-family: 'courier new', monospace;">association :store</span>&#8216;, and so on. Didn&#8217;t think much about these until yesterday.</p>
<p>Turns out that FactoryGirl will build/create and <em>save</em> those associated factories, even if you are using <span style="font-family: 'courier new', monospace;">FactoryGirl.build</span> or <span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed</span>. Learned something new there. Honestly, I didn&#8217;t expect this behavior, but I understand why. Shoulda read the docs.</p>
<p>Now, the easy way around this is to pass into a <span style="font-family: 'courier new', monospace;">FactoryGirl.create/build/build_stubbed</span> a nil for the association, if it is not needed. Ala:</p>
<blockquote>
<div><span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed(:store, company: fg_company, area: nil)</span></div>
</blockquote>
<p>Now it won&#8217;t build out the associated area. Alas, I had forgotten <em>just one</em> of these nil associations. And at the worst possible relationship level, the bottom. So every time one factory was built, it create the entire supporting structure above. Thus, every hit to an <span style="font-family: 'courier new', monospace;">let(:invoice)</span> builds an entire company structure from one single <span style="font-family: 'courier new', monospace;">FactoryGirl.build_stubbed(:invoice)</span> call.</p>
<p>But it get&#8217;s worse.</p>
<h3></h3>
<h3><strong>Problem #2</strong></h3>
<p>I love the let{}. But to be honest, I never read the docs on it. Well, I did read them yesterday. Relavent line being (emphasis added):</p>
<blockquote>
<div>The value will be cached across multiple calls <span style="text-decoration: underline;">in the same example but not across examples</span>.</div>
</blockquote>
<p>Uh-oh. <span style="font-family: 'courier new', monospace;">Let{}</span> is like a <span style="font-family: 'courier new', monospace;">before(:each)</span>. Which is what most specs need. But I don&#8217;t, not for this spec. I&#8217;m never modifying the AR records, just testing some methods within models, which don&#8217;t modify AR instances.</p>
<h3></h3>
<h3><strong>Resulting Big Problem</strong></h3>
<p>Ok, not really a problem. But certainly very, very inefficient.</p>
<p>By forgetting to nil an association in a <span style="font-family: 'courier new', monospace;">FactoryGirld.build_stubbed</span>, and with <span style="font-family: 'courier new', monospace;">let{}</span> recreating an entire company structure, to the database, for every 200+ test. Well, you get the picture. It&#8217;s slooooow. 22 seconds worth of slow.</p>
<h3></h3>
<h3><strong>Solution</strong></h3>
<p>You know I wouldn&#8217;t drag you along this far without a solution.</p>
<ol>
<li>Just remove all the &#8216;<span style="font-family: 'courier new', monospace;">association :model</span>&#8216; statements from all FactoryGirl definitions. I know they are handy, but I want CONTROL over my factories. And just one small mistake can make a spec run many X-times longer.</li>
<li>Remove the <span style="font-family: 'courier new', monospace;">let{}</span> and replace with the good ol&#8217; instance variable/build pattern.</li>
<li>Move all the instance variables into a <span style="font-family: 'courier new', monospace;">before(:all)</span>.</li>
</ol>
<blockquote>
<div>
<div><span style="font-family: 'courier new', monospace;">before(:all) do</span></div>
</div>
<div>
<div><span style="font-family: 'courier new', monospace;">  @company = FactoryGirl.build_stubbed(:company)</span></div>
</div>
</blockquote>
<blockquote>
<div>
<div><span style="font-family: 'courier new', monospace;">  @store = FactoryGirl.build_stubbed(:store, company: company)</span></div>
</div>
</blockquote>
<blockquote>
<div>
<div><span style="font-family: 'courier new', monospace;">  &#8230; and so on, 38 times.</span></div>
</div>
<div>
<div><span style="font-family: 'courier new', monospace;">end</span></div>
</div>
</blockquote>
<p>Note for step #1. It caused me to refactor some other specs as well. This turned out to be a good thing, as I was able to speed up several other specs, and add some clarity to those specs that required building out a company structure.</p>
<div></div>
<h3><strong>Results</strong></h3>
<p>2.5 seconds. Not too shabby.</p>
<p>After the refactoring for all tests, I dropped ~30 more seconds off the entire suite.</p>
<p>&nbsp;</p>
<p>Hope this helps someone else out there improve the speed of their specs too.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=llZf53c4OVw:f0CdjXSMXHQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=llZf53c4OVw:f0CdjXSMXHQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=llZf53c4OVw:f0CdjXSMXHQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=llZf53c4OVw:f0CdjXSMXHQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=llZf53c4OVw:f0CdjXSMXHQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/llZf53c4OVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2012/07/09/small-revelation-factorygirl-build_stubbed-associations-and-let/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2012/07/09/small-revelation-factorygirl-build_stubbed-associations-and-let/</feedburner:origLink></item>
		<item>
		<title>Monitor Your Elk-M1, Log to MySQL, and Daemonize it!</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/0m_l_iHd0sA/</link>
		<comments>http://blog.spoolz.com/2009/04/25/monitor-your-elk-m1-log-to-mysql-and-daemonize-it/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 03:29:43 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Home Automation]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[daemon]]></category>
		<category><![CDATA[elk]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=188</guid>
		<description><![CDATA[I received a request a couple of days ago from someone who saw my posts on the Elk&#8211;Control perl library that I took over responsibility for. I had mentioned that I logged every Elk event into a MySQL database. I am happy to report that I have this script running as a daemon, logging every ElkM1 event into my database. And it runs for months without issue. I will keep these instructions brief. If you have detailed questions, please ask in the comments and I&#8217;ll help the best I can. Download You can download all the scirpts, just click here. Notables If you don&#8217;t know a least a little perl &#8230; <p><a href="http://blog.spoolz.com/2009/04/25/monitor-your-elk-m1-log-to-mysql-and-daemonize-it/#more-188" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>I received a request a couple of days ago from someone who saw my posts on the <a href="http://blog.spoolz.com/2009/01/30/elk-m1-security-system-control-with-perl-script/">Elk&#8211;Control</a> perl library that I took over responsibility for. I had mentioned that I logged every Elk event into a MySQL database.</p>
<p>I am happy to report that I have this script running as a daemon, logging every ElkM1 event into my database. And it runs for months without issue.</p>
<p>I will keep these instructions brief. If you have detailed questions, please ask in the comments and I&#8217;ll help the best I can.</p>
<h3>Download</h3>
<p>You can download all the scirpts, <a href='http://blog.spoolz.com/wp-content/uploads/2009/04/elk_mysql_scripts.zip'>just click here</a>.</p>
<h3>Notables</h3>
<ol>
<li>If you don&#8217;t know a least a little perl and some MySQL basics, you may want to look elsewhere.</li>
<li>The script and accompanying files are designed to work in concert as a daemonized process.</li>
<li>Everything is logged into &#8216;elk_monitor.log&#8217; in the same directory (or directory of your choosing) as the script. If you have a lot of passive infra-red motion detectors, you will want to monitor the log size.
</ol>
<h3>Basic File Structure</h3>
<p><img src="http://blog.spoolz.com/wp-content/uploads/2009/04/picture-13.png" alt="file structure" title="file structure" width="169" height="110" class="aligncenter size-full wp-image-189" /></p>
<h4>elk_monitor.pl</h4>
<p>This is the main script, it runs in a loop checking for new messages every second. You <em>will</em> need edit the %zonelist, %outputs, %areas near the top. Also, you will need to set some paths, look near the top of the file.</p>
<p>Required: <a href="http://github.com/threadhead/elkm1--control/tree/master">ElkM1::Control</a>, <a href="http://log4perl.sourceforge.net/">Log4perl</a></p>
<h4>elk_monitor.sh</h4>
<p>This is the shell script that controls <em>elk_monitor.pl</em> as a daemon. Setting up daemons can be complex as each system is different, so google around for some help.</p>
<h4>elkm1.sql</h4>
<p>A MySQL script to setup the tables and fields that the <em>elk_monitor.pl</em> script uses. You <em>will</em> need to add a database named &#8216;elkm1&#8242;. After that you can execute this script to create everything else for you.</p>
<h4>lib/elkm1_db.pl</h4>
<p>The database setting and basic sql commands are abstracted into this library. This is where you will need to set MySQL&#8217;s host, name, password, etc.</p>
<h4>lib/file_tickler.pl</h4>
<p>I use a custom ruby script to monitor the daemon. This library just touches a file every minute to let us know the <em>elk_monitor.pl</em> script is still running. Why? Well, I have had the script &#8216;freeze&#8217; without exiting and most monitoring applications do not detect this. Obviously, this part is optional.</p>
<h3>Conclusion</h3>
<p>If you get all the settings right, she should run all day/week/month for you.</p>
<p>I and <strong>not</strong> a perl expert. Far from it. So I&#8217;m sure everything could use some tidying. If you do, please let me know and I&#8217;ll incorporate your changes.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=0m_l_iHd0sA:LHdEelf-R1s:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=0m_l_iHd0sA:LHdEelf-R1s:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=0m_l_iHd0sA:LHdEelf-R1s:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=0m_l_iHd0sA:LHdEelf-R1s:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=0m_l_iHd0sA:LHdEelf-R1s:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/0m_l_iHd0sA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2009/04/25/monitor-your-elk-m1-log-to-mysql-and-daemonize-it/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2009/04/25/monitor-your-elk-m1-log-to-mysql-and-daemonize-it/</feedburner:origLink></item>
		<item>
		<title>Sinatra-Tailer: a small app for viewing server log files</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/iLrLJfETtHc/</link>
		<comments>http://blog.spoolz.com/2009/03/18/sinatra-tailer-a-small-app-for-viewing-server-log-files/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 23:03:24 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[sinatra]]></category>
		<category><![CDATA[tail]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=177</guid>
		<description><![CDATA[I was reading Jason Seifer&#8217;s: Offline Gem Server Rdocs, which is an apache/passenger served Sinatra app that allows you to view the Rdocs of installed gems without using gem server. Nice. So I installed it on our sandbox server for all to enjoy. But it got me thinking, there is another think I like to keep an eye on on our servers&#8230; log files. Oh, and I was looking for good excuse to play around with Sinatra. So, &#8220;with a one, and-a-two, and-a-three&#8230;&#8221; we have Sinatra-Tailer. You can read all about it on the github page, but in short it simply performs a tail and displays the last X lines &#8230; <p><a href="http://blog.spoolz.com/2009/03/18/sinatra-tailer-a-small-app-for-viewing-server-log-files/#more-177" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>I was reading <a href="http://jasonseifer.com/2009/02/22/offline-gem-server-rdocs">Jason Seifer&#8217;s: Offline Gem Server Rdocs</a>, which is an apache/passenger served <a href="http://www.sinatrar.com">Sinatra</a> app that allows you to view the Rdocs of installed gems without using <em>gem server</em>. Nice. So I installed it on our sandbox server for all to enjoy.</p>
<p>But it got me thinking, there is another think I like to keep an eye on on our servers&#8230; log files. Oh, and I was looking for good excuse to play around with Sinatra. So, &#8220;with a one, and-a-two, and-a-three&#8230;&#8221; we have <a href="http://github.com/threadhead/sinatra-tailer/tree">Sinatra-Tailer</a>.</p>
<p>You can <a href="http://github.com/threadhead/sinatra-tailer/tree">read all about it on the github page</a>, but in short it simply performs a <em>tail</em> and displays the last X lines of the log file.</p>
<pre class="brush: bash">
tail -n /path/to/my/log/file.log
</pre>
<h3>Features</h3>
<ol>
<li>refreshes the list every X seconds, set by the user</li>
<li>only one config.yml file to edit</li>
<li>supports file globs, so you can grab a whole list of file with one line</li>
<li>specify the number of lines to show</li>
<li>completely unobtrusive js, because I&#8217;m cool?</li>
</ol>
<h3>Requirements</h3>
<ol>
<ul><a href="http://www.sinatrarb.com">Sinatra framework</a> (tested on 0.9.1.1, earlier may work)</ul>
</ol>
<p>I whipped this up pretty quickly so I&#8217;m sure there are a few bugs. There is some testing for a few unit tests, but nothing functional.</p>
<p>One word of warning, if you want to put this on a production server my recommendation is to put it on a separate port (like 9876) and <strong>for heaven&#8217;s sake</strong>, at a minimum use http basic authentication. From the sinatra <a href="http://www.sinatrarb.com/intro.html">readme</a>:</p>
<pre class="brush: ruby">
  use Rack::Auth::Basic do |username, password|
    username == &#039;admin&#039; &amp;amp;&amp;amp; password == &#039;secret&#039;
  end
</pre>
<p>Enjoy!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=iLrLJfETtHc:zcFAkLkE6N8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=iLrLJfETtHc:zcFAkLkE6N8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=iLrLJfETtHc:zcFAkLkE6N8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=iLrLJfETtHc:zcFAkLkE6N8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=iLrLJfETtHc:zcFAkLkE6N8:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/iLrLJfETtHc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2009/03/18/sinatra-tailer-a-small-app-for-viewing-server-log-files/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2009/03/18/sinatra-tailer-a-small-app-for-viewing-server-log-files/</feedburner:origLink></item>
		<item>
		<title>Apache Virtual Hosts, Rails, Rack, Passenger on Local Net</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/oXAydZoV280/</link>
		<comments>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 19:51:03 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[sinatra]]></category>
		<category><![CDATA[virtual host]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=143</guid>
		<description><![CDATA[This one has been bugging me for a couple of years and I just didn&#8217;t want to put in the time and testing to nail it down. But tonight was my night. The Problem Here in my development palace I have a couple of laptops that I use for development and an Ubuntu (hardy) server as a Rails/Rack sandbox that I run with Passenger. While I have always been able to serve up either a Rails or Sinatra project, I typically have 3 or 4 going at the same time. But I had to access them with urls like: http://192.168.0.2/project1 and http://192.168.0.2/project2. So, what&#8217;s the problem, eh? Well, for starters, &#8230; <p><a href="http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/#more-143" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>This one has been bugging me for a couple of years and I just didn&#8217;t want to put in the time and testing to nail it down. But tonight was my night.</p>
<h3>The Problem</h3>
<p>Here in my development palace I have a couple of laptops that I use for development and an Ubuntu (hardy) server as a <a href="http://rubyonrails.org/">Rails</a>/<a href="http://rack.rubyforge.org/">Rack</a> sandbox that I run with <a href="http://modrails.com">Passenger</a>. While I have always been able to serve up either a Rails or <a href="http://www.sinatrarb.com/">Sinatra</a> project, I typically have 3 or 4 going at the same time. But I had to access them with urls like: <em>http://192.168.0.2/project1</em> and <em>http://192.168.0.2/project2</em>.</p>
<p>So, what&#8217;s the problem, eh?</p>
<p>Well, for starters, you can&#8217;t do anything concerning subdomains. That&#8217;s a show stopper for many apps.</p>
<p>Second, it really messes with your environment variables like <em>["PATH_INFO"]</em>. So if you do any routing and you expect the base url to be <em>&#8216;/&#8217;</em>, it won&#8217;t be. The root url will be &#8216;/projectx&#8217;. Bummer.</p>
<h3>The Solution</h3>
<p>To remedy the issues with non-<a href="http://en.wikipedia.org/wiki/Top-level_domain">tld</a> virtual hosts (also called sub URIs?) we need to add the domains to the laptops and server, then add the virtualhosts on the server for apache. This means that I can now goto <em>http://project1.ubuntu.remote</em> url to get to my rails/rack app.</p>
<p>For reference, I am using the following:</p>
<ul>
<li>Laptops: Mac OS X, 10.5.7 and 10.4.11</li>
<li>Server: <a href="http://www.ubuntu.com/">Ubuntu</a> Desktop 8.04LTS, <a href="http://www.apache.org/">Apache</a>/2.2.8 (Ubuntu) <a href="http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html">mod_fastcgi</a>/2.4.6 PHP/5.2.4-2ubuntu5.5 with <a href="http://modrails.com">Suhosin-Patch Phusion_Passenger/2.0.6</a></li>
</ul>
<h4>On Each Laptop</h4>
<p>These instructions are for Mac OS X, but should be identical for your favorite flavor of *nix. We are going to add some friendly names to our ubuntu server using it&#8217;s ip address (192.168.0.2). In this example we will be able to access the root web documents using <em>http://ubuntu.remote</em>, and one of our Sinatra projects using <em>http://project1.ubuntu.remote</em>.</p>
<p><strong>Important!</strong> Don&#8217;t use a name ending in <em>&#8216;.local&#8217;</em>. While it did work for me, I read about a few instances where some systems will not resolve domain names ending in .local outside the local machine. Also, don&#8217;t change <strong>anything</strong> else in your /etc/hosts file except to add the lines at the end.</p>
<pre class="brush: python">
mate /etc/hosts

# add the following line to the END of your /etc/hosts file and save
# note: there is a &lt;space&gt; character between the ip address and each host name
192.168.0.2 ubuntu.remote project1.ubuntu.remote
</pre>
<h4>On The Server: Hosts File</h4>
<p>Nothing will work until we tell the server machine that it can accept incoming traffic from our new friendly names. Similar to on the mac, we need to edit our /etc/hosts file but we will add a slightly different line. In this case we are telling the server that incoming traffic from &#8216;ubuntu.remote&#8217; and &#8216;gems.ubuntu.remote&#8217; are just names for the localhost (127.0.0.1).</p>
<pre class="brush: shell">sudo pico /etc/hosts

# add the following line to the end of our /etc/hosts file and save
# you can added after your existing 127.0.0.1 line if you wish
127.0.0.1 ubuntu.remote project1.ubuntu.remote
</pre>
<h4>On The Server: VirtualHosts</h4>
<p>As a final step we will need to add or change the virtual host definitions for your rails/rack project. Depending on your Apache setup or Linux distro, the default enabled site may be slightly different and you may have to adapt your virtual host file to your default setup.</p>
<p>First, in my /etc/apache2/apache.conf file, I have the following line near the end of the file. This was to eliminate a warning every time apache was started/restarted. It may affect your virtual host default, but shouldn&#8217;t, so add it if you get errors.</p>
<pre class="brush: shell">
#added near end of /etc/apache2/apache.conf
ServerName localhost
</pre>
<p>Next we need to check our default virtual host setup to see how the NameVirtualHost is defined. We will duplicate that in each new virtual host that we add. The parts we are looking is the NameVirtualHost and VirtualHost near the top. They could be &#8216;NameVirtualHost *&#8217; and &#8216;&lt;VirtualHost *&gt;&#8217; or &#8216;NameVirtualHost *:80&#8242; and &#8216;&lt;VirtualHost *:80&gt;&#8217;. See the pattern? We need to use the same definition in our new virtual files.</p>
<p>Let&#8217;s check our default virtual host setup:</p>
<pre class="brush: shell">
cd /etc/apache2/sites-enabled
ls # your are looking for the name of your default site file

  total 0

  lrwxrwxrwx 1 root root 36 2009-02-27 18:49 000-default -&gt; /etc/apache2/sites-available/default

cat /etc/apache2/sites-enabled/000-default

  NameVirtualHost *
  &lt;VirtualHost *&gt;
    ServerAdmin webmaster@localhost
  # snipped several lines #
  &lt;/VirtualHost&gt;
</pre>
<p>On my system the NameVirtualHost is &#8216;*&#8217;, so that is what we need to use for the new virtual host. In this case, I am going to add a virtual host file for a rack based project. It&#8217;s a Sinatra app, but that doesn&#8217;t matter as this will work for any rack based project, even a rails/rack project (since rails 2.2.2?).</p>
<p>Also, I like using the Apache2 system to enable and disable sites. It&#8217;s clean, easy to use, and if any apache admin comes along they will know exactly what is going on.</p>
<p>It&#8217;s also work mentioning that you should disable or delete any existing virtual host files that you were using previously.</p>
<pre class="brush: shell">cd /etc/apache2/sites-available
sudo pico gems

# enter this as your virtual host setup
&lt;VirtualHost *&gt;
  ServerName project1.ubuntu.remote

  DocumentRoot &quot;/path/to/your/application/project/public&quot;

  RackEnv production
  &lt;directory &quot;/path/to/your/application/project/public&quot;&gt;
    Order allow,deny
    Allow from all
  &lt;/directory&gt;
&lt;/VirtualHost&gt;

# save the file and reload apache

sudo /etc/init.d/apache2 reload
</pre>
<h4>The Fun Part</h4>
<p>Assuming you saw no errors when you reloaded apache, you should be able to go to your new urls see both the root files and your rack application.</p>
<p>http://ubuntu.remote</p>
<p>http://project1.ubuntu.remote</p>
<p><strong>Dyn-O-Mite!</strong></p>
<h3>Bonus Points!</h3>
<p>For extra credit, let&#8217;s say you have admin access to your router, and you are one of those gotta-have-control-of-everything dudes (or dudettes) so you installed a 3rd party firmware. You&#8217;re in luck! You can probably add some custom entries in your DNS and you don&#8217;t have to edit the /etc/hosts files on your laptop.</p>
<p>I installed <a href="http://www.polarcloud.com/tomato/">Tomato firmware</a> on my Linksys wireless router. Tomato uses <a href="http://localhost:9292/doc_root/actionmailer-1.3.6/rdoc/index.html">Dnsmasq</a> with allows you to set internal host names.</p>
<p>Maybe I&#8217;ll cover that in another post.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=oXAydZoV280:oYRx79MK83I:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=oXAydZoV280:oYRx79MK83I:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=oXAydZoV280:oYRx79MK83I:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=oXAydZoV280:oYRx79MK83I:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=oXAydZoV280:oYRx79MK83I:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/oXAydZoV280" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/</feedburner:origLink></item>
		<item>
		<title>Elk M1 Security System Control with Perl Script</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/KeafEKqEvQ0/</link>
		<comments>http://blog.spoolz.com/2009/01/30/elk-m1-security-system-control-with-perl-script/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 17:42:26 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Home Automation]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[elk]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=129</guid>
		<description><![CDATA[I have an Elk M1 security system that I like to monitor and record all the activity. It&#8217;s useful to know what doors are open and how long they have been open. For several years in the past I have use Homeseer to do the monitoring where I wrote VBScript files to push the activity and changes to my MySQL server. Honestly, I have never likes Homseer, it&#8217;s flaky and I prefer that I don&#8217;t depend on WinXP either. About a year ago, James Russo released a script on Cocoontech to monitor and control your Elk M1 from a perl script. You can read the forum post for more details. Thanks to &#8230; <p><a href="http://blog.spoolz.com/2009/01/30/elk-m1-security-system-control-with-perl-script/#more-129" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>I have an <a href="http://www.elkproducts.com/index2.html" target="_blank">Elk M1 security</a> system that I like to monitor and record all the activity. It&#8217;s useful to know what doors are open and how long they have been open. For several years in the past I have use <a href="http://www.homeseer.com/" target="_blank">Homeseer</a> to do the monitoring where I wrote VBScript files to push the activity and changes to my MySQL server. Honestly, I have never likes Homseer, it&#8217;s flaky and I prefer that I don&#8217;t depend on WinXP either.</p>
<p>About a year ago, James Russo released a script on <a href="http://www.cocoontech.com" target="_blank">Cocoontech</a> to monitor and control your Elk M1 from a perl script. You can <a href="http://www.cocoontech.com/index.php?showtopic=8920" target="_blank">read the forum post</a> for more details. Thanks to James and other Cocoontech members, it works fairly well.</p>
<p>But there have been no updates or bug fixes in over a year. Not wanting to relive my perl days (sorry, I never really liked perl), I decided to revive the project and give it a new home. I asked James for permission to take over the project and he gracefully agreed.</p>
<h4>ElkM1::Control New Home on Github</h4>
<p>Go check it out! <a href="http://github.com/threadhead/elkm1--control/tree">ElkM1::Control on github</a>.</p>
<p>Why github? First, I have stopped using SVN. And sourceforge, ElkM1::Control&#8217;s original home, doesn&#8217;t support git. Second, github makes it too easy to fork a project and make changes yourself, then push them back up so that I can integrate those changes. You really should try <a href="http://git-scm.com/" target="_blank">git</a> if you haven&#8217;t before. And you don&#8217;t need git to download ElkM1::Control and install it.</p>
<h4>Updates and Bug Fixes!</h4>
<p>You read that right, I have made a few bug fixes and added a couple of new features. I have been running ElkM1::Control on my Ubuntu Hardy server for about a month with no problems. I have also run and do some debugging on OS X (10.5.x).</p>
<p>I also changed the version numbering system to the more common <em>major.minor.release</em> notation. We are not at version 0.1.0.</p>
<h4>Quick Installation Instructions</h4>
<ol>
<li>Goto the <a href="http://github.com/threadhead/elkm1--control/tree" target="_blank">project home page</a> and click the <em>download</em> button. Select the ZIP version (for some reason the TAR doesn&#8217;t work sometimes).</li>
<li>Follow the README file, don&#8217;t forget the PREREQUISITES section. For those who don&#8217;t rtfm&#8230;</li>
<li>From your favorite shell, you may need to add sudo in front of each: &#8216;perl Makefile.PL&#8217;</li>
<li>&#8216;make&#8217;</li>
<li>&#8216;make test&#8217;</li>
<li>Then to install: &#8216;make install&#8217;</li>
</ol>
<p>Next, you&#8217;ll need a little script to get going. There are <a href="http://www.cocoontech.com/index.php?showtopic=8920" target="_blank">several scripts posted on Cocoontech</a>, but this one should get you started:</p>
<pre class="brush: php">
# Example 2: Display all M1 messages
use ElkM1::Control;
    my $elk = ElkM1::Control-&gt;new(host =&gt; &#039;192.168.0.251&#039;, port =&gt; 2101);
    while (1) {  # Loop forever
        while (my $msg = $elk-&gt;readMessage) { # Read the M1&#039;s messages
                print $msg-&gt;toString;  # Print the messages
        }
    }
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=KeafEKqEvQ0:4EKE0cEypds:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=KeafEKqEvQ0:4EKE0cEypds:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=KeafEKqEvQ0:4EKE0cEypds:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=KeafEKqEvQ0:4EKE0cEypds:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=KeafEKqEvQ0:4EKE0cEypds:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/KeafEKqEvQ0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2009/01/30/elk-m1-security-system-control-with-perl-script/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2009/01/30/elk-m1-security-system-control-with-perl-script/</feedburner:origLink></item>
		<item>
		<title>Authlogic – Rails Authentication Done Right</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/fbY4weLLugI/</link>
		<comments>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 21:56:24 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[authentication]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=119</guid>
		<description><![CDATA[Sorry to borrow the title line directly from Ben&#8217;s site, but Authlogic is the authentication system I have been looking for. Bye, bye restful authentication. Hello easy, simple, get out of my way, easily upgradeable, smartly written Authlogic. I shouldn&#8217;t disrespect restful authentication much as she has been with me for over a year now. But every time I had to install, setup, and get the basics working in RA I couldn&#8217;t help gnashing my teeth. I jumped on the RA bandwagon like so many other Rails developers looking for an authentication system that just and move on to more important things. Enter Authlogic by Ben Johnson of BinaryLogic. By luck, I &#8230; <p><a href="http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/#more-119" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>Sorry to borrow the title line directly from Ben&#8217;s site, but <a href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Authlogic</a> is the authentication system I have been looking for. Bye, bye restful authentication. Hello easy, simple, get out of my way, easily upgradeable, smartly written Authlogic.</p>
<p>I shouldn&#8217;t disrespect restful authentication much as she has been with me for over a year now. But every time I had to install, setup, and get the basics working in RA I couldn&#8217;t help gnashing my teeth. I jumped on the RA bandwagon like so many other Rails developers looking for an authentication system that just and move on to more important things.</p>
<p>Enter Authlogic by Ben Johnson of <a href="http://www.binarylogic.com/">BinaryLogic</a>. By luck, I was starting a new rails app this week, so I decided to take Authlogic out for a test drive. Following Ben&#8217;s <a title="Tutorial: Authlogic Basic Setup" href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Tutorial: Authlogic Basic Setup</a> I had a basic login/logout/session management system up and running in a ridiculously little amount of code. The best part of Authlogic is that it truly get&#8217;s out of my way and provides me with what I need&#8230; a robust and secure methodology of authentication and session management.</p>
<p>The benefits of Authlogic are:</p>
<ul>
<li>It&#8217;s a plugin and a gem. When Ben pushes an update, getting the latest release is super simple.</li>
<li>It&#8217;s a plugin and a gem. This keeps the authentication code separate from your codes, the way it should be.</li>
<li>Session are treated like ActiveRecord objects. This is just as cools as it sounds and is very Rails-like.</li>
<li>Better security. Authlogic uses a non-reversible token that is changed on every session initiation and password change, thus virtually eliminating session persistence and brute force session attacks.</li>
<li>Ben Johnson. Ben knows what he is doing and has been quickly releasing updates.</li>
<li>Ben Johnson. Sorry for the repetition, but Ben also has a nice series of tutorials with supporting project code you can download.
<ul>
<li><a title="Tutorial: Reset passwords with Authlogic the RESTful way" href="http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic">Tutorial: Reset passwords with Authlogic the RESTful way</a></li>
<li><a title="Tutorial: Authlogic Basic Setup" href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Tutorial: Authlogic Basic Setup</a></li>
</ul>
</li>
</ul>
<div>Read more on on <a href="http://www.binarylogic.com/2008/10/25/authlogic-released-rails-authentication-done-right">BinaryLogic</a> or get it at <a href="http://github.com/binarylogic/authlogic/tree/master">Github</a>.</div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=fbY4weLLugI:HYvXOE1hz94:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=fbY4weLLugI:HYvXOE1hz94:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=fbY4weLLugI:HYvXOE1hz94:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=fbY4weLLugI:HYvXOE1hz94:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=fbY4weLLugI:HYvXOE1hz94:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/fbY4weLLugI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/</feedburner:origLink></item>
		<item>
		<title>iPhoto AppleScript to Remove Duplicates</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/WaruBZho9_c/</link>
		<comments>http://blog.spoolz.com/2008/11/03/iphoto-applescript-to-remove-duplicates/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 18:04:56 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[iphoto]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=72</guid>
		<description><![CDATA[Short Story: I had several years of photos that I needed to identify and remove the duplicate. Instead of manually combing through 12,000 (read Long Story below) and before carpal tunnel set in, I needed a script to help me out. My situation may or may not be unique, so this script may not work 100% out-of-the-box for you, but it should get you started. This script will identify duplicate photos in your iPhoto library and mark them with a comment (keyword) of &#8220;duplicate&#8221;. It will not delete anything. To use: Download and unzip the script Double-click the script to open in Script Editor Go into iPhoto and select a &#8230; <p><a href="http://blog.spoolz.com/2008/11/03/iphoto-applescript-to-remove-duplicates/#more-72" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<h3>Short Story:</h3>
<p><img class="alignleft" title="iphoto_icon" src="http://blog.spoolz.com/wp-content/uploads/2008/11/iphoto_icon.png" alt="" width="128" height="128" />I had several years of photos that I needed to identify and remove the duplicate. Instead of manually combing through 12,000 (read Long Story below) and before carpal tunnel set in, I needed a script to help me out. My situation may or may not be unique, so this script may not work 100% out-of-the-box for you, but it should get you started.</p>
<p><a href="http://blog.spoolz.com/wp-content/uploads/2008/11/iphoto-remove-duplicates.zip"><img class="alignright size-full wp-image-95" title="download_scpt_button-trans" src="http://blog.spoolz.com/wp-content/uploads/2008/11/download_scpt_button-trans.png" alt="" width="206" height="85" /></a></p>
<div>This script will identify duplicate photos in your iPhoto library and mark them with a comment (keyword) of &#8220;duplicate&#8221;. <em>It will not delete anything</em>.</div>
<p>To use:</p>
<ol>
<li>Download and unzip the script</li>
<li>Double-click the script to open in Script Editor</li>
<li>Go into iPhoto and select a group of photos you want to compare</li>
<li>Switch back to Script Editor and run the script</li>
<li><strong>Don&#8217;t Touch Anything!</strong> Just let the script finish, it could take a while if you are comparing a lot of photos</li>
<li>After the script is done, go back into iphoto and search for &#8220;duplicate&#8221; <img class="alignnone size-full wp-image-81" title="duplicate" src="http://blog.spoolz.com/wp-content/uploads/2008/11/duplicate.png" alt="" width="200" height="28" /></li>
<li>You can highlight all the duplicates and delete them or move them some place safe</li>
</ol>
<p>Photos are considered a duplicate if:</p>
<ol>
<li>both heights match</li>
<li>both widths match</li>
<li>the photo date in iPhoto match, this is typically the EXIF creation date</li>
</ol>
<div>There are no error checks in this script and it presents no interface except an alert when it&#8217;s done. If you need help, just post a comment below and I&#8217;ll do my best.</div>
<h3>Long Story:</h3>
<p><span id="more-72"></span></p>
<div>About a year ago I was editing down my iPhoto library of about 6000 images, just gitting rid of those out-of-focus shots and the ones of my wife&#8217;s feet (a curiously large number of these). After a long night of editing, the next morning I awoke to start again, but when I ran iPhoto there was nothing in the library.</div>
<div><strong>It was all gone!</strong></div>
<div>I couldn&#8217;t find anything anywhere. Could I restore from a backup? Ooh nooo. I had erased my backup drive the day before in preparation for moving the unwanted photos onto the backup drive and then making a new backup of my iPhoto Library. So I had no backup.</div>
<div>Not really funny. These were all the shots of my boys being born, first steps, first birthdays, first everything. I was up sh*t creek and it put a serious hurt in my stomach. At least I knew what to do: do nothing on the computer, boot from the Mac OS X install DVD and use Disk Utility to make a byte-for-byte copy of my internal hard disk. I could use this disk image to recover the images, hopefully.</div>
<div>So I tried several image recovery utilities and finally settled on <a href="http://www.datarescue.com/photorescue/v3/index.htm" target="_blank">PhotoRescue</a> for Mac. I mounted the disk image of my internal disk and set PhotoRescue to the task. About 9 hours later (not a typo), PhotoRescue gave me several folders of recovered JPEGs, TIFFs, GIFs and PNGs. I tossed all but the JPEGs. I felt a little better at this point.</div>
<div>But when I looked in the JPEG folder there was over 12,000 images! Huh? Well, PhotoRescue does not discriminate, it recovers ALL images, including thumnails, web graphics, <a href="http://en.wikipedia.org/wiki/Pron#Pr0n">pron</a> (you&#8217;ve been warned). Frankly, it was unbelievable and overwhelming.</div>
<div>So I set about dividing the images into folder that I knew were junk images and ones that I may want to keep. First, I eliminated everything below about 120K. I knew that my oldest digital camera was around 3M pixels and it saved a file that was typically &gt; 200K so those images below 120K were most likely thumbnails and web images. That cut my stack almost in half.</div>
<div>Next I looked for images &gt; 3M. These were corrupted image files that while they looked ok in Preview, I knew there was no way a 1200&#215;1600 images was 40M. Just a consequence of PhotoRescue&#8217;s recovery routine. I can live with that, believe me. So I tossed everything &gt; 3M because my current 6M pixel camera images are under 2M in size.</div>
<div>This left me with about 6,000 images that I imported into a new iPhoto Library. From the looks of it, all my images were there! What a relief, but the bad news was nothing was rotated properly, and there were many, many duplicates. Thousands of duplicates to be exact. After I rotated all the images so that I could view them properly, I set about removing the duplicates.</div>
<div>The good news about removing the duplicates was that they were fairly easy to spot. When I imported all the recovered images into iPhoto it apparently used the EXIF data data to date stamp each photo instead of using the photo file&#8217;s creation date, which was set by PhotoRescue to the day I performed the recovery. So all my photo&#8217;s were dated properly, I just had to look at each photo that matches (they were sorted by date) the one next to it and delete one of them.</div>
<div>A closer look at the duplicate photos revealed that while they had the same height, width and date/time, they varied in size. I was not able to determine why the file sizes varied as the images themselves looked identical, but my best guess is that the size difference came about from iPhoto&#8217;s insistence that when you rotate an image iPhoto considers this an &#8220;edit&#8221; and makes a copy of the original and add&#8217;s some iPhoto specific data (no verification on this though). So hey, if you are going to keep one, why not keep the smaller of the image files? So that&#8217;s what I was doing.</div>
<div>After hours and days of removing duplicates, I decided there has to be a better way. A bit of searching for &#8220;applescript iphoto remove duplicates&#8221; let me to <a href="http://www.brattoo.com/propaganda/index.php?action=software" target="_blank">Brattoo Propaganda Software&#8217;s Duplicate Annihilator</a>. I tried the demo and it works very well. But there was one thing I wanted to do that Duplicate Annihilator could not, and that is mark the larger of the duplicate files. Duplicate Annihilator marks duplicate files by date/time which I am sure is what most people want to do. So definitely check it out.</div>
<div>So Duplicate Annihilator minor missing feature led me to write my own AppleScript to do pretty much the same. The script is pretty simple and requires no additional libraries or command line voodoo. But I will say that coding in Ruby for the past year-and-a-half really reminds my why I don&#8217;t like AppleScript. AS gets the job done, but it&#8217;s so much more work, frankly it&#8217;s confusing, and if you don&#8217;t do it often it&#8217;s a lot of work getting your head around AS&#8217;s nomenclature.</div>
<div>For you fellow rubists, there is <a href="http://appscript.sourceforge.net/rb-appscript/index.html" target="_blank">rb-appscript</a> which would have made my pain a little easier, but it relies on ruby and having the rb-appscript gem installed and that would be too much for most casual Mac users. So AppleScript won this round, but only because I knew I wanted to share the script for others.</div>
<div>Good luck to all you photo recoverers. I&#8217;ve been down your road before.</div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=WaruBZho9_c:mQLNMMoeAqQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=WaruBZho9_c:mQLNMMoeAqQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=WaruBZho9_c:mQLNMMoeAqQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=WaruBZho9_c:mQLNMMoeAqQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=WaruBZho9_c:mQLNMMoeAqQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/WaruBZho9_c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/11/03/iphoto-applescript-to-remove-duplicates/feed/</wfw:commentRss>
		<slash:comments>88</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2008/11/03/iphoto-applescript-to-remove-duplicates/</feedburner:origLink></item>
		<item>
		<title>Batter Blaster – Wrong for America</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/CYEgLXStCj4/</link>
		<comments>http://blog.spoolz.com/2008/09/11/batter-blaster-wrong-for-america/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 04:05:37 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Peeves]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=47</guid>
		<description><![CDATA[Ok, the title is a tad hyperbolic, but when I saw this in Costco a few months ago a tiny rage welled inside. We were shopping on a Saturday when we came across Batter Blaster. The spiel was along the lines of how much easier breakfast would be with pancakes from a can. Breakfast from a Can? WTF! At first, I honestly thought it was a joke, but I was compelled to stop and pick up the can and watch our demo maven squirt batter out of a can onto the griddle. I did try one, and it tasted OK, but nothing better than what I make for the kids &#8230; <p><a href="http://blog.spoolz.com/2008/09/11/batter-blaster-wrong-for-america/#more-47" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p><a rel="http://www.batterblaster.com/index.php" href="http://blog.spoolz.com/wp-content/uploads/2008/09/batter_blaster1.jpg" target="_blank"><img class="alignright size-full wp-image-52" title="batter_blaster1" src="http://blog.spoolz.com/wp-content/uploads/2008/09/batter_blaster1.jpg" alt="" width="180" height="160" /></a>Ok, the title is a tad hyperbolic, but when I saw this in <a href="http://www.costco.com/">Costco</a> a few months ago a tiny rage welled inside. We were shopping on a Saturday when we came across <a href="http://www.batterblaster.com/index.php" target="_blank">Batter Blaster</a>. The spiel was along the lines of how much easier breakfast would be with pancakes from a can.</p>
<p><strong>Breakfast from a Can? WTF!</strong></p>
<p><span id="more-47"></span></p>
<p>At first, I honestly thought it was a joke, but I was compelled to stop and pick up the can and watch our demo maven squirt batter out of a can onto the griddle. I did try one, and it tasted OK, but nothing better than what I make for the kids on weekends. That&#8217;s when the whole thing <em>really</em> started to bother me.</p>
<h4>Ridiculously High Cost!</h4>
<p>I doubt one can could hold its own against my two boys. And the three pack can was something like $7.00 (please comment if you know the real price). Geeze Louise that is expensive. According to the label each can will make 28 &#8211; 4in. pancakes. I have some pretty serious doubts about that claim. Those must be <em>some darn thin pancakes</em>.</p>
<p>By their own admission, there is only 2.25 cups of batter in each can. When I make pancakes, I use a ladle that is 6oz. which I reckon results in 4oz. <strong>per pancake</strong>. And each of my boys will eat 3 to 4 of those suckers, without batting an eye. That comes out to <span style="text-decoration: underline;"><strong>ONE </strong></span><span style="text-decoration: underline;"><strong>CAN</strong></span> per child. And my kids are not the video game, boob tube species either. In fact both are a tad on the skinny side.</p>
<h4>Could You Be More Environmentally Unfriendly or What?</h4>
<p>Don&#8217;t prattle on to me about how steel cans are recyclable. The amount of energy to produce and recycle those cans, the extra weight of shipping, the added shelf space, not to mention that you must keep it refrigerated are all energy wastes. And completely unnecessary.</p>
<p>My pancakes come in paper bags&#8230; um, flour, pinch of baking soda and baking powder, maybe some buttermilk if I have it around, , dash of salt, and an egg or two. Not much to recycle there. Even if you go the pancake mix route, all you have is one small box or plastic (recyclable) bag. Even better, Elise has a great recipe for <a href="http://www.elise.com/recipes/archives/001347blueberry_buttermilk_pancakes.php" target="_blank">Blueberry Buttermilk Pancakes</a> over at <a href="http://www.elise.com/recipes/" target="_blank">Simply Recipes</a>. Yum.</p>
<p>All that steel in the name of convenience is a shameful waste.</p>
<h4>Are People Really That Lazy?</h4>
<p>That was probably my first thought. Have people become so darn lazy that can&#8217;t mix a little water with some batter mix and make semi-homemade pancakes? I hope not. For crying in a bucket, how hard is it to mix up a little batter!</p>
<p>If you poke around on the blaster site, they have so-called testimonials from overly exuberant customers espousing how much time Batter Blaster has saved them and how convenient it was. All I can picture is one of those self-absorbed parents, squirting goo out of a can, while yapping on their cell phone, kids with permanent carpel tunnel jamming out on their NDS,  while cooking some pancakes. Woot, ain&#8217;t multi-tasking great. America, we sure have come a long way baby.</p>
<p><a rel="http://www.continentalmills.com/brands/krusteaz/pancake_waffle_mixes/buttermilk_pancake_mix/" href="http://blog.spoolz.com/wp-content/uploads/2008/09/krusteaz_-_pancake_mix_-_buttermilk.jpg" target="_blank"><img class="alignleft size-full wp-image-49" title="krusteaz_-_pancake_mix_-_buttermilk" src="http://blog.spoolz.com/wp-content/uploads/2008/09/krusteaz_-_pancake_mix_-_buttermilk.jpg" alt="" width="120" height="165" /></a>Let me put a better vision in your mind&#8230; you take a box of <a href="http://www.continentalmills.com/brands/krusteaz/pancake_waffle_mixes/buttermilk_pancake_mix/">Krusteaz Pancake &amp; Waffle Mix</a> out of your cupboard, let your son or daughter measure out a couple of cups of mix, show them how to calculate the appropriate amount of water to add, topping it off with a short mixing lesson. You just made something together, and they enjoyed spending time with you, and they will enjoy cooking because they actually did something useful.</p>
<p>Wow, educating your kids about cooking and math all while you develop a real relationship with your kids FTW! Flipping amazing.</p>
<p>BTW, they sell the Krusteaz mix in big bags at <a href="http://www.costco.com/">Costco</a> for around the same price as the blasters. I can only guess the <em>hundreds</em> of pancakes you can make with that bag, plus you&#8217;ll forgo chucking enough steel to build a <a href="http://en.wikipedia.org/wiki/Image:Go_Yugo.jpg" target="_blank">Yugo</a>.</p>
<h4>Please, Please, Please&#8230;</h4>
<p>Don&#8217;t by this product. It exists for only the wrong reasons. Do what is better for your wallet, your planet, and your family by exercising your brain and hands. Trust me, your kids will like you better for it.</p>
<p>If you have a favorite pancake or waffle recipe, please add it in the comments below.</p>
<p>I feel better now℠</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=CYEgLXStCj4:vW1lGGb5Kec:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=CYEgLXStCj4:vW1lGGb5Kec:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=CYEgLXStCj4:vW1lGGb5Kec:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=CYEgLXStCj4:vW1lGGb5Kec:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=CYEgLXStCj4:vW1lGGb5Kec:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/CYEgLXStCj4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/09/11/batter-blaster-wrong-for-america/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2008/09/11/batter-blaster-wrong-for-america/</feedburner:origLink></item>
		<item>
		<title>Butt Biter: Rails ‘truncate’ Method Broken in Ruby 1.8.7</title>
		<link>http://feedproxy.google.com/~r/DaddyFixesEverything/~3/teMG7pfzruQ/</link>
		<comments>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 04:01:48 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[butt biter]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=38</guid>
		<description><![CDATA[This one threw me for far too many minutes. In ActionView::Helpers::TextHelper the truncate method is broken for Ruby 1.8.7. I&#8217;m not exactly sure the version of ruby that it stopped working for, but I was previously on 1.8.6, and I don&#8217;t recall it not working. But after I upgraded to the latest patchlevel of 1.8.7, truncate stopped working. Update 12/2/08: Fixed in Rails 2.2! (read more) The error that I received was thus: ActionView::TemplateError (undefined method `length' for #) on line #83 of dashboard/index.html.erb: Fortunately, someone has submitted a ticket to Rails core. I hope it&#8217;s applied in the Rails 2.2.0 release. Current Method, Done Busted As of Rails 2.1.0, this &#8230; <p><a href="http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/#more-38" class="more-link">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
				<content:encoded><![CDATA[<p>This one threw me for far too many minutes. In <a href="http://www.railsbrain.com/api/rails-2.1.0/doc/index.html?a=C00000713&amp;name=TextHelper">ActionView::Helpers::TextHelper</a> the <a href="http://www.railsbrain.com/api/rails-2.1.0/doc/index.html?a=M002044&amp;name=truncate">truncate</a> method is broken for Ruby 1.8.7. I&#8217;m not exactly sure the version of ruby that it stopped working for, but I was previously on 1.8.6, and I don&#8217;t recall it not working. But after I upgraded to the latest patchlevel of 1.8.7, truncate stopped working.</p>
<h3><span style="color: #800000;">Update 12/2/08: Fixed in Rails 2.2! (<a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/867">read more</a>)</span></h3>
<p>The error that I received was thus:</p>
<p><code>ActionView::TemplateError (undefined method `length' for #) on line #83 of dashboard/index.html.erb:<br />
</code></p>
<p>Fortunately, someone has submitted a <a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/867">ticket to Rails core</a>. I hope it&#8217;s applied in the Rails 2.2.0 release.</p>
<p><span id="more-38"></span></p>
<h3>Current Method, Done Busted</h3>
<p>As of Rails 2.1.0, this is the current method (Rails 2.0.2 is similar, and also broken).</p>
<pre class="brush: ruby">&lt;br /&gt;
# File actionpack/lib/action_view/helpers/text_helper.rb, line 49&lt;br /&gt;
def truncate(text, length = 30, truncate_string = &quot;...&quot;)&lt;br /&gt;
if text&lt;br /&gt;
l = length - truncate_string.chars.length&lt;br /&gt;
chars = text.chars&lt;br /&gt;
(chars.length &gt; length ? chars[0...l] + truncate_string : text).to_s&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
</pre>
<p>The problem is that <em>chars</em> method called on the string object (<em>truncate_string</em>) returns an &lt;Enumerable::Enumerator&gt; object. And according to the Ruby 1.8.7 RDoc, there is no &#8216;length&#8217; method in Enumerable::Enumerator. To be honest, I can&#8217;t find the &#8216;chars&#8217; method in any of the Ruby <a href="http://www.ruby-doc.org/core/">1.8.6 docs</a> or <a href="http://www.ruby-doc.org/core-1.8.7/index.html">1.8.7 docs</a>. I guessing that it may have been Rails method at some time.</p>
<h3>Fix #1</h3>
<p>The fix is to get rid of all the <em>chars</em> methods. On the bug ticket, the author gives his fix, but you are going to have to monkey-patch rails, or change the method name.</p>
<pre class="brush: ruby">&lt;br /&gt;
def truncate(text, length = 30, truncate_string = &quot;...&quot;)&lt;br /&gt;
if text&lt;br /&gt;
l = length - truncate_string.chars.to_a.length&lt;br /&gt;
chars = text.chars&lt;br /&gt;
(chars.to_a.length &gt; length ? chars.to_a[0...l].to_s + truncate_string : text).to_s&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
</pre>
<h3>Fix #2 (mine, tiny bit better?)</h3>
<p>I&#8217;m not exactly sure why the string needs to be converted to an array, when the <a href="http://www.ruby-doc.org/core/classes/String.html#M000789">length</a> function works just dandy on string objects. So I added this to my <em>application_helper.rb</em> file. Also, in the submitted patch, the result of the ternary is converted to a string (.to_s), when all the resulting methods of the ternary return strings. Unnecessary IMHO and probably left over from when the string object was converted to an enumerable. Note that I started with the Rail 2.0.1 version, so it&#8217;s slightly different than if I started with the 2.1.0 version.</p>
<pre class="brush: ruby">&lt;br /&gt;
def truncate_string(text, length = 30, truncate_string = &#039;...&#039;)&lt;br /&gt;
if text.nil? then return end&lt;br /&gt;
l = length - truncate_string.length&lt;br /&gt;
text.length &gt; length ? text[0...l] + truncate_string : text&lt;br /&gt;
end&lt;br /&gt;
</pre>
<p>Yeah, yeah, I could have monkey-patched the TextHelper module, but why tempt fate if you don&#8217;t have to. A quick find/replace on &#8216;truncate&#8217; to &#8216;truncate_string&#8217; is all that was necessary. Works for me.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=teMG7pfzruQ:cJWPKwFFhC8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=teMG7pfzruQ:cJWPKwFFhC8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=teMG7pfzruQ:cJWPKwFFhC8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DaddyFixesEverything?a=teMG7pfzruQ:cJWPKwFFhC8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/DaddyFixesEverything?i=teMG7pfzruQ:cJWPKwFFhC8:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DaddyFixesEverything/~4/teMG7pfzruQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/</feedburner:origLink></item>
	</channel>
</rss>
