We're currently hiring Developers and Designers in Boston and New York.
Find out more and apply on our jobs page.

Mar 05 2010

Write Fewer Regular Expressions

Posted by lolconomy

Oh man Cucumber is awesome but why do I have to write regular expressions? It’s always like:

Then /^show me the emails$/ do
  puts ActionMailer::Base.deliveries.map do |email|
    email.subject
  end.join("\n")
end

Then /^I should see the "([^"]+)" link once$/ do |link_title|
  assert_select '.deal_title', :text => link_title, :count => 1
end

Then /^I should see "([^"]+)" for "([^"]+)" (.*) field in the response XML$/ do |value, xpath, field|
  @parsed_response.xpath("#{xpath}[@#{field}='#{value}']").should_not be_empty
end

Ugh that’s so ugly and it feels like I’m writing awk or Perl, and while I love me a good awk script it really does not belong near my beautiful Ruby. (They’re so ugly that they broke the syntax highlighter!)

Well you probably know how to replace the first one with a string:

Then 'show me the emails' do
  puts ActionMailer::Base.deliveries.map do |email|
    email.subject
  end.join("\n")
end

But what of our parameterized steps?

I had a vision, a vision of a string with printf-like escapes inside a string. I was pumped and ready to make a patch so I cloned the source off github and started looking through the classes (this was about 11PM). That’s when I discovered that this was done for me by the wonderful scientists at the Cucumber Research Institute! We can re-write those steps like this:

Then 'I should see the "$link_title" link once' do |link_title|
  assert_select '.deal_title', :text => link_title, :count => 1
end

Then 'I should see "$value" for "$xpath" $field field in the response XML' do |value, xpath, field|
  @parsed_response.xpath("#{xpath}[@#{field}='#{value}']").should_not be_empty
end

Here’s how it works: the Cucumber step parser for Ruby turns every string into a regular expression, to reduce it to a previously-solved problem. On the way it translates $foo into (.*). That’s it!

if String === regexp
  p = Regexp.escape(regexp)
  p = p.gsub(/\\\$\w+/, '(.*)') # Replace $var with (.*)
  regexp = Regexp.new("^#{p}$") 
end

This, obviously, is not going to rid the world of regular expressions overnight. Take these two for examples:

Given /^(?:|I )am on (.+)$/ do |page_name|
  visit path_to(page_name)
end

Given /^the user with email "([^\"]*)" is (not )?an admin$/ do |email, status|
  user = User.find_by_email!(email)
  user.admin = status.blank?
  user.save!
end

But these steps are few and far between.

Only you can reduce your regexps. Replace them with strings, today!

We're currently hiring Developers and Designers in Boston and New York.
Find out more and apply on our jobs page.

Mar 02 2010

Where to stay when you visit us

Posted by lolconomy

Hey! You!

You’re a hip Rails dev looking to expand your knowledge and hang out in Boston!

So come take our Rails training class April 7th, 8th, and 9th!

Map of hotels around thoughtbot

And while you’re here you could stay in these sweet hotels:

They do not come with totally deck sneakers and wild haircuts but they are near places that can help.

If you’re looking for something more casual may I suggest:

These two actually has a hard time filling up so you can often get some last-minute less expensive deals*. We recommend checking them first (especially if you’re looking last-minute!).

* This is a rumor we’ve heard and passed along from someone who heard it and passed it along.

Transportation

Cars are for the suburbs; we have the first perfectly hateable public transit system here in the city! When using Google Maps to find your way around you can select “by public transit” to see that much of the time the walking directions are more fun and faster than the T.

To get downtown from Logan Airport you have a few options: taxi, subway, or Silver Line. The taxi is undoubtly the most expensive and fastest option (about 20 minutes).

The Silver Line is a bus that runs from the airport terminal to South Station, which is a few blocks away from our office. You can take the Red Line (subway) from South Station to Park St Station (our office) if you want, or you can walk and enjoy the pun that Summer St turns into Winter St. Funny guys.

You can also catch the 22 Logan Shuttle (bus) to Airport Station, and take the Blue Line (subway) to Government Center; from there you can walk down Tremont St or jump on the Green Line (subway) to Park St Station.

You can’t miss us.

We're currently hiring Developers and Designers in Boston and New York.
Find out more and apply on our jobs page.

Feb 18 2010

Hoptoad Notifier: Rack and automatic Metal support

Posted by jasonmorrisontb
If you’re not sending your application errors to our hosted service Hoptoad, take a few minutes and try it out for free today!

The newest version of the official Hoptoad Notifier, 2.2, was released to Gemcutter today, and brings with it support for Rack, automatic notification of exceptions occurring in Rails Metal endpoints, and some Rails 1.2.6 fixes.

Rack support

From the README:

In order to use hoptoad_notifier in a non-Rails rack app, just load the hoptoad_notifier, configure your API key, and use the HoptoadNotifier::Rack middleware:

require 'rack'
require 'hoptoad_notifier'

HoptoadNotifier.configure do |config|
  config.api_key = 'my_api_key'
end

app = Rack::Builder.app do
  use HoptoadNotifier::Rack
  run lambda { |env| raise "Rack down" }
end

This makes the notifier usable in any Rack-based application, including Merb or Sinatra. The README also includes an example for using the Rack notifier in Sinatra.

Atticus mans a very fashionable wine rack

Automatic metal notification

The Hoptoad::Rails module also uses this Rack support to provide automatic Hoptoad notification from within your Rails Metal applications:

if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
  ::Rails.configuration.middleware.insert_after 'ActionController::Failsafe',
                                                HoptoadNotifier::Rack
end

This means that any exceptions during requests handled by metal endpoints in your Rails application will automatically be sent to Hoptoad, just like requests that are handled by ActionController.

Atticus does metal

You can read about the other changes in 2.2 (including fixes for Rails 1.2.6) in the CHANGELOG.

We're currently hiring Developers and Designers in Boston and New York.
Find out more and apply on our jobs page.

Feb 16 2010

The More You Know: custom time descriptions

Posted by dancroak

Fred asked if we could shorten the “about 1 month ago” text in an information-rich table that was squeezing the created_at data.

wrapping onto multiple lines

I’m not familiar with the i18n API beyond supporting internationalization in Clearance. Therefore, it took me mildly by surprise when I learned that you can override distance_in_words with the i18n API (and, by extension, time_ago_in_words).

Speaks English real good

i18n is the right tool to solve a problem like this even in an English-only application. A quick change to config/locales/en.yml, however, and we’re done:

en:
  datetime:
    distance_in_words:
      less_than_x_seconds:
        other: '1 minute'
      half_a_minute: '1 minute'
      less_than_x_minutes:
        one: '1 minute'
      x_minutes:
        one: '1 minute'
        other: '{{count}} minutes'
      about_x_hours:
        one: '1 hour'
        other: '{{count}} hours'
      about_x_months:
        one: '1 month'
        other: '{{count}} months'
      about_x_years:
        one: '1 year'
        other: '{{count}} years'
      over_x_years:
        one: 'over 1 year'
        other: 'over {{count}} years'

The result:

fits on one line

You can see other options in svenfuchs/i18n.