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

Feb 09

Hoptoad scheduled downtime Wednesday February 10 at 3:00pm ET

Posted by jasonmorrisontb

Hoptoad will have scheduled downtime on Wednesday February 10 at 3:00pm ET. We are aiming for a maximum of 1 hour of downtime, but expect the actual downtime to be 15 to 20 minutes.

We’re moving onto the Engine Yard Cloud so that we can improve Hoptoad performance and have greater flexibility in our architecture. After the move, we’ll be able to more easily isolate the error notification service endpoint, utility and batch processing functions, and the user-facing website so that high activity in one of these areas does not affect the usability of the other components.

Cloud Frog

Do your apps have errors that you don’t know about until your users email you? Do you use an exception notifier that emails you every time your app has an error? Send your application errors to Hoptoad - get a free account and add Hoptoad to your app in 5 minutes flat.

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

Jan 27

Hoptoad's notifier now available in convenient gem form

Posted by jferris

Frog in a box

The hoptoad_notifier library has traditionally been a Rails-only plugin. Although the majority of the code was not Rails-specific, the internals of the notifier were not decoupled such that the notifier parts could be loaded without also using the Rails-specific catcher parts.

However, at the end of last year, we released a newly refactored hoptoad_notifier plugin that targetted our brand new v2 server API, as well as sporting improved separation of concerns. Starting with version 2.0 of hoptoad_notifier, the notifier code was usable outside of Rails applications.

The quest for a reusable notifier

Unfortunately, it was still packaged as a Rails plugin, which made it difficult to build libraries based on it or use it in non-Rails applications. A number of people have requested a gem version of the library, and we’re happy to provide one. However, we thought it would be a good idea to explain some of the reasons that we were unable to provide a gem sooner.

The folly of two distribution methods

For a while, we tried packaging the notifier as both a plugin as a gem. Although using the gem version had some advantages, it made it much more difficult for us to identify problems that our users were experiencing. There was a different set of common problems for plugin users and gem users, and without access to our users’ codebases or servers, it was often impossible to debug anything without a game of 20 questions that was frustrating to our users.

In the end, we decided that our users would be happier with fewer possibilities to debug. When we released version 2 of the notifier, we decided to wait until the gem was fully supported, and then switch to that entirely. However, before restricting our users to the gem, we wanted to make sure that the installation and configuration process remained seamless, and there were a few issues with Rails and gems that stood in our way.

The pitfalls of Rails and gems

There are a few things that “just work” in plugins that Rails treats very differently in gems. Rails does not automatically load rake tasks from gems, and Capistrano only looks for recipes in plugins. Additionally, gems could potentially be installed on the system, vendored in the vendor/gems directory, or both. To make matters worse, handling of gems has changed substantially through the history of Rails, and we don’t want to abandon our users that aren’t on the latest and greatest Rails.

Generators (sort of) to the rescue

We decided to add one more step to the install process: running the “hoptoad” generator. This has the added benefit of generating an appropriate configuration file and automatically running the integration test for new users. However, generators in gems suffer from similar problems to rake tasks: old versions of Rails only look for generators in gems ending in “_generator,” and some newer versions won’t load generators from vendored gems.

What’s a toad to do?

In the end, we decided to add an automated test to make sure that the catcher, notifier, and installer continue to work on various versions of Rails. We wrote up some Cucumber features that go through the whole process, starting from a freshly built hoptoad_notifier gem, continuing with installing and configuring the notifier in a freshly generated Rails application, and ending with receiving a test notification. The test runs several different scenarios (vendored gems, installed gems, and so on) and runs for every supported version of Rails. If you’d like to see this in action, check it out on Github.

What’s in it for me?

As a user of Hoptoad, this means two things:

If you’re using a Rails application, the installation and upgrade process has changed slightly:

# in config/environment.rb
config.gem 'hoptoad_notifier'

# from your Rails root:
$ rake gems:install
$ rake gems:unpack GEM=hoptoad_notifier
$ script/generate hoptoad --api-key your_key_here

If you’re writing a library or non-Rails application, using hoptoad_notifier is now much easier:

require 'rubygems'
require 'hoptoad_notifier'
HoptoadNotifier.configure do |config|
  config.api_key 'your_key_here'
end
HoptoadNotifier.notify(:error_message => 'Krakow')

So go ahead and “gem install hoptoad_notifier,” and send all your Rails (or not) errors to the toad!

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

Jan 20

MyGem.configure block

Posted by dancroak

We recently made some enhancements to Clearance. One of those was to replace a manual process of the developer setting constants in their Rails environment files with a configuration block that could be used in config/initializers/clearance.rb.

I liked the way Hoptoad does it and wanted to implement the same pattern:

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

So let’s implement:

module Clearance
  class << self
    attr_accessor :configuration
  end

  def self.configure
    self.configuration ||= Configuration.new
    yield(configuration)
  end

  class Configuration
    attr_accessor :mailer_sender

    def initialize
      @mailer_sender = 'donotreply@example.com'
    end
  end
end

We have a configure class method that stores a Configuration object inside the Clearance module.

Anything application developers can set from their configure block is an attr_accessor on the Configuration class.

side note - I used the name mailer_sender to match the Devise API.

So now, we can have a config/initializers/clearance.rb:

Clearance.configure do |config|
  config.mailer_sender = 'donotreply@example.com'
end

Easy for the application developer to understand. Cleaner implementation internally:

Clearance.configuration.mailer_sender

As an added bonus, in the library’s tests, we can set configuration attributes without worrying about undefining constants:

Clearance.configuration.mailer_sender= 'new.email@example.com'

Yay.

spirograph

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

Jan 18

8 Simple Rules for Dating My Business: Our Hiring Process

Posted by chadpytel

Our hiring process has been continually refined over the 7 years we’ve been in business to reflect the needs of our team, the lessons we learned along the way, and the changes in the candidates we see.

In this post I’ll go through our hiring process, note places where we’ve seen changes, and hopefully answer some common questions.

It’s worth noting that we’re currently actively searching for both a new Designer and Developer.  If you’re interested, I hope you’ll get in touch.

The History

When we first started out, we were smaller and we didn’t focus exclusively on Ruby on Rails.  So our decision-making process for hiring new people was necessarily different.

At first, I’d basically talk to people a few times, meet them in person, and make the decision about whether to hire or not largely on my own, with consultation from Jon when he was available or when I thought it was particularly necessary.

Now that we’re a bit larger and have a well qualified team we involve the rest of the team in the decision making process to ensure that the people we’re hiring have been agreed to by the team.

We do this because having a cohesive team is incredibly important to our overall culture and attitude.  We want to make sure that everyone will work well together to uphold our high standards.

Also, because we used to use a variety of different technologies our requirements were in some ways more loose, and in some ways more strict.  For example, we didn’t use Java on every project, but that meant that if you were being hired as a Java programmer you’d be working with particular clients on particular projects.  You needed to be able to perform well on those specific projects as well as just demonstrate a technical aptitude.

Back then, we also didn’t have the standards and practices we do now.  We didn’t write automated tests, we used many different frameworks, and we weren’t as particular about the projects we took or the kinds of people we hired.

When we switched to Rails, that was our chance to push the reset button on our standards, including our hiring process.

We established that we would do test driven development, run continuous integration, more strictly follow agile methodologies and hold ourselves to a higher standard.  Necessarily, our hiring practices needed to change to match this.

The Current Process

We ask all development candidates to provide us with information about them and a code sample as part of the initial contact.

After reviewing the code sample and their resume and cover letter, we decide whether we’ll do an initial interview with them.

We used to only ask for a code sample after the initial interview and before the second, technical interview was already scheduled.  However, after a few candidates who would have never gotten through to the technical interview had we seen their code first got through, we decided to ask for this and evaluate it up front.

The initial interview is either by phone, video chat, or in person based on their capability and location.  This initial conversation isn’t technical at all.  Its a chance for us to hear in their own words what their experience is and for us to give some insight into thoughtbot, how we operate and where we’re going as a company.

If this initial interview goes well, then we’ll ask the candidate to do a technical interview with other members of the team (same for design candidates).

The technical interview is usually with two people, we review the sample code (or designs) ask them questions on that, and also ask a series of more technical questions.

We have some technical questions that we’ve come up with and revised over time.  With these questions we try to judge core technical competency rather than just being up to date on the latest plugin or buzz-word (though those are also things we consider).

For candidates who we think might be a good fit after the technical interview, we then invite them to come and work in our office for a week, for which we pay them for their time.

This week-long trial, particularly for remote candidates, is as much for us as it is for them.  We want to make sure that everyone involved is a good fit before the big decision.

During this week-long trial we try to get them interacting with each member of the team and try to give them as accurate a picture as possible of what its like to work at thoughtbot.

Things We Can Improve

As with any process, this one continues to evolve, and there are certainly areas that we can improve.

We used to do a really terrible job of keeping track of potential candidates throughout the process, particularly in notifying people of a no-hire decision.  We now do a less terrible job by using Wufoo to take submissions in a standardized form and Highrise to keep track of people, but we could stand to do an even better job with this.

As I mentioned above, our technical interview questions try to strike a balance and identify strong core technical competency rather than just being able to spout of the latest buzzwords or familiarity with a specific plugin.  However, our questions could probably try to work with more practical knowledge rather than computer science topics.  We’ve recently made some changes here already, and focus more on the sample code they’ve submitted, but we continue to refine.

Like all things we do, we also don’t want our hiring process to be a burden.  We are a small team with lots of responsibilities.  If anything we do becomes a burden on anyone involved it’s not working.

One problem we were having was that the number of low quality candidates we were receiving took a lot of time to screen.  To help with this problem, we’ve started to avoid posting to job boards right away.  Instead, we’ve focused more on trying to find qualified candidates through networking and directed advertising to more focused groups.  Then, if  we haven’t found someone through those circles, doing a broader search.

Our goal for our hiring process is to find people that will be a good fit with the team and who will do a great job with the kind of work we do.  Our process has been honed over time to hopefully become a useful tool in identifying the right kinds of people for us.

I’d love to hear what you’ve liked or disliked about either side of the hiring table you’ve been on.