rSpec, controller, restful route problem

I’m trying to wrap my brain around bdd, and it’s not going nearly as
well as I’d like. I’ve been struggling with it for a few weeks now, and
had been doing relatively well at first, while I was doing models. Now
I’m trying to understand how to spec controllers, and it’s got me a bit
befuddled. I’ve been reading what I can find on the internet and have
also watched the PeepCode screencasts. I have come a bit further in the
past few days, but I’ve hit a small snag with named routes that I can’t
quite figure out. To make matters worse, I’m implementing REST for the
first time as well. So I’m trying to get a grip on BDD and REST at the
same time.

Here’s what I have (applicable code only):

in the spec:

require File.dirname(FILE) + ‘/…/model_helper’

describe WelcomeController do
include ModelHelperMethods # for valid_user_hash

it ‘POST :log_in should log user in with correct email/password’ do
email = valid_user_hash[:email]
password = valid_user_hash[:password]
user = mock_model(User)
user.stub!(:id).and_return(1)
User.should_receive(:authenticate).with(email,
password).and_return(user)
post :log_in, {:email => email, :password => password} # this is
line 86 in the error
session[:user_id].should == user.id
response.should be_redirect
end
end

in the controller:

class WelcomeController < ApplicationController
def log_in
user = User.authenticate(params[:email], params[:password])
if user
session[:user_id] = user.id
redirect_to users_path(user) # this is line 15 in the error
else
flash[:error] = ‘Invalid login.’
redirect_to :action => :index
end
end
end

in routes.rb

map.resource :users

When I run the spec, I’m getting the error

NoMethodError in ‘WelcomeController POST :log_in should log user in with
correct email/password’
You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.to_sym
(eval):17:in users_path' /Users/phillip/dev/projects/cashflow/app/controllers/welcome_controller.rb:15:inlog_in’
./spec/controllers/001_welcome_controller_spec.rb:86:
script/spec:4:

I believe it has something to do with the call to users_path and it
trying to figure out the id of the object. That’s why I have the
user.stub!(:id) line in there. If I change

users_path(user)

to

users_path

in the controller, the error goes away. But since I’ve done a singleton
map.resource, I’m redirecting to the show method of the users
controller, and that requires an id, or so I believe.

Two questions, one specific and one more general:

  1. What’s the cause of the error and how can I resolve it? [Okay, that
    was two questions there]
  2. Am I one the right track as far as bdd-ing contollers?

Peace,
Phillip

Any thoughts greatly appreciated!

Peace,
Phillip

cause of the error:
no, a singleton resource doesn’t need an id, since there is (should be)
only a single thingy of it around (either only one exists at all or like
in case of logins you keep the necessary id in the session)
this nil.to_sym is very typical for that kind of error with the
path_helpers

if for some reason you need the id anyway use:
users_path(:id => user)
but since you store the thing in session[:user_id] that’s not necessary

otherwise your spec code looks fine
just i would stub the authenticate thing instead of the id and return a
User out of the fixtures, otherwise you’ll end up stubbing every single
attribute for more complex use-cases
(but we’re not making that much use of the mock/stub)

Thorsten M. wrote:

cause of the error:
no, a singleton resource doesn’t need an id, since there is (should be)
only a single thingy of it around (either only one exists at all or like
in case of logins you keep the necessary id in the session)
this nil.to_sym is very typical for that kind of error with the
path_helpers

Thanks for the input, Thorsten. Maybe I’m not understanding the
singleton resource correctly. I was under the impression that if you
have no need of listing out the resources, you should use the singleton.
So in my case, the users controller is for the currently logged in user.
This controller will never list all users (that will be in an admin
controller). Is this the correct understanding? If so, maybe using the
plural form of user was a mistake. If I plan on singleton mapping,
maybe I should use the singular

user_controller

?

Okay, so if I have session[:user_id], I don’t need an id passed into
:show, user_path with no parameter would generate the correct route?
Something like

/user/show

?

Wow. If it’s really that simple, how’d I miss it? sigh

otherwise your spec code looks fine
just i would stub the authenticate thing instead of the id and return a
User out of the fixtures, otherwise you’ll end up stubbing every single
attribute for more complex use-cases
(but we’re not making that much use of the mock/stub)

The only point of stubbing :id was I thought it was needed by Rails in
users_path(user). I mistakenly thought the error was referring to the
fact that it looked for a method :id and couldn’t find it (nil to sym).

Thanks again!
Phillip

This controller will never list all users (that will be in an admin
controller). Is this the correct understanding?

yes

If so, maybe using the
plural form of user was a mistake. If I plan on singleton mapping,
maybe I should use the singular

user_controller

no, your controllers are always pluralized, rails will handle that