Recently, I created thoughtbot Foursquare lists to help out-of-town workshops students find hotels, coffee shops, and bars.
In the process, I noticed Foursquare has an “act as” feature:

It lets you, well, “act as” another user:

It caught my eye because I had recently implemented a similar feature for a client. I named it with slightly more aplomb: “masquerading.”
Here’s what we wanted:
Given a user exists with email "bobby@example.com" and name "Bobby Tables"
And an admin with email "admin@example.com"
When I sign in as "admin@example.com"
Then I should see "Bobby Tables"
When I follow "Masquerade" within the "bobby@example.com" row
And I should see "Now masquerading as Bobby Tables"
And I should see "Hi Bobby" within the navigation
When I follow "Stop Masquerading"
Then I should be on the admin page
The context is that I’m an admin. A user is on the phone with me right now with support questions. I quickly find their account and see the app through their eyes.
In app/views/admin/users/index.html.erb:
<% @users.each do |user| %>
...
<%= link_to 'Masquerade', new_user_masquerade_path(user) %>
<% end %>
In config/routes.rb:
resources :users, only: [:edit, :update] do
resources :masquerades, only: [:new]
end
Nothing crazy so far.
In app/controllers/masquerades_controller.rb:
class MasqueradesController < ApplicationController
before_filter :authorize, :authorize_admin
def new
session[:admin_id] = current_user.id
user = User.find(params[:user_id])
sign_in(user)
redirect_to home_path, notice: "Now masquerading as #{user.name}"
end
def destroy
user = User.find(session[:admin_id])
sign_in :user, user
session[:admin_id] = nil
redirect_to admin_users_path, notice: "Stopped masquerading"
end
end
The masquerading controller actions are restricted to admins by before filters provided by the authentication library and the developer.
The create action switches the user ids and signs in as the user. Put your mask on because we’re masquerading.
When the customer support session is over, we’ll want to return to the admin views. In app/views/shared/_navigation.html.erb:
<% if masquerading? %>
<%= link_to "Stop Masquerading", "#" %>
<% end %>
In application_controller.rb:
def masquerading?
session[:admin_id].present?
end
helper_method :masquerading?
We define that in a controller, then expose it as a helper method to the views, so that we can alter the authorize_admin method that is used as a before_filter:
In application_controller.rb:
def authorize_admin
current_user.admin? || masquerading?
end
That way, the MasqueradesController stays protected, even when you’re signed in as a non-admin user during a masquerade.
We aren’t using this technique on our own products right now. One concern is that on many apps, the customer’s view could reveal sensitive data. Airbrake, for example, would require at minimum asking the person “may I act as your account?”
Heroku’s ZenDesk support form does something similar: “May we access your application code? Check here to allow us to clone and/or inspect your code for debugging purposes.”
However, I like the idea of providing better support by viewing the app as our customers do.
Written by Dan Croak.
The Boston Globe recently raised the bar for responsive web design.
Please allow me to lower it.
For our playbook, I wanted to provide a pleasant reading experience for desktop and mobile web browsers. However, I’m lazy.
My answer to “what’s the simplest thing that could possibly work?” was a single-column layout with a maximum width that would also fit mobile devices:
margin: 0 auto;
max-width: 480px;
That makes the User experience section look like this on a desktop…

… and like this on an iPhone…


No media queries or other additional resizing tricks except for messing with the viewport a little and hiding the browser bar when possible:
It also means fewer conditional statements, which we aim to eliminate.
max-width isn’t supported in IE6 but we don’t support IE6.
Responsive web design is already very elegant in its simplicity. My thought is that for use cases like landing pages and content sites, it can be even simpler using a thin, vertical one-column layout.
I’ve heard landing pages convert better using a vertical, single-column layout. The premise is anything that distracts the user, including navigational elements and sidebars, will hurt conversion.
For the playbook, the average time on the site is 4:40. So, I’m feeling pretty good that the layout is working well to focus readers on the content.
My guess is other content sites like McSweeney’s Internet Tendency do similarly well keeping its readers engaged on their 400px-wide desktop version:

With the addition of one line of code…
<meta name="viewport" content="width=device-width">
…they could make their mobile web version immediately readable without zooming instead of presenting a garish request to download software for “optimized” reading:

It’s so easy, even a lazy man can do it.
Written by Dan Croak.
I was recently tasked with this story:
Background:
Given I go to the sign up page
And I fill in "Email" with "new@example.com"
And I fill in "Password" with "password"
Scenario: Visitor signs up and does not want email
When I press "Sign up"
Then email service is not notified "new@example.com" signed up
Scenario: Visitor signs up and wants email
When I check "Please email me"
And I press "Sign up"
Then email service is notified "new@example.com" signed up
The email service in question was internal, accessible via an HTTP API, and did not have a Ruby client library.
So, I had to write and test my own. The usual approach would involve using a HTTP stubbing library like Sham Rack or Artifice. I decided to try something different and see how it felt.
First, I needed an interface that I could test:
Then /^email service is notified "([^"]*)" signed up$/ do |email|
EmailService.notifications.should include(email)
end
Then /^email service is not notified "([^"]*)" signed up$/ do |email|
EmailService.notifications.should_not include(email)
end
I’m re-using a pattern (“store data in a simple array for easy state-based testing”) we’ve used before for Javascript integration testing Mixpanel.
So I have the start to an EmailService interface. I thought I wanted it invoked as part of an after_save callback on the User model, so here’s that spec:
describe User, 'who opts into email' do
subject { build(:user, email_opt_in: true) }
before do
EmailService.stubs(:notify)
subject.save
end
it 'notifies EmailService' do
EmailService.should have_received(:notify).with(subject.email)
end
end
describe User, 'who does not opt into email' do
subject { build(:user, email_opt_in: false) }
before do
EmailService.stubs(:notify)
subject.save
end
it 'does not notify EmailService' do
EmailService.should have_received(:notify).never
end
end
This is the stubbing and spying technique and uses RSpec, mocha, and bourne.
My thought process was that I needed an active verb, notify to invoke when the user is created, but that will store the invocation in a notifications array that the Cucumber step definition needs to check state (I don’t want to stub, spy, or mock in an integration test).
So, making the user spec pass isn’t bad:
require 'email_service/notifier'
class User < ActiveRecord::Base
after_create do
if email_opt_in?
EmailService.notify(email)
end
end
end
Now, the EmailService can be spec’ed. We already had John Nunemaker’s HTTParty as a dependency in the app, and I only had to make one HTTP POST, so I knew I would be re-using HTTParty’s interface.
describe EmailService::Notifier, '#post' do
subject { EmailService::Notifier }
let(:email) { 'new-signup@example.com' }
before do
subject.stubs(:post)
subject.new(email).post
end
it 'POSTs to email service with API_KEY and given email' do
subject.should have_received(:post).with(
subject::URL, query: { api_key: subject::PARAMS, email: email }
)
end
end
What I care about here is that during the one POST the app has to make, that the parameters are correct. This is close to hitting the live service as I’m willing to get without making an HTTP request.
I had an internal debate with myself while writing it over whether this is “stubbing the system under test” (considered bad practice). I decided “no” because despite the subject being stubbed, the system under test is actually the EmailService::Notifier#post method.
The stubbed and spied method is also mixed in from HTTParty, so I feel clean with this approach.
Making it pass:
require 'httparty'
module EmailService
class << self
attr_accessor :notifications
end
def self.notify(email, live = false)
if Rails.env.production? || live
Notifier.new(email).post
else
self.notifications << email
end
end
class Notifier
include HTTParty
API_KEY = 12345
URL = 'http://emailservice.example.com'
def initialize(email)
@url = URL
@email = email
end
def post
self.class.post(@url, query: { api_key: API_KEY, email: @email })
end
end
end
EmailService.notify, which is used by the User model.EmailService.notify with the live flag so I can invoke it from the Rails console on production or staging when testing or debugging.This almost takes longer to describe than to code but I’m curious what people think about this style of writing an API client with test, staging, and production environments in mind. How do you do things differently?
Written by Dan Croak.
The first time you push a git branch to a remote, you have to be explicit the first time:
git push origin my-branch-name
Every time after that, a simple git push will work fine. But there’s a ~/.gitconfig setting that will let you just git push without needing that initial explicitness:
[push]
# Push current branch even if you've never pushed it before
default = current
You might want to take a look at my gitconfig for more tips.
Ever needed to interact with a Javascript confirm() dialog? Here’s how to do it in Selenium from Cucumber:
When /^I confirm the dialog$/ do
page.driver.browser.switch_to.alert.accept
end
When /^I cancel the dialog$/ do
page.driver.browser.switch_to.alert.dismiss
end