I want to isolate and spec methods that are shared by controllers,
and live in application.rb.
Whereas I usually also provide examples in individual controllers
that use these methods, not necessarily all the edge cases and I’d
like to isolate the examples.
This is the approach I’m taking (thanks to bryanl for suggestions and
Parked at Loopia). WDYT?
This example is a before_filter that finds the Account specified in
params[:account_id], which may be used by any number of other
controllers in my app. As you can see, the filter is still getting
spec’d and has pending examples.
application.rb
class ApplicationController < ActionController::Base
…
def find_account
@account = Account.find_by_id( params[:account_id])
# TODO: check account status is suspended, closed, different
flash message?
return( error_redirect_gracefully( “Account not found”)) unless
@account
end
…
end
application_controller_spec.rb
require File.dirname(FILE) + ‘/…/spec_helper’
ActionController::Routing::Routes.draw do |map|
map.connect ‘foos/:action’, :controller => ‘foos’
end
class FoosController < ApplicationController
end
describe FoosController, “account authorization” do
before do
FoosController.class_eval do
define_method(:foo) {
find_account # this is the method being tested
}
end
end
it “should find_account from params” do
acnt = mock_model(Account)
Account.should_receive(:find_by_id).with(‘99’).and_return(acnt)
get :foo, :account_id => “99”
assigns[:account].should == acnt
end
it “should redirect gracefully if no account specified” do
controller.stub!(:error_redirect_gracefully)
controller.should_receive(:error_redirect_gracefully).with
( “Account not found”)
acnt = mock_model(Account)
Account.should_receive(:find_by_id).with(nil).and_return(nil)
get :foo
end
it “should not find accounts that are suspended”
it “should flash different message for accounts that are suspended”
it “should not find accounts that are closed”
end