I'm following this article(http://asciicasts.com/episodes/160-authlogic), I'm not using nifty generator tho.
I've done the User model and localhost:3000/users/new page works fine.
But when I try to open localhost:3000/login, the page is just empty. The source is empty too.
I've just copied the source from the site.
routes.rb
map.login 'login', :controller => 'user_sessions', :action => 'new'
map.logout 'logout', :controller => 'user_sessions', :action => 'destroy'
map.resources :user_sessions
map.resources :users
user_sessions_controller.rb
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] = "Successfully logged in."
redirect_to root_url
else
render :action => 'new'
end
end
def destroy
#user_session = UserSession.find
#user_session.destroy
flash[:notice] = "Successfully logged out."
redirect_to root_url
end
end
/views/user_sessions/new.html.erb
<% form_for #user_session do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :username %><br />
<%= f.text_field :username %>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_field :password %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
The code is just same as the site.
The server console shows that the views are being rendered:
Completed 200 OK in 149ms (Views: 145.5ms | ActiveRecord: 3.2ms)
Why is the login form not displayed at all?
Update
After added new action 'index' into user_sessions controller(also plus index.html.erb), if I open localhost:3000/user_sessions/index shows me below message.
Unknown action
No action responded to show. Actions: create, destroy, index, and new
And, this is WEBrick output
Processing UserSessionsController#show
(for 127.0.0.1 at 2010-01-22 12:47:10)
[GET]
Parameters: {"id"=>"index"}
ActionController::UnknownAction (No
action responded to show. Actions:
create, destroy, index, and new):
I've found the reason.
There was nothing in Views/layouts/application.html.erb, the file is exist, tho.
/views/new.html.erb should be located at views/user_sessions/new.html.erb
Related
I must be missing something... my views are being rendered, but it appears like code in the controller isn't being executed. I can't find what's wrong.
When I click the login button in login.html.erb, the login_process method of the PublicController should be called to authenticate the user. That doesn't seem to happen as the view login_process.html.erb just displays, which shouldn't be possible.
I've even tried putting a flash[:notice] = "heyhey" on the login_screen action so it appears on the login form, but that doesn't happen either.
What have I done wrong?
Is it something in the routes.rb?
routes.rb
root :to => "public#index"
get "login",
:to => "public#login",
:as => "login_screen"
post "login_process",
:to => "public#login_process",
:as => "login_process"
get "logout",
:to => "public#logout",
:as => "logout"
public_controller.rb
class PublicController < ApplicationController
def login_screen
flash[:notice] = "heyhey"
end
def login_process
authenticated_user = User.authenticate params[:email], params[:password]
if authenticated_user
session[:user_id] = authenticated_user.id
session.countdown_start(1.minute)
redirect_to :public => :index
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
render :login_screen
end
def logout
session.countdown_abort
flash[:notice] = "You are now logged out"
redirect_to :login_screen
end
def count
render :text => session.countdown_count.to_i
end
end
views/public/login.html.erb
<h1>Login</h1>
<p id="notice"><%= notice %></p>
<%= form_tag :login_process do %>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Login" %>
</div>
<% end %>
<h1>Login</h1>
<p id="notice"><%= notice %></p>
<%= form_tag :login_process do %>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Login" %>
</div>
<% end %>
login_process.html.erb
I never expect to see this page as the user should be directed elsewhere
<p>login_process.html.erb</p>
<p id="notice"><%= notice %></p>
Update 1:
I've modified the authenticate action in the User model to be:
def authenticate(:email, :password)
#x = new User
#x.id = 123
return false #x
end
and login_process on PublicController to be:
def login_process
if true
flash[:notice] = 'boom'
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
redirect_to :login_screen
end
Unfortunately though... same issue. The login_process.html.erb is
displayed with no flash notices either.
Versions:
Ruby 2.0.0p247
Rails 4.0.0
The code in your controller is probably executing just fine.
I think the authenticate class method on User is not giving you the correct result. That's why it doesn't go through the if authenticated_user and just renders the login_process view. You don't have to call this render command though, it's done for you if you do nothing.
There's a problem with the login_process method though. You can't have a render call and a redirect_to be called together, now it can happen in your case, if the user is authenticated. Put the render :login_screen in the else case, otherwise you get the AbstractController::DoubleRenderError error saying: Render and/or redirect were called multiple times in this action. [etc.]
This is what you would get as an error if the user was authenticated.
Edit: Running this locally (stubbing User.authenticate) on a new Rails project it works. Flash notices appear and everything.
Also: render :login_screen is probably render :login, no? in login_process?
If nothing works still, what's your: Ruby version, Rails version, put authenticated_user = false # or true in login_process to see if it behaves differently.
redirect_to :public => :index
It seems like you are redirecting from login_process to /login_process?public=index, which I don't think is your intention.
If you are meaning to redirect to public#index, try
redirect_to root_path
(But I can't see that action in your public controller.)
I believe the problem is that you call two renders in one action. You can only render one page per action.
def login_process
authenticated_user = User.authenticate params[:email], params[:password]
if authenticated_user
session[:user_id] = authenticated_user.id
session.countdown_start(1.minute)
redirect_to :public => :index
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
render :login_screen
end
The user is authenticated and the redirect_to should bring you to the public/index, however, you call render :login_screen after the if statement, so it will execute that portion of the code no matter what and bring you back to the login.
I'm super new to Ruby on Rails. I'm trying to make an authentication system using Authlogic (following this tutorial). The error that I'm getting is right after I submit the login form:
No route matches "/user_sessions/%23%3CUserSession:0x103486aa8%3E"
Surprisingly the URL of the page right after the form is submitted which also brings up the error is:
http://localhost:3000/user_sessions/%23%3CUserSession:0x103486aa8%3E
I have no idea what I have done wrong and where that weird UserSession code thing is coming from!!!
This is how my login form looks like:
<% form_for #user_session do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :username %><br />
<%= f.text_field :username%>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_field :password %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
Here is my UserSession class:
class UserSession < Authlogic::Session::Base
def to_key
new_record? ? nil : [ self.send(self.class.primary_key) ]
end
end
and the create action of my UserSessionController:
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default root_path
else
render :action => :new
end
end
"redirect_back_or_default" method in ApplicationController:
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
And lastly everything related to user_sessions in routes.rb:
resources :user_sessions
match 'login' => "user_sessions#destroy", :as => :login
match 'logout' => "user_sessions#destroy", :as => :logout
These are the codes that I thought could be involved in getting that error. If I should add some more code to make it more clear please let me know.
Ok, first, you have a bad route:
match '/login', :to => 'user_sessions#new', :as => 'login'
note the new instead of destroy
also, the to_key is not needed in later versions - I'm using rails 3 and don't have it in my UserSession Model.
Definitely need to change your route to not match login to destroy.
Here's the route setting I have... (from "Agile Web Development with Rails" example).
controller :user_sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
I am a beginning developer, and I was able to successfully use this tutorial (I'm in Rails 3): http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/ to allow for users to reset their passwords, however I also have a customer model that I need to do this for, and I'm running into issues (listed below code). I think the error is my routing, but I'm not sure how to fix it.
routes.rb
resources :password_resets do
get 'edit_customer'
post 'edit_customer'
end
password_resets_controller.rb
class PasswordResetsController < ApplicationController
before_filter :load_user_using_perishable_token, :only => [:edit, :update]
before_filter :load_customer_using_perishable_token, :only => [:edit_customer, :update_customer]
before_filter :require_no_user, :require_no_customer
def new
render
end
def create
#user = User.find_by_email(params[:email])
#customer = Customer.find_by_email(params[:email])
if #user
#user.deliver_password_reset_instructions!
flash[:notice] = "Instructions to reset your password have been emailed to you. " +
"Please check your email."
redirect_to new_user_session_path
elsif
if #customer
#customer.deliver_customer_password_reset_instructions!
flash[:notice] = "Instructions to reset your password have been emailed to you. " +
"Please check your email."
redirect_to new_customer_session_path
end
else
flash[:notice] = "No account was found with that email address"
render :action => :new
end
end
def edit
render
end
def edit_customer
#redirect_to edit_customer_password_resets_path
end
def update
#user.password = params[:user][:password]
#user.password_confirmation = params[:user][:password_confirmation]
if #user.save
flash[:notice] = "Password successfully updated"
redirect_to new_user_session_path
else
render :action => :edit
end
end
def update_customer
#customer.password = params[:customer][:password]
#customer.password_confirmation = params[:customer][:password_confirmation]
if #customer.save
flash[:notice] = "Password successfully updated"
redirect_to new_customer_session_path
else
render :action => :edit
end
end
private
def load_user_using_perishable_token
#user = User.find_using_perishable_token(params[:id])
unless #user
flash[:notice] = "We're sorry, but we could not locate your account." +
"If you are having issues try copying and pasting the URL " +
"from your email into your browser or restarting the " +
"reset password process."
redirect_to new_user_session_path
end
end
def load_customer_using_perishable_token
#customer = Customer.find_using_perishable_token(params[:id])
unless #customer
flash[:notice] = "We're sorry, but we could not locate your account." +
"If you are having issues try copying and pasting the URL " +
"from your email into your browser or restarting the " +
"reset password process."
#redirect_to new_customer_session_path
end
end
end
MODELS
user.rb model
def deliver_password_reset_instructions!
reset_perishable_token!
UserMailer.password_reset_instructions(self).deliver
end
customer.rb model
def deliver_customer_password_reset_instructions!
reset_perishable_token!
UserMailer.customer_password_reset_instructions(self).deliver
end
VIEWS
password_resets/new
<% form_tag password_resets_path do %>
<p>Email:</p>
<%= text_field_tag "email" %><br />
<br />
<%= submit_tag "Reset my password" %>
<% end %>
password_resets/edit
<% form_for #user, :url => password_reset_path, :method => :put do |f| %>
<%= f.label :password %><br />
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Change my password and log me in"%>
<% end %>
password_resets/edit_customer
<% form_for #customer, :url => password_reset_path, :method => :put do |f| %>
<%= f.label :password %><br />
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Change my password and log me in" %>
<% end %>
It works perfectly for the code that does not have "customer" appended to it. The token generates, and I can get the email to send with the same format for the url: /password_resets//edit_customer
However, it receives an error when I try to pull up the url. With the code above, I receive this error: "No route matches {:action=>"show", :controller=>"password_resets"}" - I can also see that it interprets the :id to be the id of the controller (which is different than how the user one works - it correctly interprets the id as the token.
I have experimented a lot:
change :id in controller for edit_customer in load_customer_using_perishable_token to perishable_token, customer.perishable_token, #customer.perishable_token)
tried to append these to "get 'edit_customer'" using the path helper (=> "cust_pass") - :path, :path_name, :as so i could change the url to cust_pass_path
i even tried to add this to the routes just to see if it would work
match '/password_resets/:id/edit_customer' => 'password_resets#edit_customer'
So I stumped. Any help would be greatly appreciated!
Ok by my interpretation you are recieving the email, but clicking the link gives you an error? To start with the error message
"No route matches {:action=>"show", :controller=>"password_resets"}"
is appearing because you are trying to call the show action in your password_resets contoller, but it is not defined. First thing you should do is exclude it from your routes.
resources :password_resets, :except => :destroy do
get 'edit_customer'
post 'edit_customer'
end
I dont think it will fix your problem, but having routes that go nowhere is kind of pointless. Secondly make sure you do not have anything linking to the show action. As the error seems to be occuring when you click the link in the email I would think that the link you are sending is not correct.
I was able to fix this by updating the url in edit_customer.rb
from
:url => password_reset_path
to
:url => {:action=>"update_customer", :controller=>"password_resets"}
I also had to update my route.rb
from
resources :password_resets do
get 'edit_customer'
post 'edit_customer'
end
to
resources :password_resets, :except => [:index, :destroy, :show] do
get 'edit_customer'
put 'update_customer'
end
Right now I'm building a project management app in rails, here is some background info:
Right now i have 2 models, one is User and the other one is Client. Clients and Users have a one-to-one relationship (client -> has_one and user -> belongs_to which means that the foreign key it's in the users table)
So what I'm trying to do it's once you add a client you can actually add credentials (add an user) to that client, in order to do so all the clients are being displayed with a link next to that client's name meaning that you can actually create credentials for that client.
So in order to do that I'm using a helper the link to helper like this.
<%= link_to "Credentials",
{:controller => 'user', :action => 'new', :client_id => client.id} %>
Meaning that he url will be constructed like this:
http://localhost:3000/clients/2/user/new
By creating the user for the client with he ID of 2.
And then capturing the info into the controller like this:
#user = User.new(:client_id => params[:client_id])
EDIT: This is what i currently have in my View/Controller and Routes
I keep getting this error: No route matches "/clients//user" with {:method=>:post}
Routes
ActionController::Routing::Routes.draw do |map|
map.resources :users
map.resources :clients, :has_one => :user
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def new
#user = User.new
#client = Client.new
end
def load_client
#client = Client.find(params[:client_id])
end
def create
#user = User.new(params[:user])
#user.client_id = #client.id
if #user.save
flash[:notice] = "Credentials created"
render :new
else
flash[:error] = "Credentials created failed"
render :new
end
end
View
<% form_for #user, :url => client_user_url(#client) do |f| %>
<p>
<%= f.label :login, "Username" %>
<%= f.text_field :login %>
</p>
<p>
<%= f.label :password, "Password" %>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation, "Password Confirmation" %>
<%= f.password_field :password_confirmation %>
</p>
<%= f.submit "Create", :disable_with => 'Please Wait...' %>
<% end %>
Your form tag is wrong, you are posting to /users without the :client_id.
Try this:
<% form_for #user, :url => {:controller => 'users', :action => 'new', :client_id => #client.id} do |f| >
Alternatively, you could use nested resources:
config/routes.rb
map.resources :clients do |clients|
clients.resources :users
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def load_client
#client = Client.find(params[:client_id])
end
# Your stuff here
end
View
<% form_for [#client, #user] do |f| %>
I solved this by using nested attributes, by including the user model, when creating the client. And it works flawlessly.
In case any of you guys need more info here's the two screencasts that helped me come up with as solution:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/196-nested-model-form-part-2
I'm trying to set up a simple login using AuthLogic into my User table. Every time I try, the login fails and I don't know why. I'm sure this is a simple error but I've been hitting a brick wall with it for a while.
#user_sessions_controller
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
else
flash[:notice] = "We couldn't log you in. Please try again!"
redirect_to :controller => "index", :action => "index"
end
end
#_user_login.html.erb (this is the partial from my index page where Users log in)
<% form_tag user_session_path do %>
<p><label for="login">Login:</label>
<%= text_field_tag "login", nil, :class => "inputBox", :id => "login",
</p>
<p><label for="password">Password: </label>
<%= password_field_tag "password", nil, :class => "inputBox", :id => "password",
</p>
<p><%= submit_tag "submit", :class => "submit" %></p>
<% end %>
I had Faker generate some data for my user table but I cannot log in! Every time I try it just redirects to index. Where am I going wrong? Thanks everybody.
------UPDATE------
I implemented Jakub Hampl's suggestion with form_for just now - I'm getting a new error.
ActionView::TemplateError (called id for nil, which would mistakenly be 4 -
1: <% form_for #user_session do |f| %>
2: <% if flash[:notice] -%>
3: <p class="notice"><%= flash[:notice] %></p>
4: <% end -%>
app/views/index/_user_login.html.erb:1
app/views/layouts/index.html.erb:65
app/controllers/index_controller.rb:3:in `index'
Rendered rescues/_trace (86.0ms)
Rendered rescues/_request_and_response (1.0ms)
Rendering rescues/layout (internal_server_error)
I have not changed the controller at all. Thank you everyone who is responding to this topic - it's incredibly helpful to me. What can I do now to get past this hurdle?
------UPDATE #2------
Here is my application controller.
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.user
end
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to login_path
return false
end
end
def require_no_user
if current_user
store_location
flash[:notice] = "You must be logged out to access this page"
redirect_to root_url
return false
end
end
Which one of these should be changed to #user_session?
A good idea is to use form_for if you possibly can:
<% form_for #user_session do |f| %>
<p>
<%= f.label :username %>
<%= f.text_field :username, :class => :inputBox %>
</p>
<p>
<%= f.label :password %>
<%= f.password_field :password, :class => :inputBox %>
</p>
<p><%= f.submit "submit", :class => :submit %></p>
<% end %>
Apart from that hard to say. Does your log file give any detail (aka errors)? Also try to add the errors on the table to you flash so that you can see what's going wrong.
Since it seems fro your last update that #user_session is not set, just go ahead and create one: <% form_for UserSession.new do |f| %>.
in your case, params[:user_session] is empty because it's not being set in your view. I think Jakub Hampl's suggestion to use form_for is the best way, but you can also stay with form_tag by setting input names to user_session[login] and user_session[password], OR you can change the line in your action to #user_session = UserSession.new(:login => params[:login], :password => params[:password])
.