<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Pivotal Labs &#187; Grant Hutchins</title>
	<atom:link href="http://pivotallabs.com/author/grant/feed/" rel="self" type="application/rss+xml" />
	<link>http://pivotallabs.com</link>
	<description>Agility Developed</description>
	<lastBuildDate>Tue, 21 May 2013 16:50:52 +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>
		<item>
		<title>Keep gem configurations up-to-date with Rails generators</title>
		<link>http://pivotallabs.com/keep-gem-configurations-up-to-date-with-rails-generators/</link>
		<comments>http://pivotallabs.com/keep-gem-configurations-up-to-date-with-rails-generators/#comments</comments>
		<pubDate>Mon, 01 Apr 2013 18:39:54 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Labs]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/?p=18095</guid>
		<description><![CDATA[<p>Many Ruby gems are packaged with a Rails generator that generates a configuration file. Keeping these gem configurations up-to-date can be much easier if you take advantage of these generators during the upgrade process. Installing a gem that has configuration One example is simple_form, a gem that makes it easy to create and maintain forms. Another is devise, a popular gem for handling user session management. (Both of these gems are maintained by the excellent developers at Plataformatec.) The simple_form README says to run this command during installation: $ rails generate simple_form:install exist config create config/initializers/simple_form.rb create config/locales/simple_form.en.yml create lib/templates/erb/scaffold/_form.html.erb The file config/initializers/simple_form.rb looks like this: # Use this setup block to configure all options available in SimpleForm. SimpleForm.setup do &#124;config&#124; # Components used by the form builder to generate a complete input. You can remove # any of them, change the order, or even add your own components to&#8230;</p><p>The post <a href="http://pivotallabs.com/keep-gem-configurations-up-to-date-with-rails-generators/">Keep gem configurations up-to-date with Rails generators</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Many Ruby gems are packaged with a Rails generator that generates a configuration file. Keeping these gem configurations up-to-date can be much easier if you take advantage of these generators during the upgrade process.</p>
<h2>Installing a gem that has configuration</h2>
<p>One example is <a href="https://github.com/plataformatec/simple_form">simple_form</a>, a gem that makes it easy to create and maintain forms. Another is <a href="https://github.com/plataformatec/devise">devise</a>, a popular gem for handling user session management. (Both of these gems are maintained by the excellent developers at <a href="http://plataformatec.com.br">Plataformatec</a>.)</p>
<p>The simple_form README says to run this command during installation:</p>
<pre><code class="plain">$ rails generate simple_form:install
       exist  config
      create  config/initializers/simple_form.rb
      create  config/locales/simple_form.en.yml
      create  lib/templates/erb/scaffold/_form.html.erb
</code></pre>
<p>The file <code>config/initializers/simple_form.rb</code> looks like this:</p>
<pre><code class="ruby"># Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
  # Components used by the form builder to generate a complete input. You can remove
  # any of them, change the order, or even add your own components to the stack.
  # config.components = [ :placeholder, :label_input, :hint, :error ]

  # Default tag used on hints.
  # config.hint_tag = :span

  # CSS class to add to all hint tags.
  # config.hint_class = :hint

  # CSS class used on errors.
  # config.error_class = :error

and so on...
</code></pre>
<p>Also notice that you get a nice ERB template that extends the built-in Rails scaffold generator to automatically hook newly generated forms up to simple_form. And you get a default set of internationalization strings in <code>config/locales</code>.</p>
<h2>Upgrading a gem that has configuration</h2>
<p>The problem is that when you upgrade the simple_form gem from 1.5 to 2.0, the files that you have generated are stale. They might represent options that are no longer in the gem. Also, you might be missing out on new configurable features.</p>
<p>And the defaults might have changed, so any commented out lines showing the defaults will now be wrong. This recalls the programmer adage, &#8220;a comment is a lie waiting to happen.&#8221;</p>
<p>Well, there is an easy solution, of course. Just re-run the generator!</p>
<p>Assuming you&#8217;re using a source control system like Git, you can safely re-run the generator without breaking any of your code.</p>
<pre><code class="plain">$ rails generate simple_form:install
SimpleForm 2 supports Twitter bootstrap. In case you want to generate bootstrap configuration, please re-run this generator passing --bootstrap as option.
    conflict  config/initializers/simple_form.rb
Overwrite /Users/grant/code/blog_posts/rerun_generators/config/initializers/simple_form.rb? (enter "h" for help) [Ynaqdh]
</code></pre>
<p>Oops, looks like we have a conflict! Not to worry. I always just say yes to everything and move on. We will address the conflicts later.</p>
<p>Afterwards, all three of the generated files show up as having changes.</p>
<pre><code class="plain">$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add &lt;file&gt;..." to update what will be committed)
#   (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)
#
#   modified:   config/initializers/simple_form.rb
#   modified:   config/locales/simple_form.en.yml
#   modified:   lib/templates/erb/scaffold/_form.html.erb
#
no changes added to commit (use "git add" and/or "git commit -a")
</code></pre>
<p>I can use command-line tools like <code>git diff</code> or GUIs like <a href="http://gitx.frim.nl">GitX</a> to figure out what changed, and more important, make an educated decision about which changes I want to keep and which ones I want to change back to the old version.</p>
<p>For example, there is the change to the scaffold:</p>
<pre><code class="diff">$ git diff lib/templates/erb/scaffold/_form.html.erb
diff --git a/lib/templates/erb/scaffold/_form.html.erb b/lib/templates/erb/scaff
index 24a1768..201a069 100644
--- a/lib/templates/erb/scaffold/_form.html.erb
+++ b/lib/templates/erb/scaffold/_form.html.erb
@@ -1,13 +1,13 @@
 &lt;%%= simple_form_for(@&lt;%= singular_table_name %&gt;) do |f| %&gt;
   &lt;%%= f.error_notification %&gt;

-  &lt;div class="inputs"&gt;
+  &lt;div class="form-inputs"&gt;
   &lt;%- attributes.each do |attribute| -%&gt;
     &lt;%%= f.&lt;%= attribute.reference? ? :association : :input %&gt; :&lt;%= attribute.n
   &lt;%- end -%&gt;
   &lt;/div&gt;

-  &lt;div class="actions"&gt;
+  &lt;div class="form-actions"&gt;
     &lt;%%= f.button :submit %&gt;
   &lt;/div&gt;
 &lt;%% end %&gt;
</code></pre>
<p>Now I know that I should think about which class I want to use in my application for the inputs and actions <code>div</code> tags. I might stick to the old version, because perhaps I have a lot of CSS and JavaScript code built up that I don&#8217;t want to update right now. Or if my code is lean and easy to change, I&#8217;ll more likely adopt the new standard so that I can honor <a href="http://en.wikipedia.org/wiki/Convention_over_configuration">&#8220;convention over configuration&#8221;</a>.</p>
<p>Now let&#8217;s look at <code>config/initializers/simple_form.rb</code>.Check out this <a href="https://gist.github.com/nertzy/5286543">diff</a>; it&#8217;s got quite a lot of changes!</p>
<h2>Changes to the name of a setting</h2>
<p>Let&#8217;s focus on one small change:</p>
<pre><code class="diff">-  # When false, do not use translations for labels, hints or placeholders.
-  # config.translate = true
+  # When false, do not use translations for labels.
+  # config.translate_labels = true
</code></pre>
<p>This configuration option changed! I imagine that using the old version would give a deprecation warning when your application boots. Most people would simple change <code>translate</code> to <code>translate_labels</code> and move on, but in our version, we pick up the change to the comment as well, helping out future developers (and our future selves) to figure out what&#8217;s going on more quickly.</p>
<h2>Changes to settings that are not on by default</h2>
<p>Here&#8217;s another interesting example. Note that the comment didn&#8217;t change. It turns out that the simple_form authors are doing something subtle here.</p>
<pre><code class="diff">   # You can define the class to use on all labels. Default is nil.
-  # config.label_class = nil
+  config.label_class = 'control-label'
</code></pre>
<p>They really want new users that follow the installation instructions to set a <code>config.label_class</code>. This would make it easier for those users to style the form labels generated by simple_form while not affecting other labels that they might be manually generating. But the authors also don&#8217;t want to force that decision on other gem users who upgrade blindly and don&#8217;t even realize the configuration file exists.</p>
<p>So they have set a reasonable backwards-compatible default for the past, and have pushed out a good new opinionated default for new users. This is a balanced and thoughtful approach. And now that we are sitting in front of this diff output, we get to make a conscious decision about which direction to take.</p>
<h2>Bigger changes</h2>
<p>For my final example, I&#8217;ll ask you to spend some more time looking over the diff, which appears below.</p>
<p>Notice that several settings were bundled together and moved into a <code>config.wrappers</code> block. This change is pretty drastic, and I imagine there is some sort of backward-compatibility for users who use the old settings.</p>
<p>But by embracing the new block style, we learn that we can create additional groups of settings. The <code>:default</code> argument to <code>config.wrappers</code> implies that we can create additional named settings groups and mix and match where we use them in the application.</p>
<p>Indeed, we have now discovered the new Wrappers API as described in <a href="http://blog.plataformatec.com.br/tag/simple_form/">Plataformatec&#8217;s blog post</a> announcing Simple Form 2.0.</p>
<p>So by re-running the generator, we find ourselves making a lot of interesting choices about our application right at the time that we upgrade a gem. This is great because we still have full context about why we chose to upgrade. Woe to the developer that is working on a bug several months from now who doesn&#8217;t understand why a setting is set in some strange old way.</p>
<h2>Full diff of config/initializers/simple_form.rb</h2>
<script src="https://gist.github.com/5286543.js"></script><noscript><pre><code class="language-diff diff">diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb
index 553961b..e3f8d09 100644
--- a/config/initializers/simple_form.rb
+++ b/config/initializers/simple_form.rb
@@ -1,83 +1,126 @@
 # Use this setup block to configure all options available in SimpleForm.
 SimpleForm.setup do |config|
-  # Components used by the form builder to generate a complete input. You can remove
-  # any of them, change the order, or even add your own components to the stack.
-  # config.components = [ :placeholder, :label_input, :hint, :error ]
-
-  # Default tag used on hints.
-  # config.hint_tag = :span
-
-  # CSS class to add to all hint tags.
-  # config.hint_class = :hint
-
-  # CSS class used on errors.
-  # config.error_class = :error
-
-  # Default tag used on errors.
-  # config.error_tag = :span
-
-  # Method used to tidy up errors.
+  # Wrappers are used by the form builder to generate a
+  # complete input. You can remove any component from the
+  # wrapper, change the order or even add your own to the
+  # stack. The options given below are used to wrap the
+  # whole input.
+  config.wrappers :default, :class =&gt; :input,
+    :hint_class =&gt; :field_with_hint, :error_class =&gt; :field_with_errors do |b|
+    ## Extensions enabled by default
+    # Any of these extensions can be disabled for a
+    # given input by passing: `f.input EXTENSION_NAME =&gt; false`.
+    # You can make any of these extensions optional by
+    # renaming `b.use` to `b.optional`.
+
+    # Determines whether to use HTML5 (:email, :url, ...)
+    # and required attributes
+    b.use :html5
+
+    # Calculates placeholders automatically from I18n
+    # You can also pass a string as f.input :placeholder =&gt; &quot;Placeholder&quot;
+    b.use :placeholder
+
+    ## Optional extensions
+    # They are disabled unless you pass `f.input EXTENSION_NAME =&gt; :lookup`
+    # to the input. If so, they will retrieve the values from the model
+    # if any exists. If you want to enable the lookup for any of those
+    # extensions by default, you can change `b.optional` to `b.use`.
+
+    # Calculates maxlength from length validations for string inputs
+    b.optional :maxlength
+
+    # Calculates pattern from format validations for string inputs
+    b.optional :pattern
+
+    # Calculates min and max from length validations for numeric inputs
+    b.optional :min_max
+
+    # Calculates readonly automatically from readonly attributes
+    b.optional :readonly
+
+    ## Inputs
+    b.use :label_input
+    b.use :hint,  :wrap_with =&gt; { :tag =&gt; :span, :class =&gt; :hint }
+    b.use :error, :wrap_with =&gt; { :tag =&gt; :span, :class =&gt; :error }
+  end
+
+  # The default wrapper to be used by the FormBuilder.
+  config.default_wrapper = :default
+
+  # Define the way to render check boxes / radio buttons with labels.
+  # Defaults to :nested for bootstrap config.
+  #   :inline =&gt; input + label
+  #   :nested =&gt; label &gt; input
+  config.boolean_style = :nested
+
+  # Default class for buttons
+  config.button_class = 'btn'
+
+  # Method used to tidy up errors. Specify any Rails Array method.
+  # :first lists the first message for each field.
+  # Use :to_sentence to list all errors for each field.
   # config.error_method = :first
 
   # Default tag used for error notification helper.
-  # config.error_notification_tag = :p
+  config.error_notification_tag = :div
 
   # CSS class to add for error notification helper.
-  # config.error_notification_class = :error_notification
+  config.error_notification_class = 'alert alert-error'
 
   # ID to add for error notification helper.
   # config.error_notification_id = nil
 
-  # You can wrap all inputs in a pre-defined tag.
-  # config.wrapper_tag = :div
-
-  # CSS class to add to all wrapper tags.
-  # config.wrapper_class = :input
+  # Series of attempts to detect a default label method for collection.
+  # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
 
-  # CSS class to add to the wrapper if the field has errors.
-  # config.wrapper_error_class = :field_with_errors
+  # Series of attempts to detect a default value method for collection.
+  # config.collection_value_methods = [ :id, :to_s ]
 
   # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
   # config.collection_wrapper_tag = nil
 
-  # You can wrap each item in a collection of radio/check boxes with a tag, defaulting to span.
-  # config.item_wrapper_tag = :span
+  # You can define the class to use on all collection wrappers. Defaulting to none.
+  # config.collection_wrapper_class = nil
 
-  # Series of attempts to detect a default label method for collection.
-  # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
+  # You can wrap each item in a collection of radio/check boxes with a tag,
+  # defaulting to :span. Please note that when using :boolean_style = :nested,
+  # SimpleForm will force this option to be a label.
+  # config.item_wrapper_tag = :span
 
-  # Series of attempts to detect a default value method for collection.
-  # config.collection_value_methods = [ :id, :to_s ]
+  # You can define a class to use in all item wrappers. Defaulting to none.
+  # config.item_wrapper_class = nil
 
   # How the label text should be generated altogether with the required text.
   # config.label_text = lambda { |label, required| &quot;#{required} #{label}&quot; }
 
   # You can define the class to use on all labels. Default is nil.
-  # config.label_class = nil
+  config.label_class = 'control-label'
 
   # You can define the class to use on all forms. Default is simple_form.
   # config.form_class = :simple_form
 
+  # You can define which elements should obtain additional classes
+  # config.generate_additional_classes_for = [:wrapper, :label, :input]
+
   # Whether attributes are required by default (or not). Default is true.
   # config.required_by_default = true
 
   # Tell browsers whether to use default HTML5 validations (novalidate option).
   # Default is enabled.
-  # config.browser_validations = true
+  config.browser_validations = false
 
-  # Determines whether HTML5 types (:email, :url, :search, :tel) and attributes
-  # (e.g. required) are used or not. True by default.
-  # Having this on in non-HTML5 compliant sites can cause odd behavior in
-  # HTML5-aware browsers such as Chrome.
-  # config.html5 = true
+  # Collection of methods to detect if a file type was given.
+  # config.file_methods = [ :mounted_as, :file?, :public_filename ]
 
   # Custom mappings for input types. This should be a hash containing a regexp
   # to match as key, and the input type that will be used when the field name
   # matches the regexp as value.
   # config.input_mappings = { /count/ =&gt; :integer }
 
-  # Collection of methods to detect if a file type was given.
-  # config.file_methods = [ :mounted_as, :file?, :public_filename ]
+  # Custom wrappers for input types. This should be a hash containing an input
+  # type as key and the wrapper that will be used for all inputs with specified type.
+  # config.wrapper_mappings = { :string =&gt; :prepend }
 
   # Default priority for time_zone inputs.
   # config.time_zone_priority = nil
@@ -88,6 +131,12 @@ SimpleForm.setup do |config|
   # Default size for text inputs.
   # config.default_input_size = 50
 
-  # When false, do not use translations for labels, hints or placeholders.
-  # config.translate = true
+  # When false, do not use translations for labels.
+  # config.translate_labels = true
+
+  # Automatically discover new inputs in Rails' autoload path.
+  # config.inputs_discovery = true
+
+  # Cache SimpleForm inputs discovery
+  # config.cache_discovery = !Rails.env.development?
 end
</code></pre></noscript>
<p>The post <a href="http://pivotallabs.com/keep-gem-configurations-up-to-date-with-rails-generators/">Keep gem configurations up-to-date with Rails generators</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/keep-gem-configurations-up-to-date-with-rails-generators/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Active Record Scopes</title>
		<link>http://pivotallabs.com/testing-active-record-scopes/</link>
		<comments>http://pivotallabs.com/testing-active-record-scopes/#comments</comments>
		<pubDate>Mon, 18 Mar 2013 23:34:02 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Labs]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/?p=16045</guid>
		<description><![CDATA[<p>Active Record scopes are an interesting thing to test. In projects I&#8217;ve worked on, I have seen many different patterns of testing, some much better than others. A little over two years ago I wrote the gem pg_search, which provides a sort of Domain-Specific Language (DSL) for creating Active Record scopes that take advantage of PostgreSQL&#8217;s built-in full-text search. For example, the following code will set up a scope that accepts query as a string and returns records whose name matches that query. The records will be ordered by relevance. class Book include PgSearch pg_search_scope :search_by_name, :against =&#62; :name end Book.search_by_name("catch") # =&#62; [#&#60;Book id: 3, name: "Catch 22"&#62;, # #&#60;Book id: 7, name: "The Catcher in the Rye"&#62;] In pg_search&#8217;s test suite, I found myself needing to test the results of scopes over and over again. In doing so, I believe I have developed a reasonable approach. But first,&#8230;</p><p>The post <a href="http://pivotallabs.com/testing-active-record-scopes/">Testing Active Record Scopes</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Active Record scopes are an interesting thing to test. In projects I&#8217;ve worked on, I have seen many different patterns of testing, some much better than others.</p>
<p>A little over two years ago I wrote the gem <a href="http://github.com/Casecommons/pg_search">pg_search</a>, which provides a sort of Domain-Specific Language (DSL) for creating Active Record scopes that take advantage of PostgreSQL&#8217;s built-in full-text search.</p>
<p>For example, the following code will set up a scope that accepts <code>query</code> as a string and returns records whose <code>name</code> matches that query. The records will be ordered by relevance.</p>
<pre><code>class Book
  include PgSearch
  pg_search_scope :search_by_name, :against =&gt; :name
end

Book.search_by_name("catch") 
# =&gt; [#&lt;Book id: 3, name: "Catch 22"&gt;, 
#     #&lt;Book id: 7, name: "The Catcher in the Rye"&gt;]
</code></pre>
<p>In <a href="https://github.com/Casecommons/pg_search/tree/master/spec">pg_search&#8217;s test suite</a>, I found myself needing to test the results of scopes over and over again. In doing so, I believe I have developed a reasonable approach. But first, let&#8217;s look at a common pitfall.</p>
<h2>Antipattern: Stub the object under test</h2>
<pre><code>describe ".chronological" do
  it "should call order('year ASC')" do
    expected_result = double("expected result")
    Book.stub(:order).with("year ASC").and_return(expected_result)

    Book.chronological.should == expected_result
  end
end
</code></pre>
<p>In this example, we use an <a href="https://www.relishapp.com/rspec/rspec-mocks/docs">RSpec test double</a> to simulate what would happen if we were to call <code>Book.order("year ASC")</code>. We then call our <code>Book.chronological</code> method to see if it returns the same value.</p>
<p>There are a few problems with this approach. First off, we are testing a class method on the <code>Book</code> class, and also stubbing the class method <code>Book.order</code>. By modifying part of how <code>Book</code> works, we cannot be sure that the object will work when the mocks are absent.</p>
<p>Secondly, our test code is tightly coupled to our implementation. What if we decide that the <code>.chronological</code> scope should always rank records with <code>NULL</code> year first? In PostgreSQL, this would work:</p>
<pre><code>def self.chronological
  order("year ASC NULLS FIRST")
end
</code></pre>
<p>This is effectively a new feature, but you have to go back and change the test for an old feature in order to make everything pass.</p>
<h2>Better solution: Set up a failing scenario</h2>
<pre><code>describe ".chronological" do
  it "orders records by year" do
    later = Book.create!(year: "2005")
    earlier = Book.create!(year: "2002")
    middle = Book.create!(year: "2004")

    results = Book.chronological

    results.index(earlier).should be &lt; results.index(middle) 
    results.index(middle).should be &lt; results.index(later) 
  end
end
</code></pre>
<p>In this example, we set up a much simpler situation. We create three records, then expect the <code>chronological</code> method to return them in order. Note that we use <a href="http://ruby-doc.org/core-2.0/Array.html#method-i-index"><code>Enumerable#index</code></a> to compare the positions of the records in the output Array.</p>
<p>Now we can experiment with different solutions.</p>
<pre><code>order("year ASC")
order("year")
order("year DESC").reverse_order
joins(:author).order("year ASC")
</code></pre>
<p>All of these code examples should pass the test. And our test no longer cares about that <code>joins(:author)</code> part. The original stubbed version would have failed because <code>.order</code> is not called directly on <code>Book</code> anymore.</p>
<h2>Avoiding brittleness</h2>
<p>We could also have written something like this:</p>
<pre><code>results.should == [earlier, middle, later]
</code></pre>
<p>But now that the database is involved, we would need to be more careful to allow for other records that might be there, such as test fixtures. We could solve that by deleting all <code>Book</code> records at the beginning of the spec.</p>
<pre><code>describe ".chronological" do
  it "orders records by year" do
    Book.delete_all

    later = Book.create!(year: "2005")
    earlier = Book.create!(year: "2002")
    middle = Book.create!(year: "2004")

    results = Book.chronological
    results.should == [earlier, middle, later]
  end
end
</code></pre>
<p>My personal preference is to avoid the <code>Book.delete_all</code> solution. In my opinion it&#8217;s better to have a test that works regardless of the internal state of other objects and systems.</p>
<p>Also, if later down the road a test fixture happens to be present and somehow breaks my test, I have a chance of noticing and doing something about it at that point. If I always delete all of the records, then this free informal fuzz testing goes away.</p>
<p>This is similar to the oft-repeated <a href="https://en.wikipedia.org/wiki/Robustness_Principle">Robustness Principle</a> (aka Postel&#8217;s Law)</p>
<blockquote><p>Be conservative in what you do, be liberal in what you accept from others.</p></blockquote>
<p>In other words, I want my test to tread lightly, but also not to fail when a bunch of garbage is thrown at it. It should still pass when I do this:</p>
<pre><code>describe ".chronological" do
  it "orders records by year" do
    later = Book.create!(year: "2005")
    earlier = Book.create!(year: "2002")
    middle = Book.create!(year: "2004")

    1_000_000.times do
      random_year = 2000 + rand(10)
      Book.create!(year: random_year.to_s)
    end

    results = Book.chronological

    results.index(earlier).should be &lt; results.index(middle) 
    results.index(middle).should be &lt; results.index(later) 
  end
end
</code></pre>
<h2>But that&#8217;s not a unit test!</h2>
<p>This example fully integrates the test against the database. Some would argue that this is no longer a unit test, and is thus not as good.</p>
<p>I agree that this is not a pure unit test. It has a dependency on the database. For example, if the database is not set up properly, this test will fail, while the stubbed example would still pass.</p>
<p>Scopes are an interesting concept that I believe evade easy unit testing; they are methods that return instances of <code>ActiveRecord::Relation</code>.</p>
<p>The strange thing about these <code>Relation</code> objects is that they behave somewhere in-between a class and an instance. For example, they are clearly not a class.</p>
<pre><code>Book.chronological.is_a?(Class) # =&gt; false
</code></pre>
<p>But they behave much like the <code>Book</code> class, delegating many of the common things you might do.</p>
<pre><code>Book.chronological.new # =&gt; #&lt;Book id: nil, name: nil&gt;
Book.where(year: 2007).destroy_all # (destroys all records with year 2007)
</code></pre>
<p>And any class method you define on <code>Book</code> is callable directly on the <code>Relation</code> instance. It&#8217;s almost as if it were a subclass of <code>Book</code>. Even silly methods that have nothing to do with the database work almost as normal.</p>
<pre><code>class Book &lt; ActiveRecord::Base
  def self.name_in_french
    "Livre"
  end
end

Book.where(:year =&gt; "2000").name_in_french # =&gt; "Livre"
</code></pre>
<p>And yet <code>Relation</code> objects also act like an <code>Enumerable</code> and have all the methods like <code>#each</code>, <code>#map</code>, <code>#select</code>, and so on. In fact, there is the crazy implementation of <a href="http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-select"><code>ActiveRecord::QueryMethods#select</code></a> which goes out of its way to guess whether you wanted the Active Record class method or the <code>Enumerable</code> method.</p>
<h2>In closing</h2>
<p>So scopes are these strange methods that have a fluent interface that chains, create a set of virutal subclasses of your model, and build an abstract syntax tree (AST) of your SQL queries using the <a href="https://github.com/rails/arel">Arel gem</a>.</p>
<p>This last point is the nail in the coffin for me. An AST is not that meaningful until it is compiled into runnable code and executed. And with scopes and <code>Relation</code> objects, that means generating SQL code. And SQL code itself is not that interesting until it is executed against a database. For most of its useful operations, a <code>Relation</code> is actually a code generator for another language!</p>
<p>So my vote is to embrace the database, get something working quickly, and move on. That way, you know that your true goals are going to work against your actual application.</p>
<p>I&#8217;d love to hear feedback and debate. I don&#8217;t believe this is a closed issue. Feel free to join the discussion in the comments!</p>
<p>The post <a href="http://pivotallabs.com/testing-active-record-scopes/">Testing Active Record Scopes</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/testing-active-record-scopes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Arel to build complex SQL expressions</title>
		<link>http://pivotallabs.com/using-arel-to-build-complex-sql-expressions/</link>
		<comments>http://pivotallabs.com/using-arel-to-build-complex-sql-expressions/#comments</comments>
		<pubDate>Sun, 10 Feb 2013 21:55:33 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Labs]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/?p=15167</guid>
		<description><![CDATA[<p>I write and maintain a gem called pg_search that makes it easy to build Active Record scopes that take advantage of PostgreSQL&#8217;s built-in full-text search functionality. Part of generating these scopes involves taking user input (which come in as Ruby strings) and comparing it against columns in database tables to see which records match. Escaping strings Here&#8217;s a (simplified) example query that uses the trigram operator, %, to do a fuzzy text match. SELECT * FROM "blog_posts" WHERE content % 'foo'; A naïve way to write this in an Active Record would be: BlogPost.where("content % '#{query}'") This is, of course, a bad way to write this query, because it would be trivial for a user to supply a query string that does something destructive. query = "'; DELETE FROM blog_posts; SELECT '1" BlogPost.where("content % '#{query}'") This query breaks out of the quotes and generates multiple SQL queries. The second query&#8230;</p><p>The post <a href="http://pivotallabs.com/using-arel-to-build-complex-sql-expressions/">Using Arel to build complex SQL expressions</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I write and maintain a gem called <a href="http://github.com/Casecommons/pg_search">pg_search</a> that makes it easy to build Active Record scopes that take advantage of PostgreSQL&#8217;s built-in full-text search functionality.</p>
<p>Part of generating these scopes involves taking user input (which come in as Ruby strings) and comparing it against columns in database tables to see which records match.</p>
<h2>Escaping strings</h2>
<p>Here&#8217;s a (simplified) example query that uses the <a href="http://www.postgresql.org/docs/current/static/pgtrgm.html">trigram</a> operator, <code>%</code>, to do a fuzzy text match.</p>
<pre><code>SELECT * FROM "blog_posts" WHERE content % 'foo';
</code></pre>
<p>A naïve way to write this in an Active Record would be:</p>
<pre><code>BlogPost.where("content % '#{query}'")
</code></pre>
<p>This is, of course, a bad way to write this query, because it would be trivial for a user to supply a query string that does something destructive.</p>
<pre><code>query = "'; DELETE FROM blog_posts; SELECT '1"
BlogPost.where("content % '#{query}'")
</code></pre>
<p>This query breaks out of the quotes and generates multiple SQL queries. The second query would delete every blog post in the system.</p>
<pre><code>SELECT * FROM "blog_posts" WHERE content % ''; DELETE FROM blog_posts; SELECT '1';
</code></pre>
<p>The most common way Rails developers work around this in Active Record is to use the built-in support for escaping strings by providing two arguments to <code>#where</code>.</p>
<pre><code>query = "'; DELETE FROM blog_posts; SELECT '1"
BlogPost.where("content % ?", query)
</code></pre>
<p>That way, the BlogPost model would generate SQL with the evil query escaped. The following example is from PostgreSQL, where <code>''</code> inside a string is an escaped single quote.</p>
<pre><code>SELECT "blog_posts".* FROM "blog_posts"  WHERE (content % '''; DELETE FROM blog_posts; SELECT ''1');
</code></pre>
<h2>Avoiding strings of SQL</h2>
<p>Now, when you want to write a scope that matches by equality, Active Record offers a nicer syntax. For example, you could find all blog posts whose title is an exact match to a query using the Hash-based syntax. The two following lines are mostly equivalent.</p>
<pre><code>BlogPost.where("title = ?", query)
BlogPost.where(title: query)
</code></pre>
<p>I prefer the Hash syntax because there are no string literals involved. Also, as an added bonus, Active Record uses a fully-qualified column name such as <code>"blog_posts"."title"</code> instead of just <code>title</code>, which makes it easier to use in multi-table expressions that use joins.</p>
<p>Also, it&#8217;s still possible to generated invalid SQL when using the two-parameter version.</p>
<pre><code>BlogPost.where("title = '?'", query) # extra ' surrounds query
</code></pre>
<p>Luckily this example always generates invalid SQL, so it&#8217;s easy to catch. But it&#8217;s still frustrating that the most common syntax doesn&#8217;t prevent bugs from leaking all the way into the database.</p>
<h2>Symbolic expressions</h2>
<p>That&#8217;s where <a href="https://github.com/rails/arel">Arel</a> steps in. Arel is a Relational Algebra gem that allows you to generate SQL queries directly from an abstract syntax tree (AST) of nodes. It&#8217;s what Active Record uses internally to build up expressions symbolically from the Hash syntax.</p>
<p>The <code>#where</code> method in Active Record can accept an Arel node. For the title equality example, it would look like this:</p>
<pre><code>expression = BlogPost.arel_table[:title].eq(query)
BlogPost.where(expression)
</code></pre>
<p>Unfortunately, the <a href="http://rubydoc.info/gems/arel">documentation for Arel</a> is pretty sparse. For instance, the <code>#eq</code> method I used above has <a href="http://rubydoc.info/gems/arel/Arel/Predications#eq-instance_method">no documentation at all</a>.</p>
<p>However, digging into the source of the method gives some clues as to how it works.</p>
<pre><code># File 'lib/arel/predications.rb', line 15
def eq other
  Nodes::Equality.new self, other
end
</code></pre>
<p>It turns out that <code>#eq</code>, when called on one Arel node and passed another, creates an <code>Arel::Nodes::Equality</code> instance. Looking at the <a href="http://rubydoc.info/gems/arel/Arel/Nodes/Equality">docs for this <code>Equality</code> class</a> shows that it is a subclass of <code>Arel::Nodes::Binary</code>.</p>
<p>It turns out that an <code>Arel::Nodes::Binary</code> instance is a symbolic representation of a operation between two Arel nodes. In this case, you should think of &#8220;binary&#8221; as meaning &#8220;having two arguments&#8221;, as opposed to the Boolean concept of true and false.</p>
<p>In our example, the nodes are a database column, <code>BlogPost.arel_table[:title]</code>, and a Ruby string, <code>query</code>. And <code>Equality</code> is the particular <code>Binary</code> relationship that deals with the equality operator, <code>=</code>.</p>
<p>It turns out there are other subclasses, such as <code>Arel::Nodes::GreaterThan</code>, for other binary operations.</p>
<h2>Putting it all together</h2>
<p>Anyway, coming back to our original example using trigrams, we want to find a way to create a <code>Binary</code> expression that Active Record will accept and turn into a SQL query that uses the <code>%</code> operator.</p>
<p>After hunting around with my pair JT Archie, we discovered a class named <a href="http://rubydoc.info/gems/arel/Arel/Nodes/InfixOperation"><code>Arel::Nodes::InfixOperation</code></a>. An &#8220;infix&#8221; operator is a binary operator such as <code>=</code> or <code>+</code> that is written between its arguments. For example, in SQL notation, you would write <code>1 + 2</code>, not <code>+ 1 2</code> or <code>1 2 +</code>.</p>
<p>It turns out that <code>%</code> is an infix operator in PostgreSQL. So we can create an <code>InfixOperation</code> instance directly. Looking at its constructor, we see that it takes three arguments named &#8220;operator&#8221;, &#8220;left&#8221;, and &#8220;right&#8221;.</p>
<pre><code># File 'lib/arel/nodes/infix_operation.rb', line 13
def initialize operator, left, right
  super(left, right)
  @operator = operator
end
</code></pre>
<p>So we can write our content-matching trigram scope this way:</p>
<pre><code>content_column = BlogPost.arel_table[:content]
query = "Pivotal Labs"
expression = Arel::Nodes::InfixOperation.new("%", content_column, query)
BlogPost.where(expression)
</code></pre>
<p>This scope generates exactly the SQL we want:</p>
<pre><code>SELECT "blog_posts".* FROM "blog_posts" WHERE ("blog_posts"."content" % 'Pivotal Labs')
</code></pre>
<p>Let&#8217;s clean this up and put it into a class method on <code>BlogPost</code>.</p>
<pre><code>class BlogPost &lt; ActiveRecord::Base
  def self.search_content(query)
    expression = Arel::Nodes::InfixOperation.new(
      "%",
      arel_table[:content],
      query
    )
    where(expression)
  end
end
</code></pre>
<h2>Looking forward</h2>
<p>As of now, my <code>pg_search</code> gem builds most of its SQL through creative use of Active Record SQL-escaping methods and Ruby string interpolations. As far as I know, I have done everything correctly. Thus, I feel mostly safe from SQL injection attacks and other bugs. But it&#8217;s hard to know whether or not I&#8217;ve missed a spot.</p>
<p>But one day soon, I hope to convert it all into Arel objects. I&#8217;ve already started, and I hope it won&#8217;t be long before a fully string-interpolation-free version is released. Then I can rest easier, knowing that a typo somewhere deep in my code won&#8217;t end up going directly into the database unescaped.</p>
<p>The post <a href="http://pivotallabs.com/using-arel-to-build-complex-sql-expressions/">Using Arel to build complex SQL expressions</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/using-arel-to-build-complex-sql-expressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refactoring the Deeply-Nested Hash Antipattern</title>
		<link>http://pivotallabs.com/refactoring-the-deeply-nested-hash-antipattern/</link>
		<comments>http://pivotallabs.com/refactoring-the-deeply-nested-hash-antipattern/#comments</comments>
		<pubDate>Sat, 26 Jan 2013 23:39:35 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[object-design]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/?p=11860</guid>
		<description><![CDATA[<p>On a few different Ruby projects, I have seen an antipattern emerge involving nested hashes. For example, consider this simple question-and-answer command-line script: QUIZ = { question_1: { prompt: "What is your name?" }, question_2: { prompt: "What is your favorite color?" } } answers = {} QUIZ.each do &#124;name, question_hash&#124; print question_hash[:prompt], " " answers[name] = gets.chomp end p answers The QUIZ constant isn&#8217;t too hard to understand. The keys (question_1 and question_2) each point to a value that is itself another hash. Let&#8217;s call that a question_hash. For now a question_hash has only one key-value pair, the prompt. The answers hash simply accumulates answers. The key is the key from the QUIZ constant, and the value is the answer the user typed in. At the end of the script, the program calls Kernel#p to print out the inspect string for the answers hash. Sure enough, the program works.&#8230;</p><p>The post <a href="http://pivotallabs.com/refactoring-the-deeply-nested-hash-antipattern/">Refactoring the Deeply-Nested Hash Antipattern</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>On a few different Ruby projects, I have seen an antipattern emerge involving nested hashes.</p>
<p>For example, consider this simple question-and-answer command-line script:</p>
<pre><code>QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?"
  }
}

answers = {}

QUIZ.each do |name, question_hash|
  print question_hash[:prompt], " "
  answers[name] = gets.chomp
end

p answers
</code></pre>
<p>The <code>QUIZ</code> constant isn&#8217;t too hard to understand. The keys (<code>question_1</code> and <code>question_2</code>) each point to a value that is itself another hash. Let&#8217;s call that a <code>question_hash</code>. For now a <code>question_hash</code> has only one key-value pair, the prompt.</p>
<p>The answers hash simply accumulates answers. The key is the key from the <code>QUIZ</code> constant, and the value is the answer the user typed in.</p>
<p>At the end of the script, the program calls <a href="http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-p"><code>Kernel#p</code></a> to print out the inspect string for the answers hash.</p>
<p>Sure enough, the program works.</p>
<pre>$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
{:question_1=&gt;"Grant", :question_2=&gt;"orange"}</pre>
<p>Take a look at the <code>QUIZ.each</code> block up there. Notice that the inside of the block assumes that the <code>question_hash</code> will have a <code>:prompt</code> key.</p>
<p>That&#8217;s not too complicated. But let&#8217;s add some more features to our script. Now we will add a multiple-choice question to the <code>QUIZ</code> hash:</p>
<pre><code>QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?"
  },

  question_3: {
    prompt: "What is your favorite integer between 1 and 5?",
    choices: %w[1 2 3 4 5]
  }
}
</code></pre>
<p>Now we want to treat a <code>question_hash</code> differently if it has a <code>choices</code> key. One way to do this is to write two different methods that take the <code>question_hash</code> as an argument and ask the question. The methods will return the answer that the user inputs.</p>
<pre><code>def simple_answer(question_hash)
  print question_hash[:prompt], " "
  gets.chomp
end

def multiple_choice_answer(question_hash)
  choices = question_hash[:choices]
  answer = nil

  until choices.include?(answer)
    print question_hash[:prompt], " "
    answer = gets.chomp
    puts "You must pick an answer from #{choices}" unless choices.include?(answer)
  end

  answer
end
</code></pre>
<p>Now we simply update our block to call the appropriate method for each <code>question_hash</code>.</p>
<pre><code>QUIZ.each do |name, question_hash|
  answer = if question_hash[:choices]
    multiple_choice_answer(question_hash)
  else
    simple_answer(question_hash)
  end

  answers[name] = answer
end

p answers
</code></pre>
<p>This all still works fine.</p>
<pre>$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
What is your favorite integer between 1 and 5? 7
You must pick an answer from ["1", "2", "3", "4", "5"]
What is your favorite integer between 1 and 5? 3
{:question_1=&gt;"Grant", :question_2=&gt;"orange", :question_3=&gt;"3"}</pre>
<p>But the code is very quickly getting more complex. Before long, we will have questions with sub-questions, conditional follow-up questions, and even more complicated features. Here&#8217;s an example that supports a Proc for formatting the user&#8217;s answer.</p>
<pre><code>QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?",
    display_proc: -&gt;(color) { "The color is #{color}." }
  },

  question_3: {
    prompt: "What is your favorite integer between 1 and 5?",
    choices: %w[1 2 3 4 5]
  }
}

answers = {}

def simple_answer(question_hash)
  print question_hash[:prompt], " "
  gets.chomp
end

def multiple_choice_answer(question_hash)
  choices = question_hash[:choices]
  answer = nil

  until choices.include?(answer)
    print question_hash[:prompt], " "
    answer = gets.chomp
    puts "You must pick an answer from #{choices}" unless choices.include?(answer)
  end

  answer
end

QUIZ.each do |name, question_hash|
  answer = if question_hash[:choices]
    multiple_choice_answer(question_hash)
  else
    simple_answer(question_hash)
  end

  answers[name] = answer
end

display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name][:display_proc]
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]

p display_answers
</code></pre>
<p>The output now looks like this</p>
<pre>$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
What is your favorite integer between 1 and 5? 6
You must pick an answer from ["1", "2", "3", "4", "5"]
What is your favorite integer between 1 and 5? 3
{:question_1=&gt;"Grant", :question_2=&gt;"The color is orange.", :question_3=&gt;"3"}</pre>
<p>And the code will keep growing and growing, making it harder for the next developer to understand exactly how the big Hash will translate into the user&#8217;s experience.</p>
<p>Take a look at those answer methods. Whenever I see a bunch of methods that accept the same argument, I suspect that there is an object missing in my system. Let&#8217;s create a new Question object. Imagine that we have it in that <code>QUIZ.each</code> block, and that we can simply ask the Question for its answer directly.</p>
<pre><code>class Question
  def initialize(question_hash)
    @question_hash = question_hash
  end

  def answer
    if @question_hash[:choices]
      multiple_choice_answer(@question_hash)
    else
      simple_answer(@question_hash)
    end
  end

  private

  def simple_answer(question_hash)
    print question_hash[:prompt], " "
    gets.chomp
  end

  def multiple_choice_answer(question_hash)
    choices = question_hash[:choices]
    answer = nil

    until choices.include?(answer)
      print question_hash[:prompt], " "
      answer = gets.chomp
      puts "You must pick an answer from #{choices}" unless choices.include?(answer)
    end

    answer
  end
end

QUIZ.each do |name, question_hash|
  question = Question.new(question_hash)
  answers[name] = question.answer
end
</code></pre>
<p>Notice that <code>simple_answer</code> and <code>multiple_choice_answer</code> are now completely private. That&#8217;s good, because it hides away the internal details of how a Question works. We are now free to start doing some refactoring, without worrying about the rest of the code in the system breaking.</p>
<p>Our first refactor will be to remove the arguments from the private methods, since it&#8217;s now possible to get at the <code>@question_hash</code> directly from within the Question object.</p>
<pre><code>class Question
  def initialize(question_hash)
    @question_hash = question_hash
  end

  def answer
    if @question_hash[:choices]
      multiple_choice_answer
    else
      simple_answer
    end
  end

  private

  def simple_answer
    print @question_hash[:prompt], " "
    gets.chomp
  end

  def multiple_choice_answer
    choices = @question_hash[:choices]
    answer = nil

    until choices.include?(answer)
      print @question_hash[:prompt], " "
      answer = gets.chomp
      puts "You must pick an answer from #{choices}" unless choices.include?(answer)
    end

    answer
  end
end
</code></pre>
<p>Next, notice that the only reason we are passing the <code>question_hash</code> into the Question is to get out the <code>prompt</code> and the <code>choices</code>. When a constructor takes a hash with expected keys, you can swap the hash out for multiple arguments instead.</p>
<pre><code>class Question
  def initialize(prompt, choices)
    @prompt = prompt
    @choices = choices
  end

  def answer
    if @choices
      multiple_choice_answer
    else
      simple_answer
    end
  end

  private

  def simple_answer
    print @prompt, " "
    gets.chomp
  end

  def multiple_choice_answer
    answer = nil

    until @choices.include?(answer)
      print @prompt, " "
      answer = gets.chomp
      puts "You must pick an answer from #{@choices}" unless @choices.include?(answer)
    end

    answer
  end
end
</code></pre>
<p>Now the object is easier to understand. But there&#8217;s still a problem. To use this new object, the each block needs to be updated:</p>
<pre><code>QUIZ.each do |name, question_hash|
  prompt = question_hash[:prompt]
  choices = question_hash[:choices]
  question = Question.new(prompt, choices)
  answers[name] = question.answer
end
</code></pre>
<p>This is uglier than what we had before. But there&#8217;s a quick fix that makes our code much nicer. Let&#8217;s change the <code>QUIZ</code> hash so that its values are already Question objects:</p>
<pre><code>QUIZ = {
  question_1: Question.new("What is your name?", nil),
  question_2: Question.new("What is your favorite color?", nil),
  question_3: Question.new("What is your favorite integer between 1 and 5?",
                           %w[1 2 3 4 5])
}
</code></pre>
<p>This makes our each block much nicer!</p>
<pre><code>QUIZ.each do |name, question|
  answers[name] = question.answer
end
</code></pre>
<p>But there&#8217;s still one problem. Our <code>QUIZ</code> no longer holds the <code>display_proc</code>, so this code from before fails:</p>
<pre><code>display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name][:display_proc]
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]
</code></pre>
<p>So let&#8217;s put that proc into the Question object and make it available via an <code>attr_reader</code>. While we&#8217;re at it, we can give default values of nil for both choices and nil.</p>
<pre><code>class Question
  attr_reader :display_proc

  def initialize(prompt, choices = nil, display_proc = nil)
    @prompt = prompt
    @choices = choices
    @display_proc = display_proc
  end

  # ...
</code></pre>
<p>Now our <code>QUIZ</code> looks like this:</p>
<pre><code>QUIZ = {
  question_1: Question.new("What is your name?"),
  question_2: Question.new("What is your favorite color?",
                           nil,
                           -&gt;(color) { "The color is #{color}." }),
  question_3: Question.new("What is your favorite integer between 1 and 5?",
                           %w[1 2 3 4 5])
}
</code></pre>
<p>And our <code>display_answers</code> code looks like this:</p>
<pre><code>display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name].display_proc
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]
</code></pre>
<p>Now let&#8217;s move the logic for deciding how an answer should be formatted into the Question object. (We can remove the <code>attr_reader</code> for <code>display_proc</code> at this time as well, to keep things nicely hidden away.)</p>
<pre><code>class Question
  # ... 

  def display_answer(answer)
    if @display_proc
      @display_proc[answer]
    else
      answer
    end
  end

  # ...
</code></pre>
<p>Which gives us:</p>
<pre><code>display_answers = Hash[
  answers.map do |name, answer|
    question = QUIZ[name]
    [name, question.display_answer(answer)]
  end
]
</code></pre>
<p>At this point, it seems like the question name could also easily be put into the Question object as a new first argument. Let&#8217;s replace the <code>QUIZ</code> constant with a <code>QUESTIONS</code> constant that holds an array of Question objects.</p>
<pre><code>QUESTIONS = [
  Question.new(:question_1,
               "What is your name?"),
  Question.new(:question_2,
               "What is your favorite color?",
               nil,
               -&gt;(color) { "The color is #{color}." }),
  Question.new(:question_3,
               "What is your favorite integer between 1 and 5?",
               %w[1 2 3 4 5])
]

answers = {}

QUESTIONS.each do |question|
  answers[question.name] = question.answer
end

display_answers = Hash[
  QUESTIONS.map do |question|
    answer = answers[question.name]
    [question.name, question.display_answer(answer)]
  end
]

p display_answers
</code></pre>
<p>Now the code is much cleaner. There are definitely more places the code could be refactored. <code>choices</code> and <code>display_proc</code> could be moved into an options hash argument since they are truly optional. Maybe there could be a SimpleQuestion superclass and a subclass called MultipleChoiceQuestion with all the choices-related code.</p>
<p>The most important thing to realize is that now the conversation that future developers might have about this code has shifted.</p>
<p>Before, the conversation would probably have centered around how complicated the code looked and confusion about how the structure of the <code>QUIZ</code> hash affects the control flow of the rest of the program. What is the easiest way to make a small change to add a new feature without breaking the whole big complex structure?</p>
<p>Now, the conversation can be about whether the current object model makes sense or should be tweaked in some small way. And with the full power of a Ruby class instead of the limited behavior of a Hash, the developers will have more options.</p>
<p>This code example is available on <a href="https://github.com/nertzy/refactoring-nested-hashes">GitHub</a> with a full Git history of the working code at each stage. Here&#8217;s the final code:</p>
<pre><code>class Question
  attr_reader :name

  def initialize(name, prompt, choices = nil, display_proc = nil)
    @name = name
    @prompt = prompt
    @choices = choices
    @display_proc = display_proc
  end

  def answer
    if @choices
      multiple_choice_answer
    else
      simple_answer
    end
  end

  def display_answer(answer)
    if @display_proc
      @display_proc[answer]
    else
      answer
    end
  end

  private

  def simple_answer
    print @prompt, " "
    gets.chomp
  end

  def multiple_choice_answer
    answer = nil

    until @choices.include?(answer)
      print @prompt, " "
      answer = gets.chomp
      puts "You must pick an answer from #{@choices}" unless @choices.include?(answer)
    end

    answer
  end
end

QUESTIONS = [
  Question.new(:question_1,
               "What is your name?"),
  Question.new(:question_2,
               "What is your favorite color?",
               nil,
               -&gt;(color) { "The color is #{color}." }),
  Question.new(:question_3,
               "What is your favorite integer between 1 and 5?",
               %w[1 2 3 4 5])
]

answers = {}

QUESTIONS.each do |question|
  answers[question.name] = question.answer
end

display_answers = Hash[
  QUESTIONS.map do |question|
    answer = answers[question.name]
    [question.name, question.display_answer(answer)]
  end
]

p display_answers
</code></pre>
<p>The post <a href="http://pivotallabs.com/refactoring-the-deeply-nested-hash-antipattern/">Refactoring the Deeply-Nested Hash Antipattern</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/refactoring-the-deeply-nested-hash-antipattern/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Standup 01/09/2012: Lightning and Rakes</title>
		<link>http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/</link>
		<comments>http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 12:52:00 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Standup]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[teamcity]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/</guid>
		<description><![CDATA[<p><h2>Help</h2>

<blockquote>
    <p><em>"<a href="http://blog.davidchelimsky.net/2012/01/04/rspec-28-is-released/">RSpec 2.8</a> is out. The Rake runner in TeamCity isn't yet working."</em></p>
</blockquote>

<p>The suggestion was to update to an <a href="http://confluence.jetbrains.net/display/TW/TeamCity+EAP">EAP release of TeamCity</a>.</p>

<h2>Events</h2>

<ul>
<li>Tuesday, January 10, 2012: <a href="http://www.meetup.com/NYC-rb/events/32802522/">NYC.rb lightning talks</a>, pizza, and beer after work at Pivotal NYC.</li>
</ul> <a href="http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/">Standup 01/09/2012: Lightning and Rakes</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<h2>Help</h2>
<blockquote>
<p><em>&#8220;<a href="http://blog.davidchelimsky.net/2012/01/04/rspec-28-is-released/">RSpec 2.8</a> is out. The Rake runner in TeamCity isn&#8217;t yet working.&#8221;</em></p>
</blockquote>
<p>The suggestion was to update to an <a href="http://confluence.jetbrains.net/display/TW/TeamCity+EAP">EAP release of TeamCity</a>.</p>
<h2>Events</h2>
<ul>
<li>Tuesday, January 10, 2012: <a href="http://www.meetup.com/NYC-rb/events/32802522/">NYC.rb lightning talks</a>, pizza, and beer after work at Pivotal NYC.</li>
</ul>
<p>The post <a href="http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/">Standup 01/09/2012: Lightning and Rakes</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/standup-01-09-2012-lightning-and-rakes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>pg_search: How I Learned to Stop Worrying and Love PostgreSQL full-text search</title>
		<link>http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/</link>
		<comments>http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/#comments</comments>
		<pubDate>Fri, 11 Feb 2011 19:16:00 +0000</pubDate>
		<dc:creator>Grant Hutchins</dc:creator>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://pivotallabs.com/pg-search/</guid>
		<description><![CDATA[<p><p>I’m a Pivotal Labs developer at our NYC offices working on the Casebook development team. <a href="http://www.casecommons.org/site/about/">Casebook</a> is a child-welfare-focused web application used by governments and non-profit organizations.  Our users are social workers, caseworkers, and their leadership who work with children, families, and the broader community to provide services that ensure children are safe and healthy.</p>

<h1>Search worries</h1>

<p>Our users need to quickly find accurate information about the people on their workload to respond appropriately in crises and keep a high quality written record of their work with the children and families.</p>

<p><a href="http://lucene.apache.org/solr/">Solr</a> powered Casebook’s initial search engine. Solr is built in Java, so we set up our application servers to run Java alongside our Ruby on Rails web application. We maintained a real-time copy of our important searchable data, such as people’s names, in our Solr index.</p>

<p>Our Solr-based approach ran into a few problems. Sometimes users would see outdated search results or, even worse, errors. This was annoying and also potentially damaging to our users’ ability to keep up with emergency situations.</p>

<p>Keeping our data synched in multiple locations caused most of our problems with Solr. Some of our more complex code paths would update the database but not propagate those changes to the search index. Users saw search-related error messages when there were communication problems with our Solr instances.</p>

<p>We had some fail-safes in place.</p>

<p>We wrote code that automatically restarted the Solr instances when they crashed. When we found the search data diverged from our application data, we manually rebuilt the search index to get the two data stores back in sync. These solutions just managed our problems rather than solving them.</p>

<p>These problems aren't unique to Solr. Other tools like <a href="http://lucene.apache.org/">Lucene</a>, <a href="http://www.davebalmain.com/trac">Ferret</a>, and <a href="http://sphinxsearch.com/">Sphinx</a> have the same shortcomings when combined with Ruby on Rails.</p>

<h1>Using the database itself as the search index</h1>

<p>So the thought occurred to our team that we ought to try to make the database itself be the search index. We use a <a href="http://www.postgresql.org/">PostgreSQL</a> database, and PostgreSQL 8.3 and later have <a href="http://www.postgresql.org/docs/current/static/textsearch.html">built-in support for full-text search</a>. PostgreSQL is a popular, mature SQL database solution that works great with Active Record. If you use <a href="http://heroku.com/">Heroku</a>, then you are already using a PostgreSQL 8.3 database that supports full-text search.</p>

<p>Since full-text search in PostgreSQL uses fairly complex SQL queries, we decided that the best approach would be to take advantage of Active Record's scopes. The idea is to make it easy to write code that looks like this:</p>

<pre><code>Book.search_title&#40;"Ruby"&#41;.include&#40;:author&#41;.where&#40;"created_at &#62; ?", 1.year.ago&#41;.limit&#40;10&#41;
</code></pre>

<p>So, I am proud to introduce <a href="https://github.com/casecommons/pg_search"><code>pg_search</code></a>, a Ruby gem that makes it easy to build search scopes that work just like this.</p> <a href="http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/">pg_search: How I Learned to Stop Worrying and Love PostgreSQL full-text search</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I’m a Pivotal Labs developer at our NYC offices working on the Casebook development team. <a href="http://www.casecommons.org/site/about/">Casebook</a> is a child-welfare-focused web application used by governments and non-profit organizations. Our users are social workers, caseworkers, and their leadership who work with children, families, and the broader community to provide services that ensure children are safe and healthy.</p>
<h1>Search worries</h1>
<p>Our users need to quickly find accurate information about the people on their workload to respond appropriately in crises and keep a high quality written record of their work with the children and families.</p>
<p><a href="http://lucene.apache.org/solr/">Solr</a> powered Casebook’s initial search engine. Solr is built in Java, so we set up our application servers to run Java alongside our Ruby on Rails web application. We maintained a real-time copy of our important searchable data, such as people’s names, in our Solr index.</p>
<p>Our Solr-based approach ran into a few problems. Sometimes users would see outdated search results or, even worse, errors. This was annoying and also potentially damaging to our users’ ability to keep up with emergency situations.</p>
<p>Keeping our data synched in multiple locations caused most of our problems with Solr. Some of our more complex code paths would update the database but not propagate those changes to the search index. Users saw search-related error messages when there were communication problems with our Solr instances.</p>
<p>We had some fail-safes in place.</p>
<p>We wrote code that automatically restarted the Solr instances when they crashed. When we found the search data diverged from our application data, we manually rebuilt the search index to get the two data stores back in sync. These solutions just managed our problems rather than solving them.</p>
<p>These problems aren&#8217;t unique to Solr. Other tools like <a href="http://lucene.apache.org/">Lucene</a>, <a href="http://www.davebalmain.com/trac">Ferret</a>, and <a href="http://sphinxsearch.com/">Sphinx</a> have the same shortcomings when combined with Ruby on Rails.</p>
<h1>Using the database itself as the search index</h1>
<p>So the thought occurred to our team that we ought to try to make the database itself be the search index. We use a <a href="http://www.postgresql.org/">PostgreSQL</a> database, and PostgreSQL 8.3 and later have <a href="http://www.postgresql.org/docs/current/static/textsearch.html">built-in support for full-text search</a>. PostgreSQL is a popular, mature SQL database solution that works great with Active Record. If you use <a href="http://heroku.com/">Heroku</a>, then you are already using a PostgreSQL 8.3 database that supports full-text search.</p>
<p>Since full-text search in PostgreSQL uses fairly complex SQL queries, we decided that the best approach would be to take advantage of Active Record&#8217;s scopes. The idea is to make it easy to write code that looks like this:</p>
<pre><code>Book.search_title("Ruby").include(:author).where("created_at &gt; ?", 1.year.ago).limit(10)
</code></pre>
<p>So, I am proud to introduce <a href="https://github.com/casecommons/pg_search"><code>pg_search</code></a>, a Ruby gem that makes it easy to build search scopes that work just like this.</p>
<p>Installing <code>pg_search</code> is easy. If you&#8217;re using Bundler, just add</p>
<pre><code>gem "pg_search"
</code></pre>
<p>to your Gemfile and you&#8217;re good to go.</p>
<p>To use <code>pg_search</code> to build the <code>Book.search_title</code> scope above, you would write:</p>
<pre><code>class Book &lt; ActiveRecord::Base
  include PgSearch
  pg_search_scope :search_title, :against =&gt; [:title]
end
</code></pre>
<p>It&#8217;s as simple as that!</p>
<h1>Adding more features</h1>
<p>We took cues from the <a href="https://github.com/tenderlove/texticle"><code>texticle</code></a> gem to figure out how to generate our SQL code. Thanks to <a href="http://tenderlovemaking.com/">Aaron Patterson</a> for this wonderful gem! However, our Solr solution had several features that <code>texticle</code> and the basic PostgreSQL full-text search alone don&#8217;t currently provide, like ignoring diacritical marks (accents like ü), searching for soundalikes, and searching for words that are misspelled.</p>
<p>We spent a day or two trying to hack <code>texticle</code> into something we could use, but realized that if we started from scratch we could more easily build a gem that could combine more than one PostgreSQL feature into a single search scope. That way, we could improve our <code>Book.search_title</code> scope by using <a href="http://www.postgresql.org/docs/current/static/pgtrgm.html">unaccent</a> to ignore accent marks, <a href="http://www.postgresql.org/docs/current/static/fuzzystrmatch.html#AEN121093">Double Metaphone</a> to match soundalikes, and <a href="http://www.postgresql.org/docs/current/static/pgtrgm.html">trigrams</a> to match misspellings.</p>
<p>So with all of these features turned on, we get the following code:</p>
<pre><code>class Book &lt; ActiveRecord::Base
  include PgSearch
  pg_search_scope :search_title,
    :against =&gt; [:title],
    :using =&gt; [:tsearch, :dmetaphone, :trigrams],
    :ignoring =&gt; :accents
end
</code></pre>
<p>Except for <code>:tsearch</code>, the default-in full-text search implementation, the other features require you to install certain <a href="http://www.postgresql.org/docs/current/static/contrib.html">contrib packages</a> into your database. For now, this is an exercise for the reader, but we hope to help automate this process soon.</p>
<h1>Our gem development approach</h1>
<p>We started by taking our application with the existing Solr-based search intact and boosting our test coverage as we could to cover all of the different cases (misspellings, soundalikes, etc.) for some of our most complicated searchable models. Once we were satisfied with our test coverage, we completely removed the Solr search code and were left with dozens of failing tests.</p>
<p>We then created a blank gem and starting adding features to it one-by-one to get each of our application&#8217;s tests to pass. First we made sure that simple situations were solid, such as when the search query string exactly matches the searchable text.<br />
Then we moved on to the complicated parts.</p>
<p>Our existing application uses Ruby 1.8 and Rails 2.3, and at the same time we have a new second project that uses Ruby 1.9 and Rails 3. So we made sure that all of our code worked in both environments. I will write another blog post soon about how we used two instances of <code>autotest</code> to make this easy to do.</p>
<p>The great thing about this approach is that we were able to start by defining a set of behaviors based on what our real-world application needed. This kept our code lean. Also, we were able to define our own syntax for the <code>pg_search_scope</code> method. By mimicking the Active Record scope syntax, hopefully we have created something that is easy to pick up. We would just add a new option to one of our calls to <code>pg_search_scope</code> and code until it worked as desired.</p>
<h1>User impact</h1>
<p>Our users have noticed the difference after we deployed our updated search implementation. We had been rebuilding the search index or troubleshooting a search related bug a few times a week. We haven’t seen a search related help request from our users since we made the changes. In addition, our developers are happier because code deployments are much more reliable and easy to understand.</p>
<p>Overall, the project has been a resounding success!</p>
<h1>Getting involved</h1>
<p><code>pg_search</code> isn’t complete yet (will it ever be?). There are many more features we’d like to have to improve performance, search quality, and overall user experience.</p>
<p>For example, right now our developers have to hand-build SQL indexes to improve query speed. <code>pg_search</code> should automatically generate those indexes for us based on which PostgreSQL features are in use.</p>
<p>That’s just one example. We’d love to hear more ideas from you about how pg_search can improve to meet users needs.</p>
<p>To learn more, read our <a href="https://github.com/Casecommons/pg_search/blob/master/README.rdoc">documentation</a>. We also have a public <a href="https://www.pivotaltracker.com/projects/228645">Pivotal Tracker project</a> for requesting features and bugfixes, and a <a href="http://groups.google.com/group/casecommons-dev">Google Group</a> for discussing pg_search and other Case Commons open source projects.</p>
<p>Also, the Casebook team is currently <a href="http://pivotallabs.com/users/jknowles/blog/articles/1555-casecommons-seeks-outstanding-agile-developer-in-nyc">hiring for an Agile Developer</a>.</p>
<p>The post <a href="http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/">pg_search: How I Learned to Stop Worrying and Love PostgreSQL full-text search</a> appeared first on <a href="http://pivotallabs.com">Pivotal Labs</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://pivotallabs.com/pg-search-how-i-learned-to-stop-worrying-and-love-postgresql-full-text-search/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic (Feed is rejected)
Page Caching using apc
Database Caching using apc
Object Caching 813/878 objects using apc

 Served from: pivotallabs.com @ 2013-05-21 22:19:12 by W3 Total Cache -->