Managing multiple Heroku accounts with heroku-accounts plugin

This example assumes your pre-existing heroku account will be heroku.work and you are adding a new account heroku.personal.

It also describes how to move an app from one to the other, for example, if you have hit your 25-app max and are creating a new account and want to move some of your side projects and experimental apps out of your main account.

  1. You probably need to use the plugin to create BOTH your old and your new accounts, eg, if you had one to start with you can’t just add a new heroku.personal, you need to create heroku.work to replace your old one
  2. You’ll need to reassign your old apps to your heroku.work
  3. if you are moving an app, don’t assign the app to heroku.personal (using heroku accounts:set personal) until after you transfer the app using the heroku sharing commmand as described https://devcenter.heroku.com/articles/transferring-apps

So the steps you probably need are:

  1. Install the heroku-account plugin
  2. Go to heroku.com and create your new account (if you don’t have a second account already)
  3. run heroku accounts:add work --auto to create a new heroku.work account to replace your old default account (so use the same credentials you’ve been using all along). You ALSO need to upload your new key to heroku: heroku keys:add ~/.ssh/identity.heroku.work.pub
  4. run heroku accounts:add personal --auto to create a new heroku.personal account (eg use your new credentials for your new heroku account). You ALSO need to upload your new key to heroku: heroku keys:add ~/.ssh/identity.heroku.personal.pub
  5. For each app, cd to the project root then run heroku accounts:set work (all that does it setup git to use your heroku.work, which is (unin this example) the same heroku account you’ve been using all along, only now it’s called heroku.work.
  6. If you want to move an app from heroku.work to heroku.personal,
    (a) add the new heroku account as a collaborator with heroku sharing:add
    (b) in your local directory, switch the app to heroku.personal using heroku accounts:set personal
    (c) transfer** the app from the old account to the new account using heroku sharing:transfer then
    (d) remove the old email address collaborator (if you want to) using heroku sharing:remove

** Note the heroku link I provided says there are special requirements to move an app with any paid resources. Generally, remove the paid resoures, then add them back later, or have support do it.

Getting RSpec, Postgres, DatabaseCleaner to play nicely together

Did a quick benchmark last week to find the optimal way to configure Rspec on our projects that use Postgres and DatabaseCleaner

One of our test suites takes 3.5 minutes to run when we do NOT use DatabaseCleaner, the default rspec setup:

# spec_helper.rb
#config.use_transactional_examples = false 
#config.before(:suite) do 
# DatabaseCleaner.strategy = :transaction 
# DatabaseCleaner.clean_with(:truncation) 
#end 
#config.before(:each) do 
# DatabaseCleaner.start 
#end 
#config.after(:each) do 
# DatabaseCleaner.clean 
#end

When we enabled database cleaner (with default .strategy = :transaction), the test still took 3.5 minutes, but we got lots of warnings:**WARNING: there is already a transaction in progress
NOTICE: there is no transaction in progress
**

# spec_helper.rb
 #config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

However, when we changed the .strategy to :trunctation, it eliminated the warnings, but slowed the tests down to 8 minutes!# spec_helper.rb

#config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

The best results were to leave the strategy set to :transaction, but set config.use_transactional_examples = false. That yielded a runtime of about 3.5 minutes.

# spec_helper.rb
 config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

We used the following addition spec to verify that the database was being cleaned. (run this with –order default )

#dbclean_spec.rb

require "spec_helper" 
Refer.destroy_all 
describe Refer do 
it "has none to begin with" do 
  Refer.count.should == 0 
end 
it "has one after adding one" do 
Refer.create 
Refer.count.should == 1 
end 
it "has none after one was created in a previous example" do Refer.count.should == 0 
end 
end

Rspec gotcha – instance variables are not cleared between ‘get’s

It seems that (unlike when controller methods are invoked via browser) if you do two consecutive get’s with rspec, instance variables are not cleared with each get, so data crossover is possible.

Here’s a failing test, showing that a variable set in ‘vartest1′ is still present when another controller method ‘vartest2′ is run:

Controller methods:

def vartest1 
  @this_var = "foo" 
  render :text => @this_var
end 
def vartest2 
  render :text => @this_var # should be EMPTY! 
end

Rspec controller spec (note: we use render_views so the views are rendered in the spec)

describe "instance variable crossover example", :focus => true  do 
  describe "THIS PASSES put each get in separate contexts" do 
    it "vartest1 outputs foo" do 
      get "vartest1" 
      response.body.should include("foo") 
    end 
    it "vartest2 does NOT output foo" do 
      get "vartest2" 
      response.body.should_not include("foo") 
    end 
  end 
  describe "THIS FAILS put both gets in SAME context" do 
    it "should not crossover controller instance varables" do 
      get "vartest1" 
      response.body.should include("foo") 
      get "vartest2" 
      response.body.should_not include("foo") # THIS FAILS 
    end 
  end 
end

Rspec results:

instance variable crossover example 
THIS PASSES 

put each get in separate contexts 
vartest1 outputs foo 
vartest2 does NOT output foo 
THIS FAILS 

put both gets in SAME context should not crossover 
controller instance varables (FAILED - 1)

>

What’s happening in the failing test is that when rspec does get ‘vartest1′ the controller method set an instance variable to ‘foo’, and when rspec does get ‘vartest2′ the instance variable (which should be nil) is still set, so the test fails.