Nil Object in Signup form

Since I upgraded from Rails 1.8.6 to 2.3.5, I just noticed that I can no
longer add new users through my Signup page.
Here is the error:
NoMethodError in UserController#signup

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.save!

/work/store/app/controllers/user_controller.rb:6:in `signup'

Here is my Controller, line 6 is @user.save!:
def signup
  return unless request.post?
    @user.save!
    redirect_back_or_default(:controller => 'grapher', :action =>
'index')
    flash[:notice] = "New User Successfully Created"
    rescue ActiveRecord::RecordInvalid
    render :action => 'signup'
end

Here is my form:
<% form_for :user do |f| -%>
<label for= "first_name">First Name</label>
<%= f.text_field :first_name %>

<label for= "last_name">Last Name</label>
<%= f.text_field :last_name %>

<label for= "user_login">Login</label>
<%= f.text_field :login %>

<label for= "user_email">Email</label>
<%= f.text_field :email %>

<label for= "user_password">Password</label>
<%= f.password_field :password %>

<label for= "user_password_confirmation">Confirm Password</label>
<%= f.password_field :password_confirmation %>
<%= submit_tag 'Sign up' %>
<% end -%>

Here are my request parameters when I get the error:
Request
Parameters:

{"user"=>{"password_confirmation"=>"password",
"first_name"=>"john",
"last_name"=>"smith",
"login"=>"jsmith",
"password"=>"password",
"email"=>"jsmith@email.com"},
"commit"=>"Sign up"}

It seems to me that I'm passing the correct params so I don't understand
why I'm getting a "nil object" error?

Do you have a before filter where you set the @user variable? It’s complaining that the @user variable is nil.

No, I don't have any before statements in my controller, here is what it
looks like:

class UserController < ApplicationController

public
  def signup
  return unless request.post?
    @user.save!
    redirect_back_or_default(:controller => 'grapher', :action =>
'index')
    flash[:notice] = "New User Successfully Created"
    rescue ActiveRecord::RecordInvalid
    render :action => 'signup'
end

How do you assign the user params to the @user object?

Try adding before the @user.save! line the following

@user = User.new params[:user]

When I add that line to the top of my "def signup" code in the
controller,
I no longer get my signup form, instead, I get this message instead of
seeing all the fields in my signup form:

NoMethodError in UserController#signup
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]

jack

Since I upgraded from Rails 1.8.6 to 2.3.5, I just noticed that I can no
longer add new users through my Signup page.
Here is the error:
NoMethodError in UserController#signup

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.save!

/work/store/app/controllers/user_controller.rb:6:in `signup'

Here is my Controller, line 6 is @user.save!:
def signup
return unless request.post?
@user.save!

The error is telling you that @user is nil. There does not appear to
be any code setting this up, Are you sure it ever worked?

redirect_back_or_default(:controller => 'grapher', :action =>
'index')
flash[:notice] = "New User Successfully Created"

This code also looks odd, how will it get to the flash line after the
redirect? Though I may be missing what redirect_back_or_default is
supposed to do.

rescue ActiveRecord::RecordInvalid

More odd looking code, or did the syntax for rescue change
dramatically with Rails 2 from Rails 1

render :action => 'signup'
end

Here is my form:
<% form_for :user do |f| -%>
<label for= "first_name">First Name</label>
<%= f.text_field :first_name %>

<label for= "last_name">Last Name</label>
<%= f.text_field :last_name %>

<label for= "user_login">Login</label>
<%= f.text_field :login %>

<label for= "user_email">Email</label>
<%= f.text_field :email %>

<label for= "user_password">Password</label>
<%= f.password_field :password %>

<label for= "user_password_confirmation">Confirm Password</label>
<%= f.password_field :password_confirmation %>
<%= submit_tag 'Sign up' %>
<% end -%>

Here are my request parameters when I get the error:
Request
Parameters:

{"user"=>{"password_confirmation"=>"password",
"first_name"=>"john",
"last_name"=>"smith",
"login"=>"jsmith",
"password"=>"password",
"email"=>"jsmith@email.com"},
"commit"=>"Sign up"}

What action does the log show this is going to?

It seems to me that I'm passing the correct params so I don't understand
why I'm getting a "nil object" error?

I think because @user is not getting setup.

Colin

When I add that line to the top of my "def signup" code in the
controller,
I no longer get my signup form, instead, I get this message instead of
seeing all the fields in my signup form:

You'd want to put it after the check for request.post?
Like some others here, i'm surprised this ever worked

Fred

redirect_back_or_default(:controller => ‘grapher’, :action =>
‘index’)
flash[:notice] = “New User Successfully Created”

This code also looks odd, how will it get to the flash line after the
redirect? Though I may be missing what redirect_back_or_default is
supposed to do.

Calls to redirect, render etc. don’t terminate the action so there’s nothing very wrong about this (don’t know if the rails 3.1 changes to flushing will change this)

rescue ActiveRecord::RecordInvalid

More odd looking code, or did the syntax for rescue change
dramatically with Rails 2 from Rails 1

That’s just standard ruby.

Fred

I thought you had to have
begin
...
rescue
...
end

Colin

I changed the order of my "def signup" as follows:

class UserController < ApplicationController

public
  def signup
    return unless request.post?
    @user = User.new(@params[:user])
    @user.save!
    redirect_back_or_default(:controller => 'grapher', :action =>
'index')
    flash[:notice] = "New User Successfully Created"
    rescue ActiveRecord::RecordInvalid
    render :action => 'signup'
   end

.. and now my form page comes up but still get this error message when I
hit submit:

NoMethodError in UserController#signup
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]

thanks
jack

It should be params[..] not @params[..]

I thought you said the code worked before you upgraded.

I also suggest you have a look at the Rails Guide on debugging (and
the other guides in fact). That will show you how to use ruby-debug
to break into the code and inspect the data. In this case, for
example, you could have broken in before the @user= line and you would
see that @params was nil, which would have made you look more closely
at it and realise the typo.

Colin

def some_method
...
rescue
...
end

works too

Fred

Once again the trivial extent of my knowledge is exposed :slight_smile:
No doubt that is documented somewhere in the Ruby docs, but it did not
leap out at me from anywhere I looked.

Thanks

Colin