On Sep 7, 2010, at 6:01 AM, Cameron Caine wrote:
> In almost all my controllers I scope everything through an @account
> model object, e.g:
>
> #teams_controller.rb
> def new
> @team = @account.teams.build
> end
>
> So far I have got passing specs using these:
>
> describe TeamsController do
> let(:account) { Account.new }
>
> before(:each) do
> Account.stub!(:find_by_subdomain!).and_return(account)
> account.stub!(:teams)
> end
>
> describe "GET new" do
> let(:team) { Team.new("account_id" => account.id) }
>
> before(:each) do
> account.teams.should_receive(:build).and_return(team)
> end
>
> it "assigns @team to a new scoped instance of Team" do
> get :new
> assigns[:team].should eq(team)
> end
>
> it "renders the new template" do
> get :new
> response.should render_template("new")
> end
> end
> end
>
> I am interested to know if this is best practice for scoping everything
> through an existing model object.
That''s a lot of noise for two simple examples. I''d either just
use AR (no stubs) or add a build_team method to Account. I also prefer to keep
message expectations (should_receive) in the examples that specify the
expectation. In the spec above "renders the new template" would fail
for the wrong reason if the other example failed. I also like to keep the let()
statements near each other since they''re eval''d lazily (makes
it easier to find them).
That would lead me to something like:
describe TeamsController do
let(:account) { stub_model(Account).as_null_object }
let(:team) { stub_model(Team) }
before(:each) do
Account.stub(:find_by_subdomain!) { account }
end
describe "GET new" do
it "assigns @team to a new scoped instance of Team" do
account.should_receive(:build_team) { team }
get :new
assigns(:team).should eq(team)
end
it "renders the new template" do
get :new
response.should render_template("new")
end
end
end
HTH,
David