Reputation: 25
So I'm working with authlogic, and I'm trying to duplicate the login functionality to the welcome page, so that you can log in by restful url or by just going to the main page. No, I don't know if we'll keep that feature, but I want to test it out anyway. Here's the error message:
RuntimeError in Welcome#index
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
The code is below. Basically, what's happening is the index view (the first code snippet) is sending the information from the form to the create method of user_sessions controller. At this point, in theory, it create should just pick up, but it doesn't.
PLEASE help. Please. I've been doing this for about 8 hours. I checked Google. I checked IRC. I checked every book I could find. You don't even have to answer, I can to the grunt work if you just point me in the right direction.
Sameera was good enough to provide the answer to the problem. Open question, though is what the best way to organize the app is. Is applying the object @user_sessions in a before_filter acceptable, or is there a more rails-y way of doing this?
WELCOME#INDEX
<% form_for @user_session, :url => user_sessions_path do |f| %>
<%= f.text_field :email %><br />
<%= f.password_field :password %>
<%= submit_tag 'Login' %>
<% end %>
APPLICATION CONTROLLER
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
# Scrub sensitive parameters from your log
# filter_parameter_logging :password
helper_method :current_user_session, :current_user
before_filter :new_session_object
protected
def new_session_object
unless current_user
@user_session = UserSession.new(params[:user_session])
end
end
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.record
end
end<pre></code>
USER SESSIONS CONTROLLER
class UserSessionsController < ApplicationController
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
flash[:notice] = "Logged in"
redirect_to root_url
else
render :controller => 'user_sessions', :action => 'new'
end
end
def destroy
@user_session = UserSession.find
@user_session.destroy
flash[:notice] = "Logged out"
redirect_to root_url
end
end
A more detailed STACK TRACE
1: <h1>Welcome#index</h1>
2: <p>Find me in app/views/welcome/index.html.erb</p>
3:
4: <% form_for @user_session, :url => user_sessions_path do |f| %>
5: <%= f.text_field :email %><br />
6: <%= f.password_field :password %>
7: <%= submit_tag 'Login' %>
Application Trace | Framework Trace | Full Trace
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/actionpac -2.3.5/lib/action_controller/record_identifier.rb:76:in `dom_id'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_view/helpers/record_identification_helper.rb:16:in `dom_id'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_view/helpers/form_helper.rb:293:in `apply_form_for_options!'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_view/helpers/form_helper.rb:277:in `form_for'
/Users/alex/Desktop/anglic/app/views/welcome/index.html.erb:4:in `_run_erb_app47views47welcome47index46html46erb'
Upvotes: 1
Views: 517
Reputation: 16619
Try this:
form_for :user_session, @user_session, :url => user_session_path(@user_session)} do |f|
end
Upvotes: 0
Reputation: 1185
I think you can try this in your WelcomeController
class WelcomeController < ActionController::Base
def index
@user_session = UserSession.new
.....
end
.....
end
It seems to me that you are trying to use @user_session which is not defined in the view of WelcomeController index action.
Hopefully it helps.
EDIT #1
It seems to me that the problem occur when the before_filter was called, after you submit the form in the WelcomeController#index action.
This particular section of code is strange to me
class ApplicationController < ActionController::Base
.....
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
.....
end
I am quite sure UserSession.find
will break.
Hopefully this edit helps.
EDIT #2
Another thing that I found strange is inside the protected method new_session_object:
protected
def new_session_object
unless current_user
@user_session = UserSession.new(params[:user_session])
end
end
Any reason why the UserSession.new
was created with params[:user_session]
?
The flow for your UserSessionController
login as far as I understand it is:
before_filter
:new_session_object
is called
it will return false
for
current_user
since it is a new
user session
it will set @user_session
variable
to
UserSession.new(params[:user_session])
value
UserSessionController#new
action
is called which override
@user_session
variable to
UserSession.new
new.html.erb
is rendered
containing the form for login
before_filter :new_session_object
is
called again
it will return false
for
current_user
since it is still a
new user session
it will set @user_session
variable
to
UserSession.new(params[:user_session])
value
UserSessionController#create
action is called which will again
set the @user_session
variable to
UserSession.new(params[:user_session])
value.
@user_session
is saved and the
user session is successfully
created
BUT for the WelcomeController
it is subtly different in step 4
The @user_session
variable value that is used in the WelcomeController#index
came from the before_filter
call variable assignment of UserSession.new(params[:user_session])
, at that point the params[:user_session]
value is nil
, so the @user_session = UserSession.new(nil)
when the index.html.erb
was rendered.
I am not entirely sure if this is the thing that cause your problem, but it may help you to troubleshoot this issue if you run script/server --debugger
and step trough the creation of @user_session
when using WelcomeController
, specially when the form is posted to UserSessionController#create
.
Upvotes: 0
Reputation: 8807
You should add the following method to the ApplicationController:
def require_user
unless current_user
flash[:notice] = "You must be logged in to access this page!"
redirect_to :controller => "user_sessions", :action => "new"
return false
end
end
Then in the WelcomeController add a before filter like this:
before_filter :require_user
Now, anybody accessing WelcomeController will be redirected to the login page. You don't have to duplicate the functionality across controllers.
Please go through the Authlogic set-up tutorial for details: http://rdoc.info/projects/binarylogic/authlogic
Upvotes: 1