I've been struggling for a while with this one. I have a Rails4/Devise 3.1 app with two users in the system:
Graduates
Employers
and one devise User who can be either a Graduate or Employer via a polymorphic :profile association. I have Graduates sign up via /graduate/sign_up path and employers via /employer/sign_up path both of which route to the same /views/devise/registrations/new.html.erb view (since their signup form is pretty much the same - email and password). Everything works fine, except when there is a validation error, RegistrationsController#create.respond_with resource always redirects both user types to /users path and I need to redirect them back to where they originally came from, e.g. /graduate/sign_up or /employer/sign_up respectively. I've tried replacing respond_with with redirect_to, but I end up loosing the resource object with associated error messages. Any idea guys on how this can be done?
These are my models:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :profile, polymorphic: true
end
class Graduate < ActiveRecord::Base
has_one :user, as: :profile
end
class Employer < ActiveRecord::Base
has_one :user, as: :profile
end
Registrations controller:
class RegistrationsController < Devise::RegistrationsController
def create
build_resource sign_up_params
user_type = params[:user][:user_type]
# This gets set to either 'Graduate' or 'Employer'
child_class_name = user_type.downcase.camelize
resource.profile = child_class_name.constantize.new
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
respond_with resource
end
end
end
Registration view (same for both, graduates and employers):
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<%= hidden_field resource_name, :user_type, value: params[:user][:user_type] %>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
These are my routes:
devise_for :users, :controllers => { :registrations => 'registrations' }
devise_scope :user do
match 'graduate/sign_up', to: 'registrations#new', user: { user_type: 'graduate' }, via: [:get]
match 'employer/sign_up', to: 'registrations#new', user: { user_type: 'employer' }, via: [:get]
end
root to: 'home#index'
Output of rake routes;
$ rake routes
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) registrations#cancel
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
PATCH /users(.:format) registrations#update
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#destroy
graduate_sign_up GET /graduate/sign_up(.:format) registrations#new {:user=>{:user_type=>"graduate"}}
employer_sign_up GET /employer/sign_up(.:format) registrations#new {:user=>{:user_type=>"employer"}}
root GET /
Apparently, the :location parameter is ignored if you have an existing template called, well, in this case, #index. I still don't understand why Devise redirects to #index or #show when the resource has errors on it.
I'll update this answer as I find out more.
Calling respond_with will render the default action of that resource. This I believe is the index action (/users/) and thus the cause for the redirect.
I think what you want to do is render the new action instead. Try the following:
if resource.save
...
else
clean_up_passwords(resource)
render :action => 'new'
end
In case of respond_with, for an html response - if the request method is get, an exception is raised but for other requests such as post the response depends on whether the resource has any validation errors (i.e. assuming that an attempt has been made to save the resource, e.g. by a create action) -
If there are no errors, i.e. the resource was saved successfully, the
response redirect's to the resource i.e. its show action.
If there are validation errors, the response renders a default action,
which is :new for a post request or :edit for patch or put.
source: http://apidock.com/rails/v4.1.8/ActionController/MimeResponds/respond_with
For your case, something like render 'view_path' in place of respond_with block should work.
Related
I'm using Acts_as_follower in a wishlist app I'm working on. I think it should be working, but the button to actually follow another user is not. The follow button is in my user index view, and I can see it there, but it doesn't respond to being clicked. Any help would be appreciated. Here's my code:
index.html.erb
<div class="container">
<% #users.each do |u| %>
<div class="col-sm-8 col-lg-4">
<div id="gifts">
<div class="box panel panel-default">
<h2><%= link_to u.name, u %></h2>
<p>
<table align="center" margin="5">
<tr>
<th style="padding-right: 10px"><%= button_to "View Wishlist", u, method: :get, class: "btn btn-primary" %></th>
<th>
<% if current_user.following?(u) %>
<%= form_tag user_unfollow_path(user_id: u.id), method: :delete, remote: true do %>
<%= button_tag 'unfollow', class: 'btn btn-primary' %>
<% end %>
<% else %>
<%= form_tag user_follow_path(user_id: u.id), method: :post, remote: true do %>
<%= button_tag 'follow', class: 'btn btn-success' %>
<% end %>
<% end %>
</th>
</tr>
</table>
<p>
</div>
</div>
</div>
<% end %>
</div>
followers_controller.rb
class FollowersController < ApplicationController
before_action :authenticate_user!
respond_to :js
def create
#user = User.find(params[:user_id])
current_user.follow(#user)
end
def destroy
#user = User.find(params[:user_id])
current_user.stop_following(#user)
end
end
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#gifts = #user.gifts
end
def index
#users = User.all
if params[:search]
#users = User.search(params[:search]).order("created_at DESC")
else
#users = User.all.order("created_at DESC")
end
end
def create
#user = User.find(params[:user_id])
current_user.follow(#user)
end
def destroy
#user = User.find(params[:user_id])
current_user.stop_following(#user)
end
private
def get_gifts
#gifts = Gift.find(params[:id])
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:index] do
post :follow, :to => 'followers#create'
delete :unfollow, :to => 'followers#destroy'
end
resources :gifts
resources :wishlists
get 'wishlists/index'
get '/wishlists', :to => 'wishlists#index'
get '/users/:id', :to => 'users#show', :as => :user
get '/users', :to => 'users#index'
root "gifts#index"
end
user.rb (model)
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
acts_as_follower
acts_as_followable
has_many :gifts
belongs_to :wishlist
def self.search(search)
where("name ILIKE ?", "%#{search}%")
end
end
routes:
C:\Sites\gladlygift>rake routes
Prefix Verb URI Pattern Controller#A
tion
new_user_session GET /users/sign_in(.:format) devise/sessi
ns#new
user_session POST /users/sign_in(.:format) devise/sessi
ns#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessi
ns#destroy
user_password POST /users/password(.:format) devise/passw
rds#create
new_user_password GET /users/password/new(.:format) devise/passw
rds#new
edit_user_password GET /users/password/edit(.:format) devise/passw
rds#edit
PATCH /users/password(.:format) devise/passw
rds#update
PUT /users/password(.:format) devise/passw
rds#update
cancel_user_registration GET /users/cancel(.:format) devise/regis
rations#cancel
user_registration POST /users(.:format) devise/regis
rations#create
new_user_registration GET /users/sign_up(.:format) devise/regis
rations#new
edit_user_registration GET /users/edit(.:format) devise/regis
rations#edit
PATCH /users(.:format) devise/regis
rations#update
PUT /users(.:format) devise/regis
rations#update
DELETE /users(.:format) devise/regis
rations#destroy
user_follow POST /users/:user_id/follow(.:format) followers#cr
ate
user_unfollow DELETE /users/:user_id/unfollow(.:format) followers#de
troy
users GET /users(.:format) users#index
gifts GET /gifts(.:format) gifts#index
POST /gifts(.:format) gifts#create
new_gift GET /gifts/new(.:format) gifts#new
edit_gift GET /gifts/:id/edit(.:format) gifts#edit
gift GET /gifts/:id(.:format) gifts#show
PATCH /gifts/:id(.:format) gifts#update
PUT /gifts/:id(.:format) gifts#update
DELETE /gifts/:id(.:format) gifts#destro
wishlists GET /wishlists(.:format) wishlists#in
ex
POST /wishlists(.:format) wishlists#cr
ate
new_wishlist GET /wishlists/new(.:format) wishlists#ne
edit_wishlist GET /wishlists/:id/edit(.:format) wishlists#ed
t
wishlist GET /wishlists/:id(.:format) wishlists#sh
w
PATCH /wishlists/:id(.:format) wishlists#up
ate
PUT /wishlists/:id(.:format) wishlists#up
ate
DELETE /wishlists/:id(.:format) wishlists#de
troy
wishlists_index GET /wishlists/index(.:format) wishlists#in
ex
GET /wishlists(.:format) wishlists#in
ex
user GET /users/:id(.:format) users#show
GET /users(.:format) users#index
root GET / gifts#index
I'm stuck a bit with the following problem: I use Devise in Rails, when I open the sign up form and submit it with new the data for the new user, no new user is created in the sqlite-db. I think it's because the POST-route for /register is not properly set:
rake routes:
root / static#home
new_user_session GET /login(.:format) devise/sessions#new
user_session POST /login(.:format) devise/sessions#create
destroy_user_session DELETE /logout(.:format) devise/sessions#destroy
user_password POST /password(.:format) devise/passwords#create
new_user_password GET /password/new(.:format) devise/passwords#new
edit_user_password GET /password/edit(.:format) devise/passwords#edit
PUT /password(.:format) devise/passwords#update
cancel_user_registration GET /cancel(.:format) devise/registrations#cancel
user_registration POST / devise/registrations#create
new_user_registration GET /register(.:format) devise/registrations#new
edit_user_registration GET /edit(.:format) devise/registrations#edit
PUT / devise/registrations#update
DELETE / devise/registrations#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
How should I update routes.rb, maybe only :path_names with adding POST for register in some way?:
root to: 'static#home'
devise_for :users, :path => '', :path_names => { :sign_in => "login", :sign_out => "logout", :sign_up => "register" }
RegistrationsController in Devise(from the devise-homepage, just the default one):
class Devise::RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
# GET /resource/sign_up
def new
build_resource({})
respond_with self.resource
end
# POST /resource
def create
build_resource(sign_up_params)
if resource.save
yield resource if block_given?
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_with resource
end
end
# GET /resource/edit
def edit
render :edit
end
# PUT /resource
# We need to use a copy of the resource because we don't want to change
# the current user in place.
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if update_resource(resource, account_update_params)
yield resource if block_given?
if is_flashing_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords resource
respond_with resource
end
end
# DELETE /resource
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_flashing_format?
yield resource if block_given?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
def cancel
expire_data_after_sign_in!
redirect_to new_registration_path(resource_name)
end
protected
def update_needs_confirmation?(resource, previous)
resource.respond_to?(:pending_reconfirmation?) &&
resource.pending_reconfirmation? &&
previous != resource.unconfirmed_email
end
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
end
# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
self.resource = resource_class.new_with_session(hash || {}, session)
end
# Signs in a user on sign up. You can overwrite this method in your own
# RegistrationsController.
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
def sign_up_params
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.sanitize(:account_update)
end
end
new.erb.html:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
The problem is in the order in which you are defining routes. Move the root method after devise_for and it should work as intended.
devise_for :users, :path => '', :path_names => { :sign_in => "login", :sign_out => "logout", :sign_up => "register" }
root to: 'static#home'
If you see source, the root method internally uses map. Since you are specifying root path before devise routes, post requests to root path are being processed by home action of static controller.
I only have 2 weeks learning ruby on rails, in my app the users can register their cars, from their profile (code below) the app sent to the registration cars page,
<div class="container">
<fieldset>
<h1><%= #user.email %></h1>
<br>
<h2>now you are able to...</h2>
<br>
<ul>
<li>
<strong>new car registration: </strong>
<%= link_to "new car", new_user_car_path(current_user)%>
</li>
</ul>
</fieldset>
</div>
it works before but i don't know what i did that now it show this:
Routing Error
No route matches {:action=>"show", :user_id=>#<User id: 27, email: "armando.santoya#hotmail.com", encrypted_password: "$2a$10$EZtvPWiXgMfUlAqvuvGAzODMaas/y4rGkJPKJtg4PnC6...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2012-07-24 19:07:54", last_sign_in_at: "2012-07-24 19:07:54", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", name: nil, created_at: "2012-07-24 19:07:54", updated_at: "2012-07-24 19:07:54">, :controller=>"cars"}
Try running rake routes for more information on available routes.
also I put my carsController
class CarsController < ApplicationController
def new
#car = Car.new
end
def create
#car = current_user.Car.new(params[:car])
if #car.save
flash[:notice] = "new car created success"
#redirect_to current_user, :flash => { :success => "car created!" }
else
#redirect_to new_user_car_path,
flash[:notice] = "sorry try again"
end
end
def index
#car=Car.all
end
def show
#car = current_user.car.find(params[:id])
##car = Car.find(params[:id])
#redirect_to #user
end
end
and my routes.rb
Estaciones::Application.routes.draw do
root :to => "static_pages#home"
match '/contact', :to=>'static_pages#contact'
match '/about', :to=>'static_pages#about'
devise_for :users
resources :users do
resources :cars
end
my rake routes:
root / static_pages#home
contact /contact(.:format) static_pages#contact
about /about(.:format) static_pages#about
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
user_cars GET /users/:user_id/cars(.:format) cars#index
POST /users/:user_id/cars(.:format) cars#create
new_user_car GET /users/:user_id/cars/new(.:format) cars#new
edit_user_car GET /users/:user_id/cars/:id/edit(.:format) cars#edit
user_car GET /users/:user_id/cars/:id(.:format) cars#show
PUT /users/:user_id/cars/:id(.:format) cars#update
DELETE /users/:user_id/cars/:id(.:format) cars#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
this is the new.html.erb for new cars
<div class="container">
<h2>new car registration</h2>
<%= form_for(:users, :url => user_car_path(current_user)) do |f| %>
<div><%= f.label :brand %><br />
<%= f.text_field :brand %></div>
<div><%= f.label :color %><br />
<%= f.text_field :color %></div>
<div><%= f.label :model %><br />
<%= f.text_field :model %></div>
<div><%= f.label :year %><br />
<%= f.text_field :year %></div>
<div><%= f.submit "new car",:class => "btn btn-primary" %></div>
<% end %>
<%= link_to "new car", new_user_car_path(current_user)%>
should be ok given your route
new_user_car GET /users/:user_id/cars/new(.:format) cars#new
but the error says that a car#show (not new!) is missing, so maybe look for that.
When is the error exactly thrown?
ADDITION: now that you've posted the form,
I think the line producing the error is
<%= form_for(:users, :url => user_car_path(current_user)) do |f| %>
because user_car_path needs both a user and a car - so you would need
user_car_path(current_user,#car)
I've used just this in my form:
<%= form_for ([#user,#car]) do |f| %>
but the bottom line is, every time you're referencing a car, you need also the enclosing user reference.
I don't know if it is generating the problem, but why are you passin the current_user here:
<%= link_to "new car", new_user_car_path(current_user)%>
In your creation action, you are already getting the current user:
#car = current_user.Car.new(params[:car])
Also in your show action you have car and not Car
def show
#car = current_user.car.find(params[:id])
EDIT - based in your routes, I can see you have a nested resource:
your cars controller should be:
class CarsController < ApplicationController
def new
#user = User.find(params[:user_id])
#car = #user.cars.build
end
def create
#user = User.find(params[:user_id])
#car = #user.cars.build(params[:car])
if #car.save
flash[:notice] = "new car created success"
#redirect_to current_user, :flash => { :success => "car created!" }
else
#redirect_to new_user_car_path,
flash[:notice] = "sorry try again"
end
end
def index
#car=Car.all
end
...
And the link to create the new car is new_user_car_path
For what it's worth, I had a problem very similar to the one described by OP: the "index" action for my controller worked, but the "new" action threw the same exception ("show" route missing, which was not the case). It turned out Rails had some problem with the pluralization of my model name (ending in a 'y').
Rather than fighting the convention, I ended up choosing another model name with simpler pluralization and things were fine.
I've gone through the getting started with rails tutorial and now i'm trying to setup another project using the devise gem for authentication. Basically all i want is to have a home page, a page where the user can fill out a form to essentially signup, and then a secure page that does the authentication.
right now i'm having problems when i navigate to the signup page. Here's the error i'm receiving:
NoMethodError in Signup#index
Showing /Users/tomcaflisch/Sites/project2/app/views/signup/_form.html.erb where line #1 raised:
undefined method `users_path' for #<#<Class:0x007fa734b3e510>:0x007fa734b3a910>
Extracted source (around line #1):
1: <%= form_for(#user) do |f| %>
2: <% if #user.errors.any? %>
3: <div id="errorExplanation">
4: <h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved: </h2>
signup_controller.rb:
class SignupController < ApplicationController
def index
#user = User.new
end
def new
#user = User.new
respond_to do |format|
format.html
end
end
end
user.rb model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
end
../views/signup_form.html.erb:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.text_field :password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
routes.rb:
get "signup/index"
devise_for :users
get "index/index"
root :to => 'index#index'
$ bundle exec rake routes | grep user:
new_user_session GET /users/sign_in(.:format) {:action=>"new", :controller=>"devise/sessions"}
user_session POST /users/sign_in(.:format) {:action=>"create", :controller=>"devise/sessions"}
destroy_user_session DELETE /users/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"}
user_password POST /users/password(.:format) {:action=>"create", :controller=>"devise/passwords"}
new_user_password GET /users/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"}
edit_user_password GET /users/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"}
PUT /users/password(.:format) {:action=>"update", :controller=>"devise/passwords"}
cancel_user_registration GET /users/cancel(.:format) {:action=>"cancel", :controller=>"devise/registrations"}
user_registration POST /users(.:format) {:action=>"create", :controller=>"devise/registrations"}
new_user_registration GET /users/sign_up(.:format) {:action=>"new", :controller=>"devise/registrations"}
edit_user_registration GET /users/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"}
PUT /users(.:format) {:action=>"update", :controller=>"devise/registrations"}
DELETE /users(.:format) {:action=>"destroy", :controller=>"devise/registrations"}
It looks like you're mixing two things: devise provides it's own signup / registration pages, and you've also created your own.
Sometimes that's appropriate, but many times the default devise pages are good enough -- or at least good enough to start with.
I'd recommend you begin by trying to implement devise with it's own pages -- leaving your signin and signup pages alone for now. You don't see the devise pages because they are hidden inside the gem.
If you want to customize them, you can get the devise pages installed in your project (in a haml format) by following the steps here:
https://github.com/plataformatec/devise/wiki/How-To:-Create-Haml-and-Slim-Views
Because you are creating you're own signup controller, I believe devise routes are not routing where you like
post your routes file and lets see if we can get your routes straightened out.
It is looking for Signup#index .. It should be looking for SignupController#index
in your routes.rb you want to have
root :to => 'signup#index'
Also, undefined method users_path is missing its route to get the users or most likely missing resources :users from your routes.rb
For a new user you want something like form_for(User.new) which will hit UsersController#new
__
Or do it this way
1)
For views/users/new.html.erb you want
<%= form_for(#user) do |f| %>
<%= render 'fields', :f => f %>
....
with a route to it something like get '/signup', :to => 'users#new' and link_to 'Signup', signup_path
2)
For UsersController add
def new
#user = User.new
..
end
This question is admittedly long. So I appreciate any support from the rubytutorial community. I am in Chapter 9, attempting to create a session for a logged-in user.
I've done the tutorial already in < Rails 3.1. Since I am now using Rails 3.1, I headed on over to Chapter 13 and linked to the (very good) Railscasts (#270) on the subject. I was able to rewrite my user sign up pretty easily thanks to has_secure_password.
When I try to log in with a user in the database I see this in the console):
No route matches {:action=>"show", :controller=>"users"}
Seems like I need to create a route and it should work. But if that is the case, why can I go 'users/1' and the view appear? I am using the route user_path(#user), #user in my sessions and users controllers (below).
Here is what I did.
Pass a form to the Session controller new action (note: I use form_tag and not form_for)
<%= form_tag sessions_path do %>
<div class="field">
<%= label_tag :email %><br />
<%= text_field_tag :email, params[:email] %>
</div>
<div class="field">
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Sign In" %>
</div>
<% end %>
Then, create action in sessions_controller.rb
def create
#Assign object by email attribute
user = User.find_by_email(params[:email])
# User is present and has access, must be true otherwise nil object
if user && user.authenticate(params[:password])
session[:user_id] = user.id
RIGHT HERE IS THE PROBLEM
redirect_to user_path(#user), :notice => "Logged in!"
else
#Use flash.now on render not flash[]
flash.now.alert = "Invalid email or password"
render "new"
end
end
And finally Create action for users_controller.rb, which works fine.
def create
#user = User.new(params[:user])
if #user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render "new"
#user.password.clear
#user.password_confirmation.clear
end
end
Leaving my User model:
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
has_secure_password
Oh and here is my current routes.rb file
resources :users
resources :sessions, only: [:create, :new, :destroy]
root to: "pages#home"
match "/about", to: "pages#about"
match "/contact", to: "pages#contact"
match "/help", to: "pages#help"
match "/signup", to: "users#new"
match "/signin", to: "sessions#new"
match "/signout", to: "sessions#destroy"
And finally my output when I run rake routes:
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
sessions POST /sessions(.:format) {:action=>"create", :controller=>"sessions"}
new_session GET /sessions/new(.:format) {:action=>"new", :controller=>"sessions"}
session DELETE /sessions/:id(.:format) {:action=>"destroy", :controller=>"sessions"}
root / {:controller=>"pages", :action=>"home"}
about /about(.:format) {:controller=>"pages", :action=>"about"}
contact /contact(.:format) {:controller=>"pages", :action=>"contact"}
help /help(.:format) {:controller=>"pages", :action=>"help"}
signup /signup(.:format) {:controller=>"users", :action=>"new"}
signin /signin(.:format) {:controller=>"sessions", :action=>"new"}
signout /signout(.:format) {:controller=>"sessions", :action=>"destroy"}
It's your redirect_to #user and/or user_path(#user) lines. They generate requests to /users/:id, which apparently isn't in your routes.rb.
#user is nil in your example - you're assigning to user. What rails is telling you in a not very helpful way is that it can't route to :controller => 'users', :action => 'show' without a user.