You’re reading Signal v. Noise, a publication about the web by Basecamp since 1999. Happy !

Nick

About Nick

A short, sturdy creature fond of drink and industry.

Some of my most beloved products are those that make ME amazing at something that matters to me, even if I am kicking and screaming and swearing at the product while using it. Of course if I am kicking and screaming and swearing, I’m obviously having a compromised experience… One that might prevent me from producing something wonderful. But I’ll still take a poor UX that makes me truly better at something I care about, than the beautiful, artful, exquisite “Who Cares” product.


Kathy Sierra, responding to If VCs Understood UX.

“The UNIX System: Making Computers More Productive”, from 1982. Brian Kernighan, Dennis Ritchie, and Ken Thompson talk about what UNIX is, how to use it, and show off some live coding too. Thanks to Tony Arcieri for sharing this!

Go code spelunking with me in the all new Basecamp! You’ll see how we build Rails apps at 37signals and learn several exciting Ruby and JavaScript patterns that you can use. There’s also a writeup of some of the best chunks from the talk to check out.

Our API docs are now hosted on Github

Nick
Nick wrote this on 7 comments

Since the all new Basecamp’s API launch, our Developerland site was feeling a bit dated without GitHub’s wonderful styling and syntax highlighting. Spring is a time for cleaning, and that includes API documentation!

Our API docs are now hosted on GitHub. If you’re looking to get started with our APIs, you can head to 37signals/api and check out our authentication guide or our brand guidelines.

Each 37signals product now has its own API documentation repo:

My favorite new feature of the API documentation is that each endpoint now has its own permalink. For example, here’s Highrise’s Get deal endpoint.

Found a typo or have a clarification for the API documentation? Feel free to open a pull request on any of the repos. If you spot a bug or have a question for us, opening a support ticket will be the fastest way you can get an answer.

Three quick Rails console tips

Nick
Nick wrote this on 15 comments

I was bouncing around the Rails API documentation yesterday, and I noticed a few rails console tricks I haven’t seen before. There’s been plenty of posts about irb and Rails before, but I’m hoping you’ll learn something new here. The following console samples were taken with Basecamp Next on Rails version 3.2.3.

Dive into your app

Running the app method in rails console gives you an integration session instance, so you can use it just like when you’re a normal integration test for Rails.

>> app.class
=> ActionDispatch::Integration::Session

Generating routes was always a hassle. What module did I need to include again? Did you remember to set the default_url_options? Stop googling and just use app:

>> app.project_path(Project.first)
=> "/projects/130349783-with-attachments"

It can make requests inside of your app as well:

>> app.get "/735644780/projects/605816632-bcx.atom"
=> 200

>> app.response.body
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xml:lang=\"en-US\"  ...

Check out ActionDispatch::Integration::Session and ActionDispatch::Integration::RequestHelpers to see what else this object can help you with.

Try out a helper

Getting a console session bootstrapped with Rails’ helpers is also a pain, which helper can fix for you! You could also use it to play with building HTML tags, or any existing Rails helper that ActionView knows about.

>> helper.truncate("Testing", length: 4)
=> "T..."

>> helper.link_to "Home", app.root_path
=> "<a href=\"/\">Home</a>"

One gotcha with helper is using instance variables inside of helper methods. Yes, I’m aware this is a Bad Idea™ with helpers in general, but I haven’t worked in a single Rails app without one. Here’s a small example of a method with one:

def title_tag(title = nil)
  if @project.present? && title.nil?
    content_tag :title, @project.name
  elsif @project.present?
    content_tag :title, "#{@project.name}: #{title}"
  else
    content_tag :title, title
  end
end

We can use our old friend Object#instance_variable_set to violate a core principle of OOP and let us try this helper out in the console:

>> helper.title_tag "Testing!"
=> "<title>Testing!</title>"

>> helper.instance_variable_set :@project, Project.first
=> #<Project id: 130349783, ...

>> helper.title_tag
=> "<title>With attachments!</title>"

>> helper.title_tag "Posts"
=> "<title>With attachments!: Posts</title>"

Dealing with a helper that uses params is also not straightforward. However, we can trick ActionView into listening to us with a tiny hack. This is the console, after all! Let’s say we have this helper method:

def javascript_debugging_options
  if params[:javascript_debugging] == "enabled"
    { debug: true, digest: false }
  else
    {}
  end
end

Usually ActionView needs an entire ActionDispatch::Request from the controller to figure out what parameters came in from the user. We can trick it with a little OpenStruct instead:

>> helper.controller = OpenStruct.new(params: {})
=> #<OpenStruct params={}>

>> helper.javascript_debugging_options
=> {}

>> helper.controller = OpenStruct.new(params: {javascript_debugging: "enabled"})
=> #<OpenStruct params={:javascript_debugging=>"enabled"}>

>> helper.javascript_debugging_options
=> {:debug=>true, :digest=>false}

Where does that method come from?

Hunting down the exact location of a given method isn’t always easy. Luckily, Ruby can point you in the right direction with Method#source_location:

>> Project.instance_method(:trash).source_location
=> ["/Users/qrush/37s/apps/bcx/app/models/project.rb", 90]

Whoa! You’ll get back an array with the full path of where the method was defined along with that method’s line number in the file.

I’ve used this when looking for code buried inside of gems as well. Let’s try it on app:

>> app.method(:get).source_location
=> ["/Users/qrush/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-7d95b814583b/actionpack/lib/action_dispatch/testing/integration.rb", 32]

This tip has saved me from an immense amount of source diving. Try it out!

More tips

Looking for more tips? JEG2 gave a neat talk at RailsConf about some of the hidden parts of Rails you might not know about. If you have some of your own, please share!

Code Spelunking in the all new Basecamp

Nick
Nick wrote this on 14 comments

Over the past few months I’ve learned an immense amount from the all new Basecamp codebase. This year for RailsConf, I was able to show off some new (and old!) patterns in the codebase along with some neat libraries that we’ve put to serious use for our customers. The slides are over at SpeakerDeck if you’d like to see them all, and hopefully a video of the presentation will be up soon!

Here’s a few choice sections from the talk, and plenty of great links to check out in the meantime:

Continued…

The On-Call Programmer

Nick
Nick wrote this on 39 comments

My dad is a firefighter and fire captain in Niagara Falls, NY. When I told him I had on-call duty for my new job, he was beyond excited. After relaying stories of waking in the middle of the night to head into the hall and getting overtime from his buddies that didn’t want to wake up for work were sick, I had to explain that it’s a different type of action for me. I face issues of a less life-threatening variety, but there’s still plenty of virtual fires to extinguish. Here’s a primer for what being an on-call programmer means at 37signals.

The routine

On-call programmers are rotated around every 2 weeks, and all 8 programmers currently get their fair share of customer support and interaction. Usually we have 2 to 3 programmers on-call on a given week. Support issues from email and Twitter are routed through Assistly, and handled by our awesome support team.

If there’s an issue they can’t figure out, we get a ping in our On Call room in Campfire to check out a certain issue:

These issues range in severity, and they might look like:

Continued…

All hands, battlestations!

Nick
Nick wrote this on 107 comments

Perhaps it’s my inner engineer, but seeing behind the scenes of workshops, be they real or digital, always fascinates me. Maybe that’s why How it’s Made is so compelling. The show proves that there’s more than just the end product: the workspace and the process that surround the product that turn out to be just as interesting than what was produced.
A recent discussion internally about using standing desks got me thinking: what do our workspaces look like? Does something about them inspire our craft and code? Is it the lack of clutter, or the general disarray of your everyday stuff that helps ideas flow better? Is your space a blank canvas? A workbench? A retreat?
Here’s what some of our workspaces looked like yesterday and today. Feel free to share yours!


Jamis’ desk


Jason F’s desk


Jeff’s desk

Continued…

Kicking the tires: My trial month

Nick
Nick wrote this on 28 comments

I saw some questions on David’s last posts about remote work and hiring asking how we evaluate potential employees. Racing metaphors aside, tossing new developers on real projects is a time honored tradition here, and one that we haven’t written yet about “what” exactly happens along with the “why”. Here’s how my trial month went, and what I learned.

Giordano's pizza and a pint of 312, can't get more Chicago than this meal.

The first week

I’ve never been to Chicago, outside of O’Hare airport. I have terrifying memories of that airport, so I was cautious to visit. I once left an a320 Pocket Retro Emulator in a seat pocket while deboarding, and didn’t realize it until soon before my connection was to leave. I sprinted back through 2 terminals to find the plane had already left for Nashville. I hope someone else is enjoying a slightly buggy version of Tetris Attack. My first week at 37signals went much better than this experience.

The first week in the office was great. Getting up to speed was a breeze: I fired Ruby and Rails up on a fresh box with rbenv and ruby-build. After cloning down a few repositories, and the usual run-around of “what passwords/sites do I need access to”, I was tossed into the fray of our support queue.

I was introduced to Assistly, which we use for customer support. I have to say, our support team is awesome to work with. We typically have 3 developers rotating in on-call, usually on a weekly or so basis. Here’s basically what on-call for a 37signals developer looks like:

  1. Support is stuck with an issue, and our set of internal tools isn’t helping.
  2. An issue is called out for developers to look at.
  3. Cue hacking montage as we dive into that specific product and various gems’ codebase to find the problem. This usually involves a trip into our server cluster to look for logs, find emails that didn’t process or hook up to a Rails console and hit the database.
  4. If it’s a bug, try to squash it. At least make sure we know about it in GitHub Issues.
  5. Ship it! Bug fixes and more are logged through Champagne, our internal change tracking tool. Champagne is in charge of publishing our Changes page.

Sometimes there’s not always an easy fix, or it’s a deeper issue. Typically we’ll discuss these over in Campfire to begin and see if anyone’s seen it before. This usually escalates into kicking off or contribute to ongoing discussion in Basecamp about how to solve the root problem.

Back to remote

On my first week back in Buffalo, I was tasked with creating a fresh application we’ve needed for a while. The workflow for discussing changes and features was pretty much what I expected: Here’s a list of things to accomplish, let’s see what we can get done in a week. The timeboxed aspect of the project was definitely new to me, and I think it was a great factor in focusing on what needed to get done instead of what could be done. I’m very new to a product-focused company, and this was a great way to be dropped into the environment where it’s really the customer and user experience that comes first and foremost.

After that second week remote, I went back to on-call. I really enjoy the balance of the on-call work. It’s usually split 50/50 between helping customers with issues blocking their work, and improving our infrastructure and apps. There’s lots of dirt to sweep up, including deep bugs that need investigating and apps/gems that need a fresh coat of Ruby or Rails.

Back in Buffalo, this is Bidwell Parkway.

Top score!

One thing I learned really quickly was that our users are creative: If you give them the ability to do anything, they will do everything! I found this out the hard way when we got a support issue for an extremely broken Basecamp page. After some investigation, I found out that Basecamp todos allow HTML tags, and they forgot to close one. After a fruitless hunt for why this behavior existed, I shipped a fix to strip out HTML tags and clean up ones that might cause the page to break.

The flood of support issues started almost immediately. Apparently a lot of users customize their todos with colors, images, and more. Suddenly, they couldn’t, and it was my fault. This might be a new personal top score for breaking things at a new job. I reverted the fix and deployed once again, and we apologized to those users.

Keep kickin’

I’m still getting used to remote work, but I’m enjoying the greater freedom and flexibility so far. The discipline of working near so many distractions is something I’ll be working on for a while.

This is my second official month being a signal, and I’m definitely still learning about our infrastructure and the internals of our products. I have to say though, it’s been a lot of fun and I’m excited for what’s next. If you have any other questions about the trial month experience let me know!

2011 Year-End Campfire Feature Blowout!

Nick
Nick wrote this on 21 comments

All features must ship! There’s been some improvements to your 2011 Campfire lately, and it’s time you came on down and tried them out.

Per-Room Permissions

First up, we’ve added per-room permissions settings. Previously, permissions could only be changed on a specific person, and it was tedious to click around to each person once you added a room. Now, right after a room is added, you can immediately change who has access to it in one place.

Tons of Emoji

We’ve got some hot new imports: More emoji. “More” is an understatement. How about, 495 emoji? There’s an an entire cheat-sheet so you can educate yourself on proper Emoji usage as well.

New Sounds

There’s also been a few new sounds added lately. Try out ”/play secret”, ”/play tada”, ”/play nyan” at some point!

Animated GIF Thumbnails

One of my favorite parts of Campfire is how it plays GIFs. Perhaps this isn’t the most productive way to communicate, but it sure is awesome. If you upload a GIF to Campfire now, it will resize and animate the thumbnail as well. Pretend the above image is animated, I’m only good at finding GIFs, not making them.

We’re in Campfire every day at 37signals, and we love making little improvements to make your experience better. Hopefully these brighten up your Friday!