Trying to learn ruby on rails following Michael Hartl's tutorial, when I try to go to the registration page in the book I get this:
NoMethodError in UserController#register
undefined method `save' for nil:NilClass
here is the code from the user_controller.rb file:
class UserController < ApplicationController
def index
#title = "RailsSpace User Hub"
end
def register
#title = "Register"
if request.post? and params[:user]
#user = User.new(user_params)
end
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
end
end
private
def user_params
# Add the user attributes that you sent with post (form) to the permit
method.
params.require(:user).permit(:name, :screen_name)
end
end
It's complaining about line 11 where it says: if #user.save I'm just following the tutorial I don't know what's going on.
Try to understand what the error message is saying. You're trying to call .save on #user but where you are calling it, #user may not be defined. The problem is you can't call .save on a nil object so it throws NoMethodError.
You're logic is incorrect so you must first make sure #user is instantiating a new User instance. It should be more like this:
def register
#title = "Register"
if request.post? && params[:user]
#user = User.new(user_params)
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
else
# handle erorrs here
flash[:alert] = "Please fix errors: #{#user.errors.full_messages.inspect}"
redirect_to :back #this may need to change depending, just an example.
end
end
end
NoMethodError in UserController#register undefined method 'save' for nil:NilClass
The error is thrown because you are calling save on a nil; and it is because nil object does not have this method. the save is a instance method belonging to ActiveRecord::Base class.
The reason #user is nil is because #user is an instance variable in the UserController class which you have not given it any value. Any variable starting with # inside a class is an instance variable in Ruby.
To solve this problem, you should set a value to #user, and in this case it should be a User instance. You can either create a new user object by doing #user = User.new(user_params) or you fetch a record from the Database by doing #user = User.find(<some_id>)
Related
I'm working on a rails app that contains a Users controller and an Images controller. This is the create method in the Images controller:
def create
#image = current_user.images.build(image_params)
if #image.save
flash[:success] = "Image uploaded!"
redirect_to current_user
else
render 'users/show' #Error occurs here
end
end
Successful saves are handled fine, but if the image is too large or non-existent and 'users/show' is rendered, rails gives the error:
NoMethodError (undefined method `name' for nil:NilClass):
app/views/users/show.html.erb:1:in `_app_views_users_show_html_erb___2850090823537495038_37901140'
app/controllers/images_controller.rb:12:in `create'
I expect this happened because I hadn't initialized all the variables necessary for 'users/show' within my Images controller, so I moved the content from the show method of the Users controller to a new method in the Application controller and called it before rendering the page from Images. Here's the intitialize method:
def initialize_show
#user = User.find(params[:id])
#images = #user.images.paginate(page: params[:page])
#image = current_user.images.build if logged_in?
end
And the new create method:
def create
#image = current_user.images.build(image_params)
if #image.save
flash[:success] = "Image uploaded!"
redirect_to current_user
else
initialize_show # Called this method
render 'users/show'
end
end
Now rails is giving the error:
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=):
app/controllers/application_controller.rb:6:in `initialize_show'
app/controllers/images_controller.rb:12:in `create'
What am I missing here? This is my first rails app so I appreciate the help.
ptd provided the answer in a comment above. #user wasn't getting initialized because the id param wasn't posted to images#create. Here's the solution:
def create
#image = current_user.images.build(image_params)
if #image.save
flash[:success] = "Image uploaded!"
redirect_to current_user
else
#user = current_user
initialize_show # I removed the #user initialization in this method
render 'users/show'
end
end
It looks like your template (users/show) uses something (#vars) that is not available in this case. Can you show that template code? Maybe you have something line #user.name there but this var is not initialized in case you have described...
I can't figure out why the #user variable is not being found. It's throwing the error inside of a view where I try to link to the user, and it mentions the index of Users.
What am I doing wrong?
More info: They login via a session page, and then I redirect them to the "User view" to then use the application as a logged in user. The session is created successfully.
Routes.rb
resources :users
resources :sessions
Users Controller
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.create!(user_params)
redirect_to users_path, notice: "Successfully created #{#user.name}"
end
def index
#user = User.find_by_email(params[:email])
end
private
def user_params
params.require(:user).permit!
end
end
Sessions Controller
class SessionsController < ApplicationController
def new
end
def create
#user = User.find_by_email(params[:email])
if #user && #user.authenticate(params[:password])
session[:user_id] = #user.id
redirect_to users_path, notice: "Logged in as #{#user.name}"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
end
User View
<%= link_to user.name, edit_user_path(user) %>
The user variable in your view is being seen as a local variable, which is undefined. Use #user instance variable instead of user as it's #user that's defined in your index action.
<%= link_to #user.name, edit_user_path(#user) %>
Update:
So basically the problem was in the OP's user's migration, the option id: false was set. Which led to creation of users table without the id column and #user.id was always nil. Removing this option from the migration fixed the issue!
User signs up, is redirected to a page to be collected info, pretty straight forward
I for my life can't figure out how to do this
My controller for the user
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def additional_info
#user = User.find session[:user_id]
#user = User.update(user_addinfo)
redirect_to user_path
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.require(:user).permit(:year)
end
end
user_addinfo is the action method that i want to call updating my record on for my additional_info method.
the def create method has commented line that i'm unsure if necessary, particularly the session[:user_id] = #user.id. I was told that i need this in order to keep track of my session, but perhaps someone can debunk this for me, as im following michael hartl's tutorial.
as of right now with this code, rails is giving me a parameter missing in the
params.require(:user).permit(:year) line.
Much help is greatly appreciated. Ive been trying many different things, and cant seem to figure this out
Change your controller code as below:
def additional_info
#user = User.find params[:id] ## Set #user
end
def update
if #user.update(user_addinfo)
redirect_to user_path(#user), notice: 'User was successfully updated.'
else
render action: 'additional_info'
end
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path(#user) ## Pass #user
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
and in your routes.rb update the additional_info route as
get 'info/:id' => 'users#additional_info', :as => 'additional_info'
You additional_info action seems to be wrong. You need to pass in the id of the user for whom you are collecting additional information.
def additional_info
#user = User.find params[:id]
#user.update_attributes(user_addinfo)
redirect_to user_path(#user)
end
The line you have commented in your create method:
#session[:user_id] = #user.id
Is what is storing the user id to a session variable and not a param in the url.
You then have this line commented in your additional_info method
#user = User.find session[:user_id]
This is looking up the user by the id that you would have previously stored in the session variable.
At that point the user object would be stored in user
If you need it in your instance variable, make sure to modify the line to be
#user = User.find session[:user_id]
Your user would then be stored in #user and be able to be accessed in the view
code which giving error is in CommentsController
if #comments.save
user_session.add_comment(#comments) // this is cause of error
# session[:comment_ids] ||= []
# session[:comment_ids] << #comments.id
flash[:notice] = "Comment Successfully created"
redirect_to #post
else
redirect_to :back
end
When I go to edit comment which is stored in session for 1 minute. I got this error:
NameError in CommentsController#create
undefined local variable or method `session' for #<UserSession:0xaca0684>
add_comment is defined in session model.
One more thing I want to say that error occurs because I used a centralized location through session model otherwise commented code above was working fine.
If I understand correctly, you've refactored the commented out code into the user_session object.
If you read the error message you see that the error references a variable session for #<UserSession:0xXXXXX>. From this I understand that you tried to reference the session object from within the UserSession class, but you did not pass it to the user_session object.
You should add it to the method's signature, and use it like this:
class UserSession
def add_comment(session, comment)
session[:comment_ids] ||= []
session[:comment_ids] << comment.id
end
end
And in your controller:
if #comment.save
user_session.add_comment(session, #comment)
flash[:notice] = "Comment Successfully created"
redirect_to #post
else
redirect_to :back
end
I am practicing with rails and I was in the topic of "session" and I get the message
"undefined method `session' for ApplicationController:Class"
please help me
this is the code
*(controller aplication)
class ApplicationController < ActionController::Base
session :session_key => 'ruby_cookies'
end
*(controller when I want to create the cookies)
class RegistroController < ApplicationController
def index
end
def login
if request.post?
p_user = User.new(params[:user])
user = User.find_by_nombre_and_password(p_user.nombre, p_user.password)
if user
session[:user_id] = user.id
flash[:notice] = "se ha identificado correctamente"
redirect_to home_url
else
flash[:notice] = "se incorrecto psps"
redirect_to login_url
end
end
end
def logout
session[:user_id] = nil
flash[:notice] = "adios sayonara"
redirect_to home_url
end
end
Your code is really hard to read, but the issue is probably related to this line where it looks like it's trying to call a method "session" and pass it a key/value pair.
session :session_key => 'ruby_cookies'
This doesn't appear to be within any sort of controller action. Normally you would set a session value with session[:my_value] = 'value' and read it with session[:my_value], just like a normal hash.
Your code in ApplicationController doesn't belong there. It belongs in a configuration file, for example config/environment.rb, where it would read something like this:
config.action_controller.session = {
:session_key => 'ruby_cookies'
}
See http://guides.rubyonrails.org/configuring.html for much more detail.