Blog

Saturday, July 30, 2011

Gotcha with testing expected params with Bourne/Mocha in Rails Controller

This is something that always trips me up using Bourne (a fork of Mocha, a Ruby mocking and stubbing library) to test expected params in a Rails Controller. Take this spec:

context "with filter" do
  before do
    get :index, :search => {:brand_id => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with('brand_id' => '1')
  end
end

This test fails, but what if I tried this:

context "with filter" do
  before do
    get :index, :search => {:brand_id => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with(:brand_id => '1')
  end
end

This will fail. Note I am now checking the parameters passed using symbols for the keys. I receive the following error:


Failure/Error: SearchResult.should have_received(:latest).with(has_entry(:brand_id => '1'))
     expected exactly once, not yet invoked: SearchResult(id: integer, search_id: integer, body: text, source: text, url: string, created_at: datetime, updated_at: datetime).latest(has_entry(:brand_id => '1'))

This is because the params that are passed to the controller have keys as strings rather than symbols:

{'brand_id' => '1'}

So what's the solution? I could actually use HashWithIndifferentAccess which gives access to a Hash using strings or symbols for keys. This is in fact the class that is used for the params hash in the controller:

it 'should find latest search results' do
    SearchResult.should have_received(:latest).with(HashWithIndifferentAccess.new(:brand_id => '1'))
  end

Or, as a standard practice, when dealing with parameters passed to a controller within a spec, always use strings:

context "with filter" do
  before do
    get :index, 'search' => {'brand_id' => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with('brand_id' => '1')
  end
end

I think this is a lot simpler, cleaner. Interestingly, I didn't pass the brand_id as a Fixnum:

before do
    get :index, 'search' => {'brand_id' => 1}
  end

I would have got the same error:

Failure/Error: SearchResult.should have_received(:latest).with('brand_id' => 1)
     expected exactly once, not yet invoked: SearchResult(id: integer, search_id: integer, body: text, source: text, url: string, created_at: datetime, updated_at: datetime).latest('brand_id' => 1)

As the brand_id is present in the hash as a String, not a Fixnum.

Upgrade RVM and Ruby 1.9.2p290

I've been a little lazy and haven't updated my RVM installation (version 1.1.3, now 1.6.31) for a while and have been stuck on Ruby 1.9.2p0. This morning I upgraded, here's what I did:

$ rvm get head
$ rvm reload
$ rvm install 1.9.2-p290
$ rvm upgrade 1.9.2-p0 1.9.2-p290

Hmm… Got some errors, here's the output:

Are you sure you wish to upgrade from ruby-1.9.2-p0 to     ruby-1.9.2-p290? (Y/n): y
Migrating gems from ruby-1.9.2-p0 to ruby-1.9.2-p290
Are you sure you wish to MOVE gems from ruby-1.9.2-p0 to ruby-1.9.2-p290?
This will overwrite existing gems in ruby-1.9.2-p290 and remove them from ruby-1.9.2-p0 (Y/n): y
Moving gemsets...
Moving ruby-1.9.2-p0 to ruby-1.9.2-p290
Making gemset ruby-1.9.2-p290 pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@brandizzle to ruby-1.9.2-p290@brandizzle
Making gemset ruby-1.9.2-p290@brandizzle pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@default to ruby-1.9.2-p290@default
Making gemset ruby-1.9.2-p290@default pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@global to ruby-1.9.2-p290@global
Making gemset ruby-1.9.2-p290@global pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@peters-guide to ruby-1.9.2-p290@peters-guide
Making gemset ruby-1.9.2-p290@peters-guide pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@refinery to ruby-1.9.2-p290@refinery
Making gemset ruby-1.9.2-p290@refinery pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@shoedazzle to ruby-1.9.2-p290@shoedazzle
Making gemset ruby-1.9.2-p290@shoedazzle pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@spree to ruby-1.9.2-p290@spree
Making gemset ruby-1.9.2-p290@spree pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@sproutcore to ruby-1.9.2-p290@sproutcore
Making gemset ruby-1.9.2-p290@sproutcore pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@storeworks to ruby-1.9.2-p290@storeworks
Making gemset ruby-1.9.2-p290@storeworks pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Do you wish to move over aliases? (Y/n): y
Updating alias default to point to ruby-1.9.2-p290@default
Do you wish to move over wrappers? (Y/n): Y
Do you also wish to completely remove ruby-1.9.2-p0 (inc. archive)? (Y/n): Y
ERROR: Error running 'rvm remove ruby-1.9.2-p0 --archive --gems' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//rvm.remove.log
Successfully migrated ruby-1.9.2-p0 to ruby-1.9.2-p290
Upgrade complete!

Note that I opted to move over aliases, wrappers and completely remove my old ruby-1.9.2-p0.

Looking at the gemset.pristine.log I had the following errors for each gemset:

[2011-07-30 09:08:04] rvm gemset pristine # under ruby-1.9.2-p290@brandizzle
/Volumes/Data/Users/nicholas/.rvm/scripts/functions/environment: line 235: rvm: command not found

So for each gemset I executed the following:

rvm gemset pristine 

This seemed to work fine. Next, I checked out the errors in rvm.remove.log:

[2011-07-30 09:08:32] rvm remove ruby-1.9.2-p0 --archive --gems # under ruby-1.9.2-p0
/Volumes/Data/Users/nicholas/.rvm/scripts/functions/environment: line 235: rvm: command not found

Looks like the remove of my old 1.9.2 install failed, so I ran it manually:

rvm remove ruby-1.9.2-p0 --archive --gems 

Boom! Everything is updated and working.

Thursday, July 28, 2011

Basic Heroku addons I always use for production websites


heroku addons

cron:daily
custom_domains:basic
logging:expanded
memcache:5mb
newrelic:standard
pgbackups:auto-month
sendgrid:basic
shared-database:5mb

Tuesday, July 26, 2011

Git: Push a local branch to a remote master

git push heroku yourbranch:master 
Credit Heroku

Run a SQL query within Ruby on Rails

ActiveRecord::Base.connection.execute(your_sql_statement)

Ruby Script to Duplicate a S3 Bucket


Thanks Josh Nussbaum.

Please note this blog is no longer maintained. Please visit CivilCode Inc - Custom Software Development.