<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>This is the company blog of thoughtbot, a web design and development agency based in Boston, MA.</description><title>giant robots smashing into other giant robots</title><generator>Tumblr (3.0; @thoughtbot)</generator><link>http://robots.thoughtbot.com/</link><item><title>Types of Coupling</title><description>&lt;p&gt;Those of you coming from a Google search are about to be disappointed: this is a post about types of coupling in &lt;i&gt;programming&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;Coupling refers to the degree to which components in your program rely on each other. You should generally seek to minimize this property, though you&amp;#8217;ll see it&amp;#8217;s impossible to eliminate entirely.&lt;/p&gt;

&lt;p&gt;Here are a few types of coupling, ordered by severity (first is worst):&lt;/p&gt;

&lt;h2&gt;Pathological Coupling&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Your class reaches inside another class and reads (or, perish the thought, changes) its instance variables.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You are literally pathological and deserve the pain this will cause you.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class NuclearLaunchController
  def initialize(launch_codes)
    @launch_codes = launch_codes
  end
end

class ExtremelyBadIdea
  def initialize(nuclear_launch_controller)
    @launch_controller = nuclear_launch_controller
  end

  def do_bad_things
    # This is poison
    @launch_controller.instance_variable_set(:@launch_codes, 'password')
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Global Coupling&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;You have two classes that both rely on some shared global data, maybe a &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;Singleton&lt;/a&gt; or a class variable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When many test files all depend on global factory definitions, a change to any one can ripple through the system.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# spec/factories.rb
FactoryGirl.define do
  factory :user do
    # Changes here are global and can affect many test files.
  end
end

# spec/model/user_spec.rb
before do
  # This refers to global data.
  @user = build_stubbed(:user)
end

# spec/model/order_spec.rb
before do
  # So does this.
  @user = build_stubbed(:user)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that this is probably an example where the cure (duplicating the logic for creating test objects in every spec) is worse than the disease.&lt;/p&gt;

&lt;h2&gt;Control Coupling&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;You pass in a flag that tells a method what to do.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Remember &lt;code&gt;save(false)&lt;/code&gt; in &lt;code&gt;ActiveRecord&lt;/code&gt;? That boolean argument caused control coupling. Remember how we all had to change our code when it became &lt;code&gt;save(validate: false)&lt;/code&gt;? If we&amp;#8217;d been calling &lt;code&gt;save&lt;/code&gt; and &lt;code&gt;save_without_validation&lt;/code&gt; instead, Rails Core could have refactored that method more times than the router and we&amp;#8217;d never have known. Also, notice that passing &lt;code&gt;validate: false&lt;/code&gt; into &lt;code&gt;save&lt;/code&gt; does not reduce the coupling, it&amp;#8217;s just disguised better.&lt;/p&gt;

&lt;p&gt;Control couples are smelly because the calling method has intimate knowledge of how the receiver implements the method being called. You&amp;#8217;re determining what an object should do based from outside it. Good OOP lets objects decide what to do based on their own state.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def save(should_run_validations=true)
  # When you see a parameter in a conditional, that's control coupling.
  # The fact that this method has an if in it has leaked out into client code.
  # Changes can now require changes in these clients.
  if should_run_validations
    run_validations
    persist
  else
    persist
  end
end

# One possible fix: define two methods and let the clients 
# choose which to call. Now we can refactor either without 
# affecting clients.
def save
  run_validations
  persist
end

def save_without_validations
  persist
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Data Coupling&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;You call a method and pass it a parameter that doesn&amp;#8217;t affect its control flow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is still coupling, but we&amp;#8217;re starting to reach the kind that isn&amp;#8217;t so bad. Sometimes you need parameters! If you wanted to remove all coupling you wouldn&amp;#8217;t be able to pass data between objects at all.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ScreenPrinter
  # This method is coupled to its parameter, because a change to that argument 
  # can cause breakage (if we undefined to_s, for example).
  def print(text)
    output_to_screen(text.to_s)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Message Coupling&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;You call a method on an object and send no parameters.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You&amp;#8217;re coupled to the name of the message, but not any hint of its implementation. This is the loosest type of coupling and should be your goal. Notice that this makes methods that take no arguments better than methods that take one (and so on).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# No reliance on anything outside this object. Feels good, man.
class ScreenPrinter
  def print_to_screen
    output_to_screen(@text)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Keep an eye out for the nasty types of coupling in your code, and see if you can can&amp;#8217;t refactor it into something further down the ladder.&lt;/p&gt;

&lt;p&gt;(I cribbed this list of coupling types from &lt;a href="http://en.wikipedia.org/wiki/Coupling_(computer_programming)"&gt;Wikipedia&amp;#8217;s article&lt;/a&gt;, paraphrased and added examples. The original article is worth reading.)&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/23112388518</link><guid>http://robots.thoughtbot.com/post/23112388518</guid><pubDate>Tue, 15 May 2012 14:17:00 -0400</pubDate><category>ruby</category><category>coupling</category><category>code smells</category></item><item><title>Get your callbacks on with Factory Girl 3.3</title><description>&lt;p&gt;FactoryGirl 3.3.0 was released this weekend with a slew of improvements.&lt;/p&gt;

&lt;p&gt;To install, add (or change) your Gemfile:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem 'factory_girl_rails', '~&amp;gt; 3.3.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;New Callback Syntax&lt;/h2&gt;

&lt;p&gt;Callbacks have been revamped to work well in conjunction with custom
strategies. Instead of declaring callbacks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.define do
  factory :user do
    factory :user_with_posts do
      after_create {|instance| create_list(:post, 5, user: instance) }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you can declare callbacks with &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt;, passing the symbol of
the callback as the name:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.define do
  factory :user do
    after(:custom) {|instance| instance.do_something_custom! }

    factory :user_with_posts do
      after(:create) {|instance| create_list(:post, 5, user: instance) }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, you can use completely custom callbacks without a before or after
prepended by just calling &lt;code&gt;callback&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.define do
  factory :user do
    callback(:custom_callback) {|instance| instance.do_something_custom! }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These work great with &lt;a href="http://robots.thoughtbot.com/post/21719164760/factorygirl-3-2-so-awesome-it-needs-to-be-released"&gt;custom
strategies&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class CustomStrategy
  def initialize
    @strategy = FactoryGirl.strategy_by_name(:create).new
  end

  delegate :association, to: :@strategy

  def result(evaluation)
    @strategy.result(evaluation).tap do |instance|
      evaluation.notify(:custom_callback, instance) # runs callback(:custom_callback)
      evaluation.notify(:after_custom, instance)    # runs after(:custom)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Support all &lt;code&gt;*_list&lt;/code&gt; methods&lt;/h2&gt;

&lt;p&gt;FactoryGirl already introduced &lt;code&gt;build_list&lt;/code&gt; and &lt;code&gt;create_list&lt;/code&gt; to build and create
an array of instances; in 3.3.0, &lt;code&gt;*_list&lt;/code&gt; methods are generated dynamically
for all strategies registered, so &lt;code&gt;build_stubbed_list&lt;/code&gt; and
&lt;code&gt;attributes_for_list&lt;/code&gt; join the immediate roster of methods; if you were to
register a strategy named &amp;#8220;insert&amp;#8221;, &lt;code&gt;insert_list&lt;/code&gt; would exist as well.&lt;/p&gt;

&lt;h2&gt;Fix &lt;code&gt;to_create&lt;/code&gt; and &lt;code&gt;initialize_with&lt;/code&gt; within traits&lt;/h2&gt;

&lt;p&gt;Traits are a great way to name an abstract concept of attributes, but for a
long time, they didn&amp;#8217;t support defining &lt;code&gt;to_create&lt;/code&gt; or &lt;code&gt;initialize_with&lt;/code&gt;.
3.3.0 fixes this shortcoming by having &lt;code&gt;to_create&lt;/code&gt; and &lt;code&gt;initialize_with&lt;/code&gt;
behave in traits exactly as you&amp;#8217;d expect. This is perfect for decorating
objects from within FactoryGirl.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class NotifierDecorator &amp;lt; BasicObject
  undef_method :==

  def initialize(component)
    @component = component
  end

  def save!
    @component.save!.tap do
      Notifier.new(@component).notify("saved!")
    end
  end

  def method_missing(name, *args, &amp;amp;block)
    @component.send(name, *args, &amp;amp;block)
  end

  def send(symbol, *args)
    __send__(symbol, *args)
  end
end

FactoryGirl.define do
  trait :with_notifications do
    to_create {|instance| NotifierDecorator.new(instance).save! }
  end

  factory :user
end

create(:user, :with_notifications) # decorates save! when the instance is created


FactoryGirl.define do
  trait :with_notifications do
    initialize_with { NotifierDecorator.new(new) }
  end

  factory :post
end

create(:post, :with_notifications) # returns a post instance decorated with NotifierDecorator
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Define &lt;code&gt;to_create&lt;/code&gt; and &lt;code&gt;initialize_with&lt;/code&gt; globally&lt;/h2&gt;

&lt;p&gt;If you&amp;#8217;re using an ORM other than ActiveRecord, you may want to call different
methods for persistence. Declaring a &lt;code&gt;to_create&lt;/code&gt; (or &lt;code&gt;initialize_with&lt;/code&gt;, if you
wanted to use a global decorator) within the &lt;code&gt;FactoryGirl.define&lt;/code&gt; block will
now apply to all declared factories, behaving much like sequences, traits, and
factories.&lt;/p&gt;

&lt;p&gt;You can override the global &lt;code&gt;to_create&lt;/code&gt; or &lt;code&gt;initialize_with&lt;/code&gt; with traits or by
defining &lt;code&gt;to_create&lt;/code&gt; in a factory explicitly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.define do
  to_create {|instance| instance.persist! }

  factory :user do
    factory :user_backed_by_active_record do
      to_create {|instance| instance.save! }
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;There are still cases where traits don&amp;#8217;t behave correctly (using implicit
traits is a big remaining bug) and more work for &lt;code&gt;initialize_with&lt;/code&gt; and
accessing attributes needs to be done.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/23039827914</link><guid>http://robots.thoughtbot.com/post/23039827914</guid><pubDate>Tue, 15 May 2012 09:44:00 -0400</pubDate><category>factory girl</category><category>callbacks</category><category>rails</category><category>testing</category></item><item><title>Beware Homonyms</title><description>&lt;p&gt;When you name a class, choose a name that’s unlikely to refer more than one thing.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;Visitor&lt;/code&gt; is a bad name for a class that represents unregistered users.&lt;/p&gt;

&lt;p&gt;The issue is that &lt;code&gt;Visitor&lt;/code&gt; is the name of a well-known pattern. Like it or not, the Gang of Four claimed this one (that’s why they’re called a gang).&lt;/p&gt;

&lt;p&gt;If you use this class name in a web app, I can guess which concept you’re referring to, but the ambiguity is unsettling. I’m not sure. The name has &lt;strong&gt;homonymatic complexity&lt;/strong&gt;: it sounds too much like another thing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UnregisteredUser&lt;/code&gt; is a better name. It’s easy to guess what this refers to.&lt;/p&gt;

&lt;p&gt;However, notice the ambiguity is affected by the problem domain: in a voter registration app, this name would again be ambiguous.&lt;/p&gt;

&lt;p&gt;In general, choose names so colleagues can easily guess an object’s identity.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22987775858</link><guid>http://robots.thoughtbot.com/post/22987775858</guid><pubDate>Sun, 13 May 2012 15:29:00 -0400</pubDate><category>naming</category></item><item><title>SHOULDA BEEN GONE</title><description>&lt;p&gt;We haven&amp;#8217;t been taking pull requests on &lt;a href="https://github.com/thoughtbot/shoulda-matchers"&gt;shoulda-matchers&lt;/a&gt; as much as we shoulda, but it&amp;#8217;s back in the spotlight now. Shoulda&amp;#8217;s been gone &amp;#8230; but it&amp;#8217;s back.&lt;/p&gt;
&lt;p&gt;&lt;iframe frameborder="0" height="315" src="https://www.youtube.com/embed/CNXDCHHjEvs?rel=0" width="420"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;Here are the new features in shoulda-matchers 1.1.0:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A &lt;a href="https://github.com/thoughtbot/shoulda-matchers/blob/master/NEWS.md"&gt;NEWS file&lt;/a&gt; so you can track new hottness in REAL TIME&lt;/li&gt;
&lt;li&gt;shoulda-matchers&amp;#8217; very first dependency: ActiveSupport &amp;gt;= 3.0.0. This was an implicit dependency for a while, but now it&amp;#8217;s official.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;only_integer&lt;/code&gt; option for &lt;code&gt;validates_numericality_of&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;query_the_database&lt;/code&gt; matcher, so that you can do &lt;code&gt;it { should query_the_database(4.times).or_less }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Database column primality is correctly checked&lt;/li&gt;
&lt;li&gt;The flash matcher can check specific keys using &lt;code&gt;[]&lt;/code&gt;, like so: &lt;code&gt;it { should set_the_flash[:alert].to("Bad username") }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;validates_confirmation_of&lt;/code&gt; matcher: &lt;code&gt;it { should validate_confirmation_of(:password) }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;serialize&lt;/code&gt; matcher: &lt;code&gt;it { should serialize(:details).as(Hash).as_instance_of(Hash) }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;have_sent_email&lt;/code&gt; matcher can now check &lt;code&gt;reply_to: it { should have_sent_email.reply_to([user, other]) }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;accept_nested_attributes&lt;/code&gt; matcher&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you filed a pull request and we didn&amp;#8217;t take a look, please re-submit or ping me on Github. We&amp;#8217;d love to &lt;a href="https://github.com/thoughtbot/shoulda-matchers"&gt;hear from you&lt;/a&gt;.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22899996266</link><guid>http://robots.thoughtbot.com/post/22899996266</guid><pubDate>Sat, 12 May 2012 09:14:25 -0400</pubDate><category>journey</category><category>open source</category><category>shoulda</category><category>shoulda-matchers</category><category>SHOULDABEENGONE</category></item><item><title>Read between the lines</title><description>&lt;p&gt;People frequently use lines of code as a metric. How many times have you heard someone say, &amp;#8220;it&amp;#8217;s only 10 lines?&amp;#8221; or &amp;#8220;This class is almost 200 lines?&amp;#8221; Have you ever heard somebody boast that they could write something in fewer lines of code? Do you talk about your test to code ratio?&lt;/p&gt;

&lt;p&gt;How many lines of code something takes doesn&amp;#8217;t tell us much about the code.  Let&amp;#8217;s take a closer look at some better metrics.&lt;/p&gt;

&lt;h2&gt;Complexity&lt;/h2&gt;

&lt;p&gt;Focusing on lines of code encourages developers to jam as much complexity as they can into each line.&lt;/p&gt;

&lt;p&gt;Compare this example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def credit
  user &amp;amp;&amp;amp; coupon = user.coupons.where(:product_id =&amp;gt; product.id).first.try(:amount) || 0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To this one:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def credit
  user &amp;amp;&amp;amp; user.coupon_for(product).amount || 0
end

# On User
def coupon_for(product)
  coupons.where(:product_id =&amp;gt; product.id).first.try(:amount)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Although the first example is only three lines of code, it has a lot of complexity in one method. That means this method is harder to understand, reuse, modify, or extract. Flog rates this method at 13.9.&lt;/p&gt;

&lt;p&gt;The second example example has twice as many lines, but each method is less complex. Flog rates the second example at 8.1 per method.&lt;/p&gt;

&lt;p&gt;Even in the second example, the methods are dense. Further refactoring would result in more lines of code, but smaller, simpler methods.&lt;/p&gt;

&lt;h2&gt;Readability&lt;/h2&gt;

&lt;p&gt;The previous example also improves readability. Every method you extract is an opportunity to clarify something by naming it, while every piece of complexity you add to a line is anonymous.&lt;/p&gt;

&lt;p&gt;Code is frequently more readable when it expands over multiple lines of code. Here&amp;#8217;s a common Ruby idiom:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;users.each(&amp;amp;:friend_added) if new_record?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I like to call this the &amp;#8220;if surprise.&amp;#8221; It&amp;#8217;s easy to scan down a method and miss that dangling if, not realizing that the method you&amp;#8217;re debugging actually has a logical fork.&lt;/p&gt;

&lt;p&gt;I prefer this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if new_record?
  users.each(&amp;amp;:friend_added)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s three times as many lines, but the same amount of complexity, and more readable.&lt;/p&gt;

&lt;h2&gt;Test to code ratio&lt;/h2&gt;

&lt;p&gt;Another place that people obsess over lines is their &lt;a href="http://robots.thoughtbot.com/post/159806234/simple-test-metrics-in-your-rails-app-and-what-they"&gt;test to code ratio&lt;/a&gt;. Rails even comes with a task to print this stat out for you, and many presentations use this stat when bragging about their test coverage (or lack thereof). There are a few things that make this metric meaningless:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Some frameworks create taller code. RSpec tests tend to have more lines than the same Test::Unit test, despite having the same coverage.&lt;/li&gt;
&lt;li&gt;The best way to have a high test to code ratio is to copy and paste test code, which is the testing equivalent of never flushing your toilet.&lt;/li&gt;
&lt;li&gt;How many tests you have is a poor metric for measuring the quality of the test suite.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here are some questions that can be useful when measuring your test suite:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Were all the tests written before the code that they motivate?&lt;/li&gt;
&lt;li&gt;Do you have 100% &lt;a href="http://dev-logger.blogspot.com/2008/06/c0-c1-and-c2-coverage.html"&gt;C0 coverage&lt;/a&gt;? Ask &lt;code&gt;rcov&lt;/code&gt; or &lt;code&gt;simplecov&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Do your tests break if your code breaks?&lt;/li&gt;
&lt;li&gt;Is there duplication in your tests?&lt;/li&gt;
&lt;li&gt;Can you read your tests easily?&lt;/li&gt;
&lt;li&gt;If you add new code, do old tests break?&lt;/li&gt;
&lt;li&gt;Can you refactor one class without breaking the tests for other classes?&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;No code is faster than no code&lt;/h2&gt;

&lt;p&gt;Merb popularized this saying and encouraged users not to use code they didn&amp;#8217;t need. However, it&amp;#8217;s important not to misinterpret this by assuming that fewer lines of code means less code, and therefore faster code.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example of a minimal Fibonacci sequence:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Fibber
  def fib(n)
    if n &amp;lt; 2
      n
    else
      fib(n - 1) + fib(n - 2)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This implementation is pretty slow. It took almost five seconds to print out the first 35 numbers in the sequence on my machine. You can improve the performance dramatically with just a few more lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Fibber
  def initialize
    @cache = {}
  end

  def fib(n)
    if n &amp;lt; 2
      n
    else
      @cache[n] ||= fib(n - 1) + fib(n - 2)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This takes around a millisecond on my machine.&lt;/p&gt;

&lt;p&gt;Your application will perform better if you remove functionality you don&amp;#8217;t need, but removing lines and watching the tests still pass doesn&amp;#8217;t mean you haven&amp;#8217;t lost anything.&lt;/p&gt;

&lt;h2&gt;Edge cases&lt;/h2&gt;

&lt;p&gt;In version 2.4.0 of factory_girl, we added almost three hundred lines of code and almost no features. That seems like a lot of code for no new functionality, but what actually happened is that we fixed a number of annoying bugs. Fixing the last few edge cases for a library can be a huge undertaking; the last ten percent frequently takes as long as the first ninety percent. There have been times that we&amp;#8217;ve been tempted to rewrite factory_girl, because it doesn&amp;#8217;t seem that hard to implement at a glance. However, a new implementation would reintroduce bugs that have been fixed for years.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re thinking of rewriting something, remember that it&amp;#8217;s probably not as easy as it looks. You don&amp;#8217;t just have to reimplement the features; you have to fix the edge cases, too.&lt;/p&gt;

&lt;h2&gt;Love your lines&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s stop thinking in terms of lines of code. Here are a few tips:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Think in terms of complexity, not lines&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;flog&lt;/code&gt; or &lt;code&gt;rcov&lt;/code&gt;, not &lt;code&gt;wc -l&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you want to remove complexity or improve performance, remove features and not just code&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As a community, we&amp;#8217;ve developed a number of techniques and tools for evaluating code. We can do better than just counting lines.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22777096999</link><guid>http://robots.thoughtbot.com/post/22777096999</guid><pubDate>Thu, 10 May 2012 08:43:21 -0400</pubDate><category>lines of code</category><category>metrics</category></item><item><title>Use Factory Girl's build_stubbed for a Faster Test Suite</title><description>&lt;p&gt;Want to speed up your test suite? Reduce the number of objects persisted to
the database. With Factory Girl, this is really easy; instead of using &lt;code&gt;build&lt;/code&gt;
or &lt;code&gt;create&lt;/code&gt; to instantiate your models with data, use &lt;code&gt;build_stubbed&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;build_stubbed&lt;/code&gt; is the younger, more hip sibling to &lt;code&gt;build&lt;/code&gt;; it instantiates
and assigns attributes just like &lt;code&gt;build&lt;/code&gt;, but that&amp;#8217;s where the similarities
end. It makes objects look look like they&amp;#8217;ve been persisted, creates
associations with the &lt;code&gt;build_stubbed&lt;/code&gt; strategy (whereas &lt;code&gt;build&lt;/code&gt; still uses
&lt;code&gt;create&lt;/code&gt;), and stubs out a handful of methods that interact with the database
and raises if you call them. This leads to much faster tests and reduces your
test dependency on a database.&lt;/p&gt;

&lt;p&gt;For example, let&amp;#8217;s say we have an &lt;code&gt;OrderProcessor&lt;/code&gt; that accepts instances of
&lt;code&gt;Order&lt;/code&gt; and &lt;code&gt;CreditCard&lt;/code&gt;. It hits the Braintree API and returns a boolean
value for if the charge actually happened.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class OrderProcessor
  def initialize(order, credit_card)
    @order = order
    @credit_card = credit_card
  end

  def process
    charge_successful? charge_customer
  end

  private

  def charge_successful?(result)
    # processes the result to determine if the result is valid,
    # operating on the order and credit_card instance variables to
    # add errors, send emails, or track Braintree's transaction id
  end

  def charge_customer
    # runs Braintree::Customer.sale() with the appropriate options
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;None of this code hits the database. This allows us to write tests like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe OrderProcessor do
  let(:transaction_id) { '1234' }
  let(:order) { build_stubbed(:order) }
  let(:credit_card) { build_stubbed(:credit_card) }

  subject { OrderProcessor.new(order, credit_card) }

  context 'when the Braintree result is valid' do
    before do
      MockBraintree.stub_successful_customer_sale(transaction_id: transaction_id)
    end

    it 'assigns the transaction id to the order' do
      subject.process
      order.transaction_id.should == transaction_id
    end

    it 'returns true for #process' do
      subject.process.should be
    end

    it 'does not assign any errors to the credit card' do
      subject.process
      credit_card.errors.should be_empty
    end
  end

  context 'when the Braintree result is invalid' do
    before do
      MockBraintree.stub_unsuccessful_customer_sale
    end

    it 'does not assign the transaction id to the order' do
      subject.process
      order.transaction_id.should be_nil
    end

    it 'returns false for #process' do
      subject.process.should_not be
    end

    it 'assigns errors to the credit card' do
      subject.process
      credit_card.errors.should_not be_empty
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead of creating twelve different records (at the minimum - if any of these
factories have associations, you introduce more multipliers), we create none.
This keeps the spec blazing fast.&lt;/p&gt;

&lt;p&gt;Properly factored code should be small and concise. Code should typically depend
&lt;em&gt;less&lt;/em&gt; on the state of the data &lt;strong&gt;in relation to the database&lt;/strong&gt; and more on its
state &lt;strong&gt;in relation to other objects&lt;/strong&gt;. In the above example, &lt;code&gt;OrderProcessor&lt;/code&gt;
only handles dealing with Braintree and dealing with its errors; it does &lt;strong&gt;not&lt;/strong&gt;
care about how this data is displayed to the user. That&amp;#8217;s left for the
integration tests, which should be hitting the database.&lt;/p&gt;

&lt;p&gt;Although it&amp;#8217;s not useful in every situation (there are cases where you&amp;#8217;ll want
data to exist, like when you&amp;#8217;re testing uniqueness constraints or scopes),
&lt;code&gt;build_stubbed&lt;/code&gt; should be your go-to FactoryGirl method over &lt;code&gt;build&lt;/code&gt; or
&lt;code&gt;create&lt;/code&gt;. Everyone running your test suite (yes, even yourself) will thank you.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22670085288</link><guid>http://robots.thoughtbot.com/post/22670085288</guid><pubDate>Wed, 09 May 2012 10:49:00 -0400</pubDate><category>factory girl</category><category>rails</category><category>slow tests</category><category>testing</category></item><item><title>Constrain Yourself</title><description>&lt;p&gt;Most Rails developers have written apps where you have a marketing homepage
and a route that you should be redirected to after signing in. There may even
be different pages to be redirected to after signing based on some sort of role
system.&lt;/p&gt;

&lt;p&gt;Who wants to remember that route across the app? No one.&lt;/p&gt;

&lt;p&gt;Instead of writing a nasty helper to determine where to send a user after
signing in, let&amp;#8217;s have Rails handle this for us.&lt;/p&gt;

&lt;p&gt;Enter Rails routing constraints.&lt;/p&gt;

&lt;p&gt;It turns out Rack is a beautiful piece of software! With Rails routing
constraints, we can re-use the Rails&amp;#8217; &lt;code&gt;root&lt;/code&gt; to handle all this logic for us.
This means no more remembering where &lt;code&gt;root_url&lt;/code&gt; will take you or stuffing all
that logic into some giant switch statement!&lt;/p&gt;

&lt;p&gt;For example, I recently wrote an app using Clearance and &lt;code&gt;high_voltage&lt;/code&gt;. When
visiting the root path without being signed in, I wanted to render high
voltage&amp;#8217;s &amp;#8216;homepage&amp;#8217; view. If the user was signed in, I wanted to display an
administrative page where they could manage their assets.&lt;/p&gt;

&lt;p&gt;My routes file looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;root to: "assets#index", constraints: Clearance::SignedInConstraint
root to: "high_voltage/pages#show", id: "homepage"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Two roots! My constraint to hitting assets#index is based off my class
&lt;code&gt;Clearance::SignedInConstraint&lt;/code&gt;, which I&amp;#8217;ve thrown in &lt;code&gt;lib/&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# lib/clearance/signed_in_constraint.rb
module Clearance
  class SignedInConstraint
    def self.matches?(request)
      request.env[:clearance].signed_in?
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This looks to &lt;code&gt;request.env[:clearance]&lt;/code&gt; (introduced in Clearance 0.13), which
returns a &lt;code&gt;Clearance::Session&lt;/code&gt; instance, and allows us to call &lt;code&gt;#signed_in?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With Rails constraints, if &lt;code&gt;.matches?&lt;/code&gt; returns true, the constraint is
fulfilled and the router allows assets#index to do its thing. When false, the
route &amp;#8216;falls through&amp;#8217; and the next root kicks in.&lt;/p&gt;

&lt;p&gt;Constraints are a great way to scope routes based on particular preconditions
and may end up cleaning up a handful of nasty conditional logic in a view
helper. Constraints can be great for things like subdomains as well, but I&amp;#8217;d
love to hear about some more inventive uses.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22605580334</link><guid>http://robots.thoughtbot.com/post/22605580334</guid><pubDate>Tue, 08 May 2012 10:27:00 -0400</pubDate><category>rails</category><category>routes</category><category>clearance</category><category>high_voltage</category><category>rack</category></item><item><title>Humans Present: Refactoring</title><description>&lt;p&gt;In the &lt;a href="https://workshops.thoughtbot.com/products/6-humans-present-refactoring?utm_source=blog"&gt;latest Humans Present&lt;/a&gt;, I sit down with Joe Ferris, our CTO, and we refactor real code from Trajectory.&lt;/p&gt;

&lt;p&gt;This hour and ten minute interview and screencast shows:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;What is refactoring and what you need to do it&lt;/li&gt;
&lt;li&gt;Pros and cons of different refactoring techniques&lt;/li&gt;
&lt;li&gt;Removing duplication&lt;/li&gt;
&lt;li&gt;Extracting code to classes and modules&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The changes in this video were merged into master and deployed to production the week after filming.&lt;/p&gt;

&lt;p&gt;You can purchase this video for $15 or buy it for your entire company for $50. &lt;a href="https://workshops.thoughtbot.com/products/6-humans-present-refactoring?utm_source=blog"&gt;Check it out now&lt;/a&gt;. Click through for a preview.&lt;/p&gt;

&lt;p&gt;We hope you like it.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22443641867</link><guid>http://robots.thoughtbot.com/post/22443641867</guid><pubDate>Sat, 05 May 2012 09:18:53 -0400</pubDate><category>refactoring</category><category>Humans Present</category><category>video</category><category>screencast</category></item><item><title>I Suck at Testing</title><description>&lt;p&gt;Testing is widespread in the Rails community, which is awesome.  For most new developers, learning to test is not simple.  New developers often think testing should come naturally if you can code well. I mean, I wrote the code, I should be able to write a test for it, right?  Over the past 2 months at thoughtbot I&amp;#8217;ve come to learn why this is false and now I&amp;#8217;m learning to test.&lt;/p&gt;



&lt;h2&gt;Testing is Hard&lt;/h2&gt;

&lt;p&gt;&#13;&lt;/p&gt;

&lt;p&gt;Testing is like any other skill, you have to practice to get good at it. Good test driven developers use previous experience to figure out what tools to use when presented with   new challenges. Don&amp;#8217;t get discouraged when you don&amp;#8217;t know how to test something, just take a step back and evaluate the problem. Improving your testing skill also requires discipline and persistence.&lt;/p&gt;



&lt;h2&gt;Testing is a discipline&lt;/h2&gt;

&lt;p&gt;&#13;&lt;/p&gt;

&lt;p&gt;No matter how dedicated you are to testing, there are times when it will slow you down.  At that point, its really easy to skip testing, just this one time.  It takes discipline to make sure that doesn&amp;#8217;t happen.  Take the extra time, invest the extra effort and find out how to test it, and then in the end your development process will speed up.&lt;/p&gt;



&lt;h2&gt;Ask for help&lt;/h2&gt;

&lt;p&gt;&#13;&lt;/p&gt;

&lt;p&gt;The Rails community has tons of people willing to help.  If you get stuck on testing something, google first, then check out the &lt;a href="http://railsforum.com/"&gt;Rails forums&lt;/a&gt; or the &lt;a href="http://rubyonrails.org/community"&gt;Rails IRC channel&lt;/a&gt;.  Don&amp;#8217;t hesitate to comment on blog posts which come close to solving your problem, but fall short.  I&amp;#8217;ve found the Rails community to be very helpful so don&amp;#8217;t be afraid to &amp;#8216;drink from the firehose.&amp;#8217;&lt;/p&gt;



&lt;h2&gt;It gets better&lt;/h2&gt;

&lt;p&gt;&#13;&lt;/p&gt;

&lt;p&gt;Learning to be a good at test-driven development is hard, but being a developer is hard in general and testing skills must be practiced.  Once you start writing tests more regularly, you also learn how to write code that is inherently easier to test.  I joined apprentice.io to become a great developer and learning to test well is &lt;a href="http://www.youtube.com/watch?v=pele5vptVgc"&gt;half the battle&lt;/a&gt;.  It&amp;#8217;s ok to suck at testing when you begin, but practice makes perfect.  A great place to start learning is our &lt;a href="https://workshops.thoughtbot.com/courses/1-intro-to-test-driven-rails"&gt;Intro to Test Driven Rails Workshop&lt;/a&gt;, we have a course coming up later this month.  Soon enough, you will think in tests before thinking in code.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22380971219</link><guid>http://robots.thoughtbot.com/post/22380971219</guid><pubDate>Fri, 04 May 2012 09:24:00 -0400</pubDate><category>test-driven development</category><category>learning</category></item><item><title>Come Correct with Inject and Collect</title><description>&lt;p&gt;Here&amp;#8217;s a refactoring example for a simple Ruby math problem using the &lt;code&gt;inject&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The goal is to generate an n by n multiplication matrix. Pretty straightforward. Let&amp;#8217;s make a first pass:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def multiplication_table(n)
  results = []

  (1..n).each do |row_index|
    row = []
    (1..n).each { |column_index| row &amp;lt;&amp;lt; row_index * column_index }
    results &amp;lt;&amp;lt; row
  end

  results.each do |row|
    header = '%-3s ' * row.length
    puts header % row
  end
end

multiplication_table(7)
1   2   3   4   5   6   7
2   4   6   8   10  12  14
3   6   9   12  15  18  21
4   8   12  16  20  24  28
5   10  15  20  25  30  35
6   12  18  24  30  36  42
7   14  21  28  35  42  49
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It does the job, but it&amp;#8217;s nothing to look at. We can condense using in-line blocks and fancy curly braces, but first let&amp;#8217;s try using &lt;code&gt;inject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quick background: Inject iterates over a set using a block with a collector, which is a variable whose value is passed back each round, making it good for iterative uses. The block&amp;#8217;s return value is passed into the collector (make sure you return something or you&amp;#8217;ll get a nil). Also, the return value of the whole inject block is the final collector value.&lt;/p&gt;

&lt;p&gt;Simple example &lt;a href="http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject"&gt;from the docs&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(5..10).inject {|sum, n| sum + n }            #=&amp;gt; 45
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The inject method takes a parameter, which initializes the collector value (default is to set to the first value). You can pass in an empty array and add values:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def multiplication_table(n)
  results = (1..n).map do |row_index|
    (1..n).inject([]) { |row, n| row + [row_index * n] }
  end

  results.each { |row| puts '%-3s ' * row.length % row }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So that&amp;#8217;s inject with the iterative collect &lt;a href="http://www.youtube.com/watch?v=AiVpSSkwPU4"&gt;(Whoo-aaaa - got you all in check)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: For a more in-depth discussion of &lt;code&gt;inject&lt;/code&gt;, read &lt;a href="http://robots.thoughtbot.com/post/17782192029/derive-inject-for-a-better-understanding"&gt;Mike Burns&amp;#8217; recent post.&lt;/a&gt;&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22319029309</link><guid>http://robots.thoughtbot.com/post/22319029309</guid><pubDate>Thu, 03 May 2012 09:31:21 -0400</pubDate><category>inject</category><category>enumerable</category><category>refactoring</category><category>arrays</category><category>ruby</category></item><item><title>How to extract an intention-revealing name using Vim</title><description>&lt;p&gt;This method has a &lt;a href="http://c2.com/cgi/wiki?MagicNumber"&gt;magic number&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def wait_time
  @env[QUEUE_WAIT_HEADER].to_i / 1000
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;#8217;s extract that to an &lt;a href="http://c2.com/cgi/wiki?IdentifiersRevealIntent"&gt;intention-revealing name&lt;/a&gt;. We&amp;#8217;ll type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/1000&amp;lt;Enter&amp;gt;                   # Find the number we want to extract
cwmilliseconds_per_second&amp;lt;Esc&amp;gt; # Replace the number with a variable name
O&amp;lt;Ctrl+A&amp;gt; = &amp;lt;Esc&amp;gt;p             # Assign the replaced number to the variable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def wait_time
  milliseconds_per_second = 1000
  @env[QUEUE_WAIT_HEADER].to_i / milliseconds_per_second
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Under the covers:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;&amp;lt;Ctrl+A&amp;gt;&lt;/code&gt; inserts the last text you typed in insert mode, so the variable name is available after replacing the number&lt;/li&gt;
&lt;li&gt;Replacing or deleting text in Vim will place that text in your default buffer, so the number is available to put at the end&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Assuming your cursor is at the value you want to extract, this creates an intention revealing name in 10 keystrokes, plus the keystrokes it takes to type out the name.&lt;/p&gt;

&lt;p&gt;Can you beat my Vim golf?&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/22258289125</link><guid>http://robots.thoughtbot.com/post/22258289125</guid><pubDate>Wed, 02 May 2012 11:47:10 -0400</pubDate><category>vim</category><category>golf</category><category>refactoring</category></item><item><title>Date and time formats for pirates</title><description>&lt;p&gt;Need to display a date in your Rails app? First try:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time.now.strftime "arrrround %H'ish"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To remove duplication, you imagine a &lt;a href="http://robots.thoughtbot.com/post/9012426894/custom-formats-for-datetime"&gt;time format initializer&lt;/a&gt;. Second try:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time.now.to_s :pirate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then you remember the &lt;code&gt;:default&lt;/code&gt; &lt;a href="http://guides.rubyonrails.org/i18n.html#adding-date-time-formats"&gt;localized&lt;/a&gt; key. Third time&amp;#8217;s a charm:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;l Time.now
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It formats based on the &lt;code&gt;config/locales/en.yml&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;en:
  time:
    formats:
      default: "arrrround %H'ish"
  date:
    formats:
      default: "arrrround %H'ish"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dates work, too:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;l Date.today
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://robots.thoughtbot.com/post/392707640/the-more-you-know-custom-time-descriptions"&gt;The same system&lt;/a&gt; lets you alter the display of &amp;#8220;days ago&amp;#8221; and &amp;#8220;minute from now.&amp;#8221;&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21920979385</link><guid>http://robots.thoughtbot.com/post/21920979385</guid><pubDate>Fri, 27 Apr 2012 13:59:00 -0400</pubDate><category>ruby on rails</category><category>i18n</category><category>time</category><category>time format</category></item><item><title>Inbox Zero: Github Issues Edition</title><description>&lt;p&gt;We&amp;#8217;ve noticed unpleasant trends in our most popular &lt;a href="http://thoughtbot.com/community/"&gt;open source projects&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;patches not getting merged&lt;/li&gt;
&lt;li&gt;bugs not getting fixed&lt;/li&gt;
&lt;li&gt;issues going unanswered&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We believe the causes of the problems are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;feature requests, help requests, bug reports, and patches all in the same system&lt;/li&gt;
&lt;li&gt;limited amount of manpower&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We want to do better so we&amp;#8217;re trying a new policy that we believe is helping.&lt;/p&gt;

&lt;h2&gt;Limit what&amp;#8217;s in the queue&lt;/h2&gt;

&lt;p&gt;The Github Issues queue should contain items we can act on and close quickly.&lt;/p&gt;

&lt;p&gt;This means feature and help requests should be submitted to the appropriate mailing list. If you&amp;#8217;re worried about your pull request not being accepted, reach out to us on the mailing list before you start coding.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re trying to keep issues restricted to two kinds:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Pull requests that we can easily merge in&lt;/li&gt;
&lt;li&gt;Bug reports that we can act on&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We&amp;#8217;re always going to be looking at pull requests before issues, meaning the fastest way to get your bug fixed is to submit a pull request that fixes it.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve been doing this on a few projects and the results have been good.&lt;/p&gt;

&lt;p&gt;By keeping the list restricted to items that we can act on quickly, we&amp;#8217;ve brought Paperclip&amp;#8217;s issues count down to 25 from hundreds and Factory Girl&amp;#8217;s issue count has consistently been in the single digits.&lt;/p&gt;

&lt;p&gt;Although this means that we&amp;#8217;ll be closing some issues that might represent real bugs or valuable features, we&amp;#8217;ve found that we can actually move more code through the queue by weeding out the issues that we can&amp;#8217;t act on.&lt;/p&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Pull requests will be addressed first.&lt;/li&gt;
&lt;li&gt;Bugs that we can&amp;#8217;t reproduce or act on quickly will be closed.&lt;/li&gt;
&lt;li&gt;Feature and help requests will be closed with a link to the mailing list.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://robots.thoughtbot.com/post/21919704809</link><guid>http://robots.thoughtbot.com/post/21919704809</guid><pubDate>Fri, 27 Apr 2012 13:30:00 -0400</pubDate><category>open source</category><category>issues</category></item><item><title>Humans Present: An OSS Lifestyle</title><description>&lt;p&gt;I recently sat down with Mike Burns to discuss his operating system and computer setup. Mike uses an entirely Open Source stack.&lt;/p&gt;

&lt;p&gt;We discussed how he got started with this, the current state of running Linux, as well as some of the unique benefits and cool features of doing so.&lt;/p&gt;

&lt;p&gt;We decided to make this special video available for free, and you can &lt;a href="http://workshops.thoughtbot.com/humans-present/oss"&gt;watch it here&lt;/a&gt;.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21850671129</link><guid>http://robots.thoughtbot.com/post/21850671129</guid><pubDate>Thu, 26 Apr 2012 11:33:20 -0400</pubDate><category>OSS</category><category>Linux</category><category>Ruby</category><category>Humans Present</category></item><item><title>What is good code?</title><description>&lt;p&gt;We often discuss the principles we use to write what we consider good code - test-driven development, object-oriented programming, SOLID, DRY, Law of Demeter - the list goes on. Sometimes it&amp;#8217;s useful to remind ourselves of the fundamentals.&lt;/p&gt;

&lt;h2&gt;What is the code for?&lt;/h2&gt;

&lt;p&gt;Code makes an application work for users. Getting tests passing or removing duplication is useful, but the code needs to &lt;strong&gt;be shipped&lt;/strong&gt; so that &lt;strong&gt;users can use it&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;What kind of code is good?&lt;/h2&gt;

&lt;p&gt;Code needs to &lt;strong&gt;work&lt;/strong&gt;. Assuming that as a prerequisite&amp;#8230;&lt;/p&gt;

&lt;p&gt;When code is &lt;strong&gt;easy to understand&lt;/strong&gt;, we can change or extend it faster and are less likely to make a mistake in the process. Readability counts.&lt;/p&gt;

&lt;p&gt;When code is &lt;strong&gt;easy to change&lt;/strong&gt;, we can iterate on user feedback faster.&lt;/p&gt;

&lt;p&gt;When code is &lt;strong&gt;fun to work with&lt;/strong&gt;, we&amp;#8217;re happier. Building software is our full time job. If we go home every day feeling wrung dry, something is wrong with our process.&lt;/p&gt;

&lt;h2&gt;Does good code matter?&lt;/h2&gt;

&lt;p&gt;Yes. Following certain principles can result in shipping products &lt;strong&gt;faster&lt;/strong&gt; with &lt;strong&gt;fewer bugs&lt;/strong&gt; and more &lt;strong&gt;programmer happiness&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;How do our principles result in good code?&lt;/h2&gt;

&lt;p&gt;Test-driven development helps us understand code because we state the reason for each line of application code in the test. It also makes us happy by providing a clear process for working.&lt;/p&gt;

&lt;p&gt;An automated test suite helps us change code because we have an early warning system when we break an existing component. It is fun to work with because we&amp;#8217;re more confident and less fearful.&lt;/p&gt;

&lt;p&gt;Removing duplication helps us read code by introducing semantic concepts and abstracting details. It also helps us change code by reducing the amount of code that needs to be touched for each change.&lt;/p&gt;

&lt;p&gt;SOLID principles create individual components that help us understand code. SOLID helps us change code because components are reusable, swappable, and small.&lt;/p&gt;

&lt;h2&gt;How do our principles result in bad code?&lt;/h2&gt;

&lt;p&gt;Slow or brittle tests make code harder to change. We have to be careful about writing the correct tests and the correct amount of tests.&lt;/p&gt;

&lt;h2&gt;Are we writing good code right now?&lt;/h2&gt;

&lt;p&gt;Code isn&amp;#8217;t good when it&amp;#8217;s tested, DRY, or SOLID. Code is good when it works and we can work with it. When our teammates can understand our code quickly, respond to change, and are relaxed and happy, we&amp;#8217;re writing good code.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21781129461</link><guid>http://robots.thoughtbot.com/post/21781129461</guid><pubDate>Wed, 25 Apr 2012 09:31:00 -0400</pubDate><category>quality</category></item><item><title>FactoryGirl 3.2: so awesome it needs to be released during RailsConf</title><description>&lt;p&gt;FactoryGirl 3.2 brings a slew of new features; while I&amp;#8217;d considered breaking
it all up into 3.2 and 3.3 releases, I decided to bundle them for MORE
AWESOMENESS during RailsConf.&lt;/p&gt;

&lt;p&gt;To install, add (or change) your Gemfile:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem 'factory_girl_rails', '~&amp;gt; 3.2.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, what does FactoryGirl 3.2 give you?&lt;/p&gt;

&lt;h2&gt;Implicitly Call FactoryGirl from Dynamic Attributes&lt;/h2&gt;

&lt;p&gt;Dynamic attributes are attributes you declare on a factory that are defined
with a block to be evaluated every time the factory is run.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;factory :user do
  name { NameGenerator.generate }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There have been a handful of times where I want to share a sequence or create
a record inside of an attribute, but who wants to do this?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sequence(:long_string) {|n| "#{LoremIpsum.generate}#{n}" }

factory :user do
  name { FactoryGirl.generate(:long_string) }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why type out &lt;code&gt;FactoryGirl.&lt;/code&gt; in the block? In FactoryGirl 3.2, you don&amp;#8217;t have
to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sequence(:long_string) {|n| "#{LoremIpsum.generate}#{n}" }

factory :user do
  name { generate(:long_string) }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If it just so happens that if you have a method named &lt;code&gt;generate&lt;/code&gt; on your
object and it&amp;#8217;s colliding with FactoryGirl, you can still use the explicit
&lt;code&gt;FactoryGirl.generate(:long_string)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Deprecate Alternate Syntaxes&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;ve deprecated alternate syntaxes. This means if you&amp;#8217;re using the
&lt;code&gt;object_daddy&lt;/code&gt; or &lt;code&gt;machinist&lt;/code&gt; syntax, you&amp;#8217;ll be urged to upgrade to the
FactoryGirl 2 syntax. Support of the different syntaxes will be removed in
FactoryGirl 4.0.&lt;/p&gt;

&lt;p&gt;Why are we doing this?&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re confident that the FactoryGirl 2 syntax is better than any other syntax
out there. It&amp;#8217;s clear, concise, and is incredibly flexible. It allows for
usage of traits and other benefits we&amp;#8217;ve added to the default syntax.&lt;/p&gt;

&lt;h2&gt;Skip the &lt;code&gt;to_create&lt;/code&gt; Block Easily&lt;/h2&gt;

&lt;p&gt;Certain factories may skip the &lt;code&gt;to_create&lt;/code&gt; block altogether (which normally
calls &lt;code&gt;#save!&lt;/code&gt;). Instead of calling &lt;code&gt;to_create { }&lt;/code&gt; on the factory, you can
now call &lt;code&gt;skip_create&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;factory :user do
  skip_create
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Slim Down &lt;code&gt;initialize_with&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;If you use &lt;code&gt;initialize_with&lt;/code&gt;, you&amp;#8217;ll know you can define your own construction
method instead of just calling &lt;code&gt;new&lt;/code&gt; without arguments. This becomes tedious,
however, when you constantly repeate the build class.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve created a shorthand for calling &lt;code&gt;new&lt;/code&gt; within &lt;code&gt;initialize_with&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;factory :user do
  name "John Doe"

  initialize_with { new(name) }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Other class methods won&amp;#8217;t be supported, but the common case (&lt;code&gt;new&lt;/code&gt;) is
covered for you!&lt;/p&gt;

&lt;h2&gt;Register Custom Build Strategies&lt;/h2&gt;

&lt;p&gt;Ever wish you could call &lt;code&gt;FactoryGirl.json(:user)&lt;/code&gt; to get a JSON
representation of your factory? Now you can. Ever wish &lt;code&gt;attributes_for&lt;/code&gt; would
build your association data instead of ignoring associations altogether?
You can overwrite FactoryGirl&amp;#8217;s implementation of &lt;code&gt;attributes_for&lt;/code&gt; with your
own code.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example of registering your own JSON strategy, decorating the
currently registered create strategy with additional behavior.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class JsonStrategy
  def initialize
    @strategy = FactoryGirl.strategy_by_name(:create).new
  end

  delegate :association, to: :@strategy

  def result(evaluation)
    @strategy.result(evaluation).to_json
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To register the new strategy, run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.register_strategy(:json, JsonStrategy)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once registered, you can refer to it like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FactoryGirl.json(:user)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I recommend digging through FactoryGirl&amp;#8217;s current implementations of &lt;code&gt;build&lt;/code&gt;,
&lt;code&gt;create&lt;/code&gt;, &lt;code&gt;build_stubbed&lt;/code&gt;, and &lt;code&gt;attributes_for&lt;/code&gt;, which use FactoryGirl&amp;#8217;s brand
new &lt;code&gt;register_strategy&lt;/code&gt; interface.&lt;/p&gt;

&lt;h2&gt;Add ActiveSupport::Notifications Instrumentation&lt;/h2&gt;

&lt;p&gt;Now that &lt;a href="http://robots.thoughtbot.com/post/19412394597/factory-girl-hits-3-0"&gt;we&amp;#8217;ve dropped Rails 2
support&lt;/a&gt;,
we can start using some of the awesome features of Rails 3. This includes
&lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;, which uses pub/sub and allows us to track
when factories get run.&lt;/p&gt;

&lt;p&gt;Want to see which factories take longer than half a second to run? If you&amp;#8217;re
using RSpec, you could add this to the &lt;code&gt;before(:suite)&lt;/code&gt; block:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ActiveSupport::Notifications.subscribe("factory_girl.run_factory") do |name, start, finish, id, payload|
  execution_time_in_seconds = finish - start

  if execution_time_in_seconds &amp;gt;= 0.5
    $stderr.puts "Slow factory: #{payload[:name]} using strategy #{payload[:strategy]}"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Any slow factories will be written out to STDERR.&lt;/p&gt;

&lt;p&gt;The other use case that I&amp;#8217;ve wanted for a long time is keeping track of what
factories I&amp;#8217;m creating and the strategies used. Creating a record is obviously
going to be significantly slower than building a stubbed version of it, so
printing out a table of all the factories (and the number of times each
strategy is executed for that factory) should be fairly straightforward. Feel
free to dig into FactoryGirl&amp;#8217;s acceptance tests to see a couple of
straightforward uses.&lt;/p&gt;

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

&lt;p&gt;As we continue to move forward with FactoryGirl, we&amp;#8217;re planning on making it
easier to use &lt;code&gt;initialize_with&lt;/code&gt;. I&amp;#8217;d also love to see a pull request or
example of generating a table of factories and strategy count (much like &lt;code&gt;rake stats&lt;/code&gt;).&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21719164760</link><guid>http://robots.thoughtbot.com/post/21719164760</guid><pubDate>Tue, 24 Apr 2012 13:14:00 -0400</pubDate><category>factory girl</category><category>testing</category><category>rspec</category></item><item><title>Turnip: a tasty Cucumber alternative?</title><description>&lt;p&gt;&lt;img src="https://s3.amazonaws.com/thoughtbot-blog/images/turnip-tasty-cucumber-alternative/vegetables.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve used &lt;a href="http://cukes.info/" title="Cucumber" target="_blank"&gt;Cucumber&lt;/a&gt; heavily and successfully on client work, internal projects, and open source. We also love &lt;a href="https://github.com/rspec/rspec-rails" target="_blank"&gt;RSpec&lt;/a&gt;, so when we heard that &lt;a href="https://github.com/jnicklas/turnip" target="_blank"&gt;Turnip&lt;/a&gt; would give the ability to run Gherkin based integration tests in our RSpec suite it was a no-brainer for us to try it out on a project.&lt;/p&gt;
&lt;h2&gt;Highlights of Turnip&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Integrates directly into your RSpec test suite&lt;/li&gt;
&lt;li&gt;Features and Step definitions live in the spec directory&lt;/li&gt;
&lt;li&gt;No need to maintain two configuration files&lt;/li&gt;
&lt;li&gt;Uses Ruby style symbols instead of regular expressions in step definitions&lt;/li&gt;
&lt;li&gt;No need to write Given/When/Then in the step definitions file&lt;/li&gt;
&lt;li&gt;Speed boost when running unit tests and integration tests together&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We use Cucumber integration tests in &lt;a href="https://github.com/thoughtbot/clearance" target="_blank"&gt;thoughtbot&amp;#8217;s clearance gem&lt;/a&gt;. In the example below I remove Cucumber and replace it with Turnip.&lt;/p&gt;
&lt;h2&gt;Steps used to change from Cucumber to Turnip&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Set up your &lt;code&gt;features&lt;/code&gt; directory inside the &lt;code&gt;spec&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Remove the Given/When/Then&amp;#8217;s from the step definitions&lt;/li&gt;
&lt;li&gt;Replace regular expressions in the step definitions with Ruby style symbols&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cucumber and Turnip use the same Gherkin syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="gherkin"&gt; Scenario: Visitor signs up with valid data&lt;br/&gt;   When I sign up with "email@example.com" and "password"&lt;br/&gt;   Then I should be signed in &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Change the step definitions from Cucumber to Turnip style:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt; # Cucumber step definition&lt;br/&gt; When /^I sign up (?:with|as) "(.*)" and "(.*)"$/ do |email, password| &lt;br/&gt;   visit sign_up_path &lt;br/&gt;   page.should have_css("input[type='email']") &lt;br/&gt;   fill_in "Email", :with =&amp;gt; email &lt;br/&gt;   fill_in "Password", :with =&amp;gt; password &lt;br/&gt;   click_button "Sign up" &lt;br/&gt; end &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="ruby"&gt; # Turnip step definition&lt;br/&gt; step "I sign in with/as :email and :password" do |email, password|&lt;br/&gt;   visit sign_in_path &lt;br/&gt;   page.should have_css("input[type='email']")&lt;br/&gt;   fill_in "Email", :with =&amp;gt; email &lt;br/&gt;   fill_in "Password", :with =&amp;gt; password &lt;br/&gt;   click_button "Sign in"&lt;br/&gt; end &lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Run the test suite&lt;/h2&gt;
&lt;p&gt;An advantage having everything running through RSpec is we get an immediate boost in speed when running the whole test suite. With Cucumber running &lt;code&gt;Rake&lt;/code&gt; will run the RSpec and Cucumber tests (the Rails environment will be loaded twice). With Turnip all tests run through directly through RSpec (the Rails environment is only loaded once).&lt;/p&gt;
&lt;p&gt;We save around 12 seconds when running the entire suite:&lt;/p&gt;
&lt;pre&gt;&lt;code class="terminal"&gt; # Rake running RSpec and Cucumber&lt;br/&gt; ~/Development/clearance_cucumber(master) $ time rake&lt;br/&gt; /Users/training/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S rspec ./spec/controllers/pages_controller_spec.rb ./spec/helpers/application_helper_spec.rb&lt;br/&gt; .&lt;br/&gt;&lt;br/&gt; Finished in 0.10696 seconds&lt;br/&gt; 1 example, 0 failures&lt;br/&gt; /Users/training/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S bundle exec cucumber --profile default&lt;br/&gt; Using the default profile...&lt;br/&gt; .................................................&lt;br/&gt;&lt;br/&gt; 13 scenarios (13 passed)&lt;br/&gt; 49 steps (49 passed)&lt;br/&gt; 0m1.729s&lt;br/&gt; rake 19.97s user 2.71s system 98% cpu 22.960 total&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="terminal"&gt; # RSpec with Turnip&lt;br/&gt; ~/Development/clearance_turnip(master?) $ time rspec&lt;br/&gt; ..............&lt;br/&gt;&lt;br/&gt; Finished in 1.84 seconds&lt;br/&gt; 14 examples, 0 failures, 0 pending&lt;br/&gt; rspec 8.85s user 1.06s system 95% cpu 10.362 total&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Great light-weight solution for anyone already using RSpec&lt;/li&gt;
&lt;li&gt;Step definitions easier to read than their Cucumber counterparts&lt;/li&gt;
&lt;li&gt;Low barrier to entry for developers new to integration testing&lt;/li&gt;
&lt;/ul&gt;</description><link>http://robots.thoughtbot.com/post/21494223079</link><guid>http://robots.thoughtbot.com/post/21494223079</guid><pubDate>Sat, 21 Apr 2012 09:12:00 -0400</pubDate><category>Turnip</category><category>Cucumber</category><category>Integration testing</category></item><item><title>This week in open source</title><description>&lt;h2&gt;factory_girl&lt;/h2&gt;

&lt;p&gt;
There&amp;#8217;s a new version of &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; this week, as usual: 3.1.1 (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/aa81d2f96f4c4c823dc5363c64fe027a6c0209d0" title="Bump version to 3.1.1"&gt;aa81d2f&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
Mark Rushakoff (&lt;a href="http://github.com/mark-rushakoff"&gt;mark-rushakoff&lt;/a&gt;) fixed a typo (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/4682ab0701dc10c94f22e1d6ca5c18f8470999b1" title="fix typo in GETTING_STARTED"&gt;4682ab0&lt;/a&gt;).
Have I mentioned how much I love documentation fixes? Because I do.
&lt;/p&gt;

&lt;p&gt;
Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;) ensured that &lt;code&gt;FactoryGirl.attributes_for&lt;/code&gt; works with &lt;code&gt;has_many&lt;/code&gt; associations (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/50be54564dcb8bd801fa637b852587a947170cfe" title="Test has_many with attributes_for"&gt;50be545&lt;/a&gt;).
He also refactored Strategies to be modules instead of classes, and added an Evaluation &lt;a href="http://en.wikipedia.org/wiki/Facade_pattern"&gt;façade&lt;/a&gt; to make building strategies easier (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/89d5e944d5aeeb29ff5feb34a94c5dccd0d0c796" title="Refactor Strategies

This changes Strategy from a class to a module and removes inheritance.
It introduces an Evaluation facade to make building strategies easier"&gt;89d5e94&lt;/a&gt;).
&lt;/p&gt;

&lt;h2&gt;flutie&lt;/h2&gt;

&lt;p&gt;
&lt;a href="https://github.com/thoughtbot/flutie"&gt;flutie&lt;/a&gt; got some love this
week from Edwin Morris (&lt;a href="http://github.com/ehmorris"&gt;ehmorris&lt;/a&gt;),
who changed values from pixels to ems (&lt;a href="http://github.com/thoughtbot/flutie/commit/fd26ed0406f74e8468c1ebacbc2ffa48f21679dc" title="Merge pull request #35 from ehmorris/master

Changed flutie pixel values to ems"&gt;fd26ed0&lt;/a&gt;) and these new-fangled CSS3 &amp;#8220;rems&amp;#8221;. REMs
are relative to the base element&amp;#8217;s size, not to the parent&amp;#8217;s size
(more &lt;a href="http://snook.ca/archives/html_and_css/font-size-with-rem"&gt;here&lt;/a&gt;).
I wish I&amp;#8217;d had that back in the day.
&lt;/p&gt;

&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;
&lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; got a bunch of bug fixes from Prem Sichanugrist (&lt;a href="http://github.com/sikachu"&gt;sikachu&lt;/a&gt;).

He fixed the content_type validator to allow blanks and nils (&lt;a href="http://github.com/thoughtbot/paperclip/commit/5eed1dcb785e8b42ea7881b1bd822394df6aa3a0" title="Fix content_type validator to support blank/nil

ContentTypeValidator now honors the `:allow_nil` and `:allow_blank` option."&gt;5eed1dc&lt;/a&gt;), ensured that code dealt with the content type, not the MimeType (&lt;a href="http://github.com/thoughtbot/paperclip/commit/3f1d30fb61245b54227f1f997f93df963e89ddef" title="Call #content_type on MimeType object

This will ensure that the content type is a String.

Fixes #805"&gt;3f1d30f&lt;/a&gt;), closed ALL the files (&lt;a href="http://github.com/thoughtbot/paperclip/commit/4f6d482d9823bdf14be5ef70248531fe1e3dc363" title="Close ALL the files

Make sure that we close opened files after we're done with them."&gt;4f6d482&lt;/a&gt;), and removed unused code (yay!) (&lt;a href="http://github.com/thoughtbot/paperclip/commit/02eb72593c0cc508d973af15eb455199ea8b05d0" title="Remove unused code

AttachmentAdapter now handles this for us."&gt;02eb725&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
Sebastien Guignot (&lt;a href="http://github.com/sguignot"&gt;sguignot&lt;/a&gt;) fixed &lt;code&gt;attachment.reprocess!&lt;/code&gt; when using Fog or S3
(&lt;a href="http://github.com/thoughtbot/paperclip/commit/9d1355b5ea8a0fbc999f52ebe477444a789bfbfc" title="Fix attachment.reprocess! when using storage providers fog and s3."&gt;9d1355b&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
Kir Maximov (&lt;a href="http://github.com/kir"&gt;kir&lt;/a&gt;) fixed a problem with an incorrect content_type
(&lt;a href="http://github.com/thoughtbot/paperclip/commit/3e98fc2ea7dd122176b680e5ab5b1100db97af25" title="Fix a problem with incorrect content_type detected with 'file' command for an empty file on Mac"&gt;3e98fc2&lt;/a&gt;).
&lt;/p&gt;

&lt;h2&gt;shoulda-matchers&lt;/h2&gt;

&lt;p&gt;
&lt;a href="https://github.com/thoughtbot/shoulda-matchers"&gt;shoulda-matchers&lt;/a&gt; continues to improve.
Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt; - that&amp;#8217;s me!)
added tests for Rails 3.2 (&lt;a href="http://github.com/thoughtbot/shoulda-matchers/commit/aff28245e798ac07fe96a89f84efbfcc1ba5b4d3" title="Test against Rails 3.2."&gt;aff2824&lt;/a&gt;)
and bumped rspec-rails (&lt;a href="http://github.com/thoughtbot/shoulda-matchers/commit/5baa056f352356ef5cc4b782bcf1d22246f08422" title="Bump rspec-rails."&gt;5baa056&lt;/a&gt;). As ever,
the &lt;a href="https://github.com/thoughtbot/shoulda-matchers/blob/master/NEWS.md"&gt;NEWS file&lt;/a&gt; is the place to watch for updates to functionality.
&lt;/p&gt;

&lt;p&gt;
Aaron Gibralter (&lt;a href="http://github.com/agibralter"&gt;agibralter&lt;/a&gt;) fixed
the &lt;code&gt;ensure_length_of&lt;/code&gt; matcher to check for all possible I18n error
messages (&lt;a href="http://github.com/thoughtbot/shoulda-matchers/commit/0a8e6522cf73f3781fb642bbd996eb3ceef1de7d" title="Use all possible i18n error messages for ensure_length_of_matcher."&gt;0a8e652&lt;/a&gt;),
meaning our internationalized users aren&amp;#8217;t left with false negatives in their
tests.
&lt;/p&gt;

&lt;p&gt;
Victor Pereira (&lt;a href="http://github.com/vpereira"&gt;vpereira&lt;/a&gt;) added the
&lt;code&gt;in_array&lt;/code&gt; method (&lt;a href="http://github.com/thoughtbot/shoulda-matchers/commit/e40e2cb1acf33c8716db9fecf37131aa625282bf" title="looks like its working"&gt;e40e2cb&lt;/a&gt;)
to the &lt;code&gt;ensure_inclusion_of&lt;/code&gt; matcher, meaning you can do
&lt;code&gt;it { should ensure_inclusion_of(:attribute).in_array(%w[cat dog])&lt;/code&gt; now.
&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21450611413</link><guid>http://robots.thoughtbot.com/post/21450611413</guid><pubDate>Fri, 20 Apr 2012 16:49:00 -0400</pubDate><category>This Week In Open Source</category><category>Factory Girl</category><category>Flutie</category><category>Paperclip</category><category>Shoulda Matchers</category></item><item><title>Meet thoughtbot at Railsconf 2012</title><description>&lt;p&gt;We&amp;#8217;ve had an abnormally warm Winter and Spring in Boston this year, but thoughtbot likes it EVEN HOTTER so we&amp;#8217;re going south to Austin. As a bonus, &lt;a href="http://railsconf2012.com/"&gt;Railsconf&lt;/a&gt; is there. If you&amp;#8217;d like to meet a real, live thoughtbot employee, here&amp;#8217;s who you can expect to see there:&lt;/p&gt;

&lt;div style="float: left; margin-right: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/cpytel.png"/&gt;&lt;/div&gt;

&lt;p&gt;Chad is the CEO of thoughtbot. You may recognize him from books like &lt;a href="https://workshops.thoughtbot.com/products/1-backbone-js-on-rails"&gt;Backbone.js on Rails&lt;/a&gt; or movies like &lt;a href="https://workshops.thoughtbot.com/products/4-humans-present-tmux"&gt;Humans Present: tmux&lt;/a&gt;. Chad&amp;#8217;s been focusing on workshops and other learning materials. If you have an idea for a book, screencast, or workshop, come find Chad. I&amp;#8217;m sure he&amp;#8217;d love to hear about it!&lt;/p&gt;

&lt;div style="clear: left"&gt;&lt;/div&gt;

&lt;div style="float: right; margin-left: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/mjankowski.png"/&gt;&lt;/div&gt;

&lt;p&gt;Matt is our COO. He&amp;#8217;s into &lt;a href="http://vimeo.com/40614203"&gt;movies&lt;/a&gt;, too, and he&amp;#8217;s the mastermind behind such open source works as &lt;a href="https://github.com/thoughtbot/flutie"&gt;flutie&lt;/a&gt; and &lt;a href="https://github.com/thoughtbot/pacecar"&gt;pacecar&lt;/a&gt;. If you have an idea for a web app or want to discuss your favorite kind of trail mix, look for Matt.&lt;/p&gt;

&lt;div style="clear: right"&gt;&lt;/div&gt;

&lt;div style="float: left; margin-right: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/jferris.png"/&gt;&lt;/div&gt;

&lt;p&gt;Joe isn&amp;#8217;t always the CTO of thoughtbot, but when he is&amp;#8230;actually, he always is. Joe is the original author of &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; and &lt;a href="https://github.com/thoughtbot/capybara-webkit"&gt;capybara-webkit&lt;/a&gt;. He&amp;#8217;ll be working on those, as well as his &lt;a href="http://www.youtube.com/watch?v=oHg5SJYRHA0"&gt;secret project&lt;/a&gt; with Mike Burns. If you&amp;#8217;re interested in any of those things, come find Joe.&lt;/p&gt;

&lt;div style="clear: left"&gt;&lt;/div&gt;

&lt;div style="float: right; margin-left: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/jyurek.png"/&gt;&lt;/div&gt;

&lt;p&gt;Jon is one of the co-founders of thoughtbot. He wrote the &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; gem. You may have heard of it. It&amp;#8217;s kind of a big deal. He also wrote the excitingly-named &lt;a href="https://github.com/thoughtbot/cocaine"&gt;cocaine&lt;/a&gt;. If you want to help out with paperclip, find Jon.&lt;/p&gt;

&lt;div style="clear: right"&gt;&lt;/div&gt;

&lt;div style="float: left; margin-right: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/mburns.png"/&gt;&lt;/div&gt;

&lt;p&gt;Mike is a long time thoughtbotter and just moved to Stockholm. He loves open source, Swedish slang, and the Oxford comma. If you want to discuss open source or pull requests, just follow your nose to the&amp;#8230;well, look for Mike.&lt;/p&gt;

&lt;div style="clear: left"&gt;&lt;/div&gt;

&lt;div style="float: right; margin-left: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/jclayton.png"/&gt;&lt;/div&gt;

&lt;p&gt;Josh likes testing more than he likes food or oxygen. He&amp;#8217;s also the maintainer of &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt;. If you want to yell about testing or factory_girl, Josh is ya boi.&lt;/p&gt;

&lt;div style="clear: right"&gt;&lt;/div&gt;

&lt;div style="float: left; margin-right: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/borenstein.png"/&gt;&lt;/div&gt;

&lt;p&gt;Ben is a speaker and conference enthusiast. If you&amp;#8217;re at a conference, look for Ben&amp;#8217;s name. He&amp;#8217;s probably on the speaker list under &amp;#8220;v&amp;#8221; for &amp;#8220;Vim.&amp;#8221; If you want to talk about speaking, &lt;a href="https://workshops.thoughtbot.com/products/2-vim-for-rails-developers"&gt;Vim&lt;/a&gt;, or travel, you can&amp;#8217;t do much better than Ben.&lt;/p&gt;

&lt;div style="clear: left"&gt;&lt;/div&gt;

&lt;div style="float: right; margin-left: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/prem.png"/&gt;&lt;/div&gt;

&lt;p&gt;Prem is a frequent contributor to Rails (you may have heard of it), &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt;, and other open source libraries. If you have a strange problem with paperclip, the asset pipeline, or Rails in general, look for Prem; I bet he can tell you what&amp;#8217;s happening.&lt;/p&gt;

&lt;div style="clear: right"&gt;&lt;/div&gt;

&lt;div style="float: left; margin-right: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://thoughtbot.com/images/people/gabe.jpg"/&gt;&lt;/div&gt;

&lt;p&gt;Gabe brings humor, vocabulary, and Star Wars to thoughtbot. Gabe wrote &lt;a href="https://github.com/thoughtbot/kumade"&gt;kumade&lt;/a&gt; and can probably tell you how to pronounce it. He&amp;#8217;s also a frequent contributor to open source, and has been focusing on &lt;a href="https://github.com/thoughtbot/shoulda-matchers"&gt;shoulda&amp;#8217;s matchers&lt;/a&gt; lately. For a good time, find Gabe.&lt;/p&gt;

&lt;div style="clear: left"&gt;&lt;/div&gt;

&lt;div style="float: right; margin-left: 15px; height: 147px; margin-bottom: 15px; overflow: hidden"&gt;&lt;img src="http://media.tumblr.com/tumblr_m2sai5waQn1qzocnw.jpg"/&gt;&lt;/div&gt;

&lt;p&gt;Joel just started at thoughtbot after several years as a mercenary. He&amp;#8217;s a chatty one, so if you&amp;#8217;d like to talk about anything - Ruby, Rails, Sass, beer, dogs, beer for dogs, or the economic viability of dogs as laptop stands - find him. He&amp;#8217;s the one with the big head.&lt;/p&gt;

&lt;div style="clear: right"&gt;&lt;/div&gt;

&lt;p&gt;Hope to see you there! If not, look for us at one of our other &lt;a href="http://thoughtbot.com/events/"&gt;upcoming events&lt;/a&gt;.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21437334428</link><guid>http://robots.thoughtbot.com/post/21437334428</guid><pubDate>Fri, 20 Apr 2012 11:21:00 -0400</pubDate><category>railsconf</category></item><item><title>thoughtbot in Bangkok</title><description>&lt;p&gt;Sawasdee krub!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/jayunit"&gt;Jason Morrison&lt;/a&gt; is in Bangkok for a bit, and wants to talk shop and buy you drinks.&lt;/p&gt;

&lt;p&gt;Come talk about testing in JavaScript-heavy web apps at the BKK Rails-JS meetup this Friday, April 20 at 19:00.  Check the &lt;a href="http://www.meetup.com/rails-programming-in-thailand/events/59193902"&gt;Meetup page for the full address and map&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Afterwards, come out and have a beer on us.  All local Ruby, Web development, Web design, and startup folks are welcome!  We&amp;#8217;re meeting for drinks after the meetup at &lt;a href="https://www.facebook.com/Mulligans.Restaurant.and.Bar.Bangkok"&gt;Mulligan&amp;#8217;s Restaurant and Bar&lt;/a&gt;
on Soi 11 - here are some &lt;a href="http://maps.google.com/maps?saddr=6th+Floor,+The+Pride+-+Asoke+Towers,+Sukhumvit+21+(Soi+Asoke),+Khlongtoey+Nua,+Wattana,+Bangkok+10110,+Thailand+(Glowfish)&amp;amp;daddr=13.743901,100.556694&amp;amp;hl=en&amp;amp;sll=13.739312,100.5761&amp;amp;sspn=0.055861,0.057335&amp;amp;geocode=Fde80QAdqXX-BSFl6lnnJBJONg%3BFR230QAdll_-BQ&amp;amp;oq=glowfish+bangkok&amp;amp;mra=pd&amp;amp;t=m&amp;amp;z=16"&gt;Google Map directions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you can&amp;#8217;t make it that day, get in touch with Jason on &lt;a href="http://twitter.com/jayunit"&gt;Twitter&lt;/a&gt; or by &lt;a href="mailto:jmorrison@thoughtbot.com"&gt;email&lt;/a&gt;.&lt;/p&gt;</description><link>http://robots.thoughtbot.com/post/21322624918</link><guid>http://robots.thoughtbot.com/post/21322624918</guid><pubDate>Wed, 18 Apr 2012 09:13:00 -0400</pubDate></item></channel></rss>

