I just implemented the password reset function via devise but after following the link I receive per email and resetting my password I get the following error:
No route matches [GET] "/users/password" (Routing Error)
I would assume the routing works through devise?
My code in routes.rb looks like this:
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
I didn't change anything under controllers > users > passwords_controller.rb but in case it's helpful to see it, it looks like this:
class Users::PasswordsController < Devise::PasswordsController
# GET /resource/password/new
# def new
# super
# end
# POST /resource/password
# def create
# super
# end
# GET /resource/password/edit?reset_password_token=abcdef
# def edit
# super
# end
# PUT /resource/password
# def update
# super
# end
# protected
# def after_resetting_password_path_for(resource)
# super(resource)
# end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)
# super(resource_name)
# end
end
Am I missing anything or did I do something wrong?
When I add "get 'users/password'" to routes.rb, I get the error:
The action 'password' could not be found for UsersController (Unknown action)
Any help would be highly appreciated!
I had same issue and couldn't find any solution.
There can be two reasons for this error
there is no rails-ujs (or jquer-ujs) javascript file working on this page
no recoverable in User model
But in my case, there was no problem with these two, and password was changed after error page so I fixed this error by adding line in routes.rb as follows:
Rails.application.routes.draw do
get 'users/password', to: redirect("/")
end
Make sure that you have recoverable in User model:
class User
devise :database_authenticatable,
:registerable,
:validatable,
:recoverable
end
Please let me know if it does not help you.
Related
i've started porting one of my apps from rails 3.x to rails 4.x....
when i start the app in development, i receive a route definition related error:
=> Booting WEBrick
=> Rails 4.2.5 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Exiting
/home/francesco/.rvm/gems/ruby-2.2.2#Best-i-gest_v2/gems/actionpack-4.2.5/lib/action_dispatch/routing/route_set.rb:549:in `add_route': Invalid route name, already in use: 'app_settings' (ArgumentError)
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:
http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
.....
here part of my routes.rb file containing the routes marked as double defined:
.....
get 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
put 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings' => 'admin/app_settings#index', :as => 'app_settings'
post 'app_settings/upload' => 'admin/app_settings#upload_logo', :as => 'app_settings/upload'
.....
i've defined these routes because i'm going to manage all actions related to application setting using the 'index' action only (the app has a single db record storing all settings, this record is automatically created at the first time the user will load page, then updated when it saves) as you can see here:
# only one record here! it will store all the application settings
def index
# manages all the controller actions inside the index...
if request.get?
# this is a get request... returns the first settings record or a new one if none exists!
#app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
elsif request.post?
# this is a post request, the settings record will be created
#app_settings = AppSettings.new(params[:app_settings])
#app_settings.save
elsif request.put?
# this will update the existing app_settings record
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(params[:app_settings])
end
# renders the index page
render "index"
end
i'm looking for a way to correct the routes.rb file (keeping my controller and view as is!!) or an alternative way to manage this issue!!
waiting your suggestions,
many thanks in advance for your time,
francesco
Seems like you have way too much logic in one method. I'm fairly sure even in rails 3 that wasn't acceptable.
What about using rest route ( resources as described in the rails routing guide )
resources :app_settings, only: [:index, :update, :create]
This will create three routes for index (geT), update (patch), create (post).
Your controller will now look like this:
def index
#app_settings = !AppSettings.all.first.nil? ? AppSettings.all.first : AppSettings.new
end
def create
#app_settings = AppSettings.new(params[:app_settings])
#app_settings.save
end
def update
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(params[:app_settings])
end
There will also be no need to use render 'index' ... rails will automatically look for /app/app_settings/index.html.erb
ok guys,
i've solved...
many thanks to Alexandre and Ryan who guided me in solving this issue.....
well,
Alexandre sure you're right!! too much logic inside a single action so...
here is the new version of my files:
routes.rb:
....
post 'app_settings/upload' => 'admin/app_settings#upload_logo', :as => 'app_settings/upload'
# site admin area
namespace :admin do
resources :app_settings, only: [:index, :update, :create]
resources :users
......
end
.....
as you can see, i've inserted app_settings route inside the admin namespace ..
app_settings_controller.rb:
# app_settings security settings - used for declarative authorization
filter_access_to [:index, :create, :update], :require => :manage
filter_access_to :upload_logo, :require => :manage
# app_settings index method (this replaces the show method so all actions will be managed in the index view page)
def index
# this is a get request... returns the first settings record or a new one if none exists!
#app_settings = !AppSettings.first.nil? ? AppSettings.first : AppSettings.new(id: 1)
#app_settings.save
end
# app_settings create method
def create
# this is a post request, the settings record will be created
#app_settings = AppSettings.new(app_settings_params)
#app_settings.save
# renders the index page
render "index"
end
# app_settings update method
def update
# this will update the existing app_settings record
#app_settings = AppSettings.find_by_id(params[:app_settings][:id].to_i)
#app_settings.update_attributes(app_settings_params)
# renders the index page
render "index"
end
......
as you can see, i've implemented your solution keeping the index view as only view used by the app, just for not changing too much inside the app....
i've fixed the declarative_authorization section accordingly with the modifications you've suggested and simplified the creation of the new record as Ryan suggested but adding a little extra (i've specified the record id and then saved the record itself) all to prevent another issue in my view where the form_for is declared as follows:
<!-- application settings edit form -->
<%= form_for [:admin, #app_settings] do |app_sett| %>
.....
.....
<% end %>
so many thanks again to you all!!
hoping to continue learning from you all the times i read a page of this site!!
regards,
francesco
When trying to authenticate using Omniauth, it works flawlessly in my development environment (Mac OSX Mavericks), but fails most of the time in production (on Heroku). The errors vary between "Invalid Credentials" and "Connection failed". In all cases, I'm already logged in to my Google account. I may get one or another of these errors anywhere between 4 and 8 times before the process succeeds.
Has anyone see this and can you shed some light on why this might be happening?
Gem: oa_openid (0.3.2)
config/routes.rb:
...
resource :admin_session, only: %w(show create destroy)
match '/auth/googleapps/callback' => 'admin_sessions#create'
...
config/omniauth.rb:
require 'openid/store/filesystem'
Rails.application.config.middleware.use OmniAuth::Strategies::GoogleApps,
OpenID::Store::Filesystem.new('./tmp'),
name: 'googleapps', domain: 'booktrakr.com'
admin_sessions_controller:
class AdminSessionsController < ApplicationController
# GET /admin_sessions
def show
redirect_to "/auth/googleapps?origin=#{params[:origin] || request.fullpath}" and return unless is_admin?
#session = authenticated_admin
end
# POST /admin_sessions
def create
authinfo = request.env['omniauth.auth']
uid = authinfo['uid']
unless uid =~ %r(^https?://(groundbreakingsoftware|booktrakr).com/openid)
raise "Bad hacker, no cookie"
end
self.authenticated_admin = authinfo
redirect_to request.env['omniauth.origin'], notice: 'Session was successfully created.'
end
# DELETE /admin_sessions
def destroy
self.authenticated_admin = nil
redirect_to root_url
end
end
It appears that switching to OAuth2 (https://github.com/zquestz/omniauth-google-oauth2) resolved the problem, at least at first blush. Thanks, #Ashitaka!
I've been pulling my hair out trying to get anything working with "def create" and "def update" in the users_controller.rb for Devise.
For instance, I've tried this:
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = "Test Save"
else
flash[:notice] = "Test Error"
end
end
end
I've used this code along with the appropriate code to show flash notices in the views section. However nothing is shown when I either submit a blank form, an incomplete form, or a complete form. The user registration will still go through on a complete form, but it does not follow anything I put in "def create". I've tried other ways of testing this aside from flash notices, such as sending to a different page, etc. I get no response. The same thing for "def update", it doesn't seem to even use that code.
I'm completely dumbfounded on this one, any ideas?
If i understand your question correctly, you should be overwriting the devise controller.
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
# add custom create logic here
end
def update
super
end
end
You can see what the default devise controllers are doing here:
https://github.com/plataformatec/devise/tree/master/app/controllers/devise
If you just want to edit the flash message, looking at the link above shows that devise uses a method called set_flash_message
# Sets the flash message with :key, using I18n. By default you are able
# to setup your messages using specific resource scope, and if no one is
# found we look to default scope.
# Example (i18n locale file):
#
# en:
# devise:
# registrations:
# signed_up: 'Welcome! You have signed up successfully.'
So you can just edit your devise.en.yml file with the correct text and voila!
Note: If you do overwrite the controller don't forget to also add
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
How about this instead?
if #user.save
redirect_to #user, notice: 'User was successfully created.'
else
render action: 'new'
end
You are setting the flash, but no redirection and no rendering. I'm wondering if you are getting a blank page, or a 200 with no body.
This will redirect to the show action, setting a flash notice if successful and render the new form with the #user.errors showing why it failed.
If you are using devise, you could use the Registrations Controller to create a new account, you shouldn't need to create a new one. If you create a new one, there might be a conflict in the routes with registrations#create and users#create both pointing to POST /users
I'm working on an e-commerce application. When a user logs into my app, I want to make a check to my external subscription handler and make sure that their subscription is still active and not expired/failed/whatever.
I successfully figured out how to use a Warden callback in my initializers/devise.rb to perform a check on the model after login. However, if there is a problem, I want to log them out again and redirect to a certain page that tells them what to do next.
Here is what I have. I know I can't use redirect_to from the callback. Given that, what is the best way to do what I'm trying to do?
Warden::Manager.after_authentication do |user, auth, opts|
begin
user.check_active_subscription # this works, and will raise one of several exceptions if something is goofy
rescue
redirect_to "/account/expired" # obviously this won't work, but see what I'm trying to do?
end
end
Just let the callback raise the exception and rescue from it in your controller. E.g.:
Warden::Manager.after_authentication do |user, auth, opts|
user.check_active_subscription
end
class SessionsController < ApplicationController
def create
# Authenticate
rescue SubscriptionExpiredException
# Logout
redirect_to "/account/expired"
end
end
You could also use rescue_from in your ApplicationController like this:
class ApplicationController
rescue_from SubscriptionExpiredException, :with => :deny_access
def deny_access
redirect_to "/account/expired"
end
end
We use CanCan. In our library application, a Book or Magazine can be checked out:
POST /books/123/loans # LoansController#new :book_id => 123
POST /magazines/456/loans # LoansController#new :magazine_id => 456
Books and Magazines have a parent class Stockable, so the above is equivalent to:
POST /stockables/123/loans # LoansController#new :stockable_id => 123
POST /stockables/456/loans # LoansController#new :stockable_id => 456
However, not every Stockable can be loaned:
# error: can't check out reference books from the library
POST /reference_books/789/loans # LoansController#new :reference_book_id => 789
# same error
POST /stockables/789/loans # LoansController#new :stockable_id => 789
What's the right way to write the LoansController with CanCan so that it can handle anything that's Loanable, without needing to make a specific route for everything that's Loanable?
I would just use ability.rb to define what actions are / are not allowed for each object type. The following is assuming you're using STI, and so there is a stockable_type column containing the name of the class each row represents in your db. If you aren't using STI you can still use another method to correctly determine object type (probably by passing a block to the can and cannot methods instead of using the hash syntax [check the CanCan wiki, Defining Abilities for more info]).
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can [:read], :all
can :new, Loan, :stockable_type => ["Book", "Magazine"]
cannot :new, Loan, :stockable_type => "ReferenceBook"
end
end
Then, just catch CanCan::AccessDenied in your LoansController and you can redirect people attempting to checkout reference books.
rescue_from CanCan::AccessDenied do |exception|
redirect_to some_url, :alert => "You can't check out reference books!"
end