I have a small problem that I cant track down. Basically I have my application controller and in my application controller I have a method:
def getCategories
#categories = Category.all
end
Nothing special I have a sidebar partial view that I load in to my main layout. This partial is loaded by almost all controllers/actions with few exceptions so to avoid always declaring this method i simply have a before_filter to invoke this method so that #categories are automatically included in all controllers.
The problem now is when I attempt to login using devise sign in view it tries to redirect me to root however for some reason the #categories are not included and in turn throw this exception:
NoMethodError in Devise::Sessions#create
Which is confusing because according to devise documentation if you set root :to => 'home#index' as in my case after processing user login user should be redirected to root which points to home controller which should due to before_filter include the #categoires variable.
What am I doing wrong here ?
Maybe you can try adding a new controller "Registrations" and add your method:
class RegistrationsController < Devise::RegistrationsController
def getCategories
#categories = Category.all
end
end
then Modify config/routes.rb to use the new controller
Modify your devise_for line in routes.rb to look like the below.
devise_for :users, :controllers => { :registrations => "registrations" }
replace root :to => 'home#index' with
devise_scope :user do
match "/", to: "devise/registrations#new", via: 'get'
end
Related
I have a problem with the devise gem, I have this controller.
class AdminController < ApplicationController
before_action :authenticate_user!
def index
end
def per
end
def po
end
end
When redirect to sign_in form , shows nothing
sign_in form
These are my routes:
match 'po' => 'admin#po', :via => :get
match 'per' => 'admin#per', :via => :get
match 'admin' => 'admin#index', :via => :get
match 'admin/index' => 'admin#index', :via => :get
match 'admin/per' => 'admin#per', :via => :get
match 'admin/po' => 'admin#po', :via => :get
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
root 'home#index'
I have three templates: application, admin and home
I overwrite the default route after log in
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
#before_action :authenticate_user!
def after_sign_in_path_for(resource)
#request.env['omniauth.origin'] || stored_location_for(resource) || admin_path
admin_path
end
end
My last gem installed:
gem 'bootstrap-sass'
You need to run the generator for Devise views which will copy the necessary files in your views folder:
Run:
rails g devise:views
There is more information on configuring the Devise views here
Your problem probably isn't with Devise, it looks systemic to me.
#config/routes.rb
namespace :admin do
root "application#index" #->
resources :model_controller, path: "", only: :index do #-> url.com/admin/...
collection do
get :po #-> you shouldn't really have this
get :per #-> you shouldn't really have this
end
end
end
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
This will give you the following:
#app/controllers/admin/application_controller.rb
class Admin::ApplicationController < ApplicationController
before_action :authenticate_user!
def index
# do something here
end
end
This gives you the ability to create a custom "dashboard" type page for your admin area, from which you'll be able to use controllers bound to models.
Your po and per actions really shouldn't be there - they are not part of the CRUD system
In regards to your Devise views, the other answers are correct in that you would be best to generate the Devise views in your app:
rails generate devise:views
This won't solve your problem (hence why I downvoted the other answers). It will simply put the views in your app. It will do nothing apart from put code in a different place.
You will need to debug the issue:
Check the action you're seeing at /users/sign_in
Check the code in the <body> tags (which you haven't shown)
If the HTML is there, there will be some other issue preventing it from loading
If there is no HTML, it will likely mean a problem with the core of Devise
What I would recommend you do is the following:
Generate your views
From your screenshot, show us the contents of the <body> tag
Screenshot your console log (this will show any errors)
Update your question with the above
This will give you a much clearer perspective on what the potential issue will be, and allow other community members to better define the solution.
I know how to override default controllers and it is working, but now I need to add new action into Registrations controller.
I need to update user fields. I need to add First and Last name in this form, but I don't want to use standard edit page, because it will be separate page.
So I need other page. I have paypal..html.erb in my registrations folder, but I can't render it from action in regustrations controller.
Paypal action:
class RegistrationsController < Devise::RegistrationsController
def paypal
end
...
end
routes.rb:
devise_for :users, :controllers => {:registrations => 'registrations', :sessions => 'sessions'} do
match 'paypal' => 'registrations#paypal'
end
but somehow it render new registration file. Here is error:
NoMethodError in Registrations#paypal
Showing C:/1508/app/views/devise/registrations/new.html.erb where line #22 raised:
How I can use update form to do this and what I'm doing wrong ?
I added this to my routes to make it work
devise_scope :user do
get 'paypal(/:id)', :action => 'paypal', :controller => 'user/registrations', :as => 'paypal'
end
Your question seems a little unclear, however Why not explicitly render the view?
def paypal
render 'devise/registrations/paypal'
end
If you have multiple type of users it may be better to separate out the paths and routing.
https://github.com/plataformatec/devise/wiki/How-To%3a-Customize-routes-to-user-registration-pages
Using devise 2.1.0
I am trying to send the new registration page a PricingPlan model.
So in my routes I have:
devise_scope :user do
delete "/logout" => "devise/sessions#destroy"
get "/login" => "devise/sessions#new"
get "/signup/:plan" => "devise/registrations#new"
end
And I override the devise registration controller. With this in my routes.rb to make it work:
devise_for :users, :controllers => {:registrations => "registrations"}
In my actual Registration controller which overrides Devise's controller I have:
class RegistrationsController < Devise::RegistrationsController
view_paths = "app/views/devise"
def new
super
#plan = PricingPlan.find_by_name(params[:plan])
end
So that the default views still go to devise....
In my new view for the registration controller I call this:
<h3>You've chosen the <%= #plan.name %> plan.</h3>
And I get this error:
undefined method `name' for nil:NilClass
Also... in my PricingPlan model:
class PricingPlan < ActiveRecord::Base
has_many :users
And in my User model:
class User < ActiveRecord::Base
belongs_to :pricing_plan
I'm rather new at rails.
For some reason your #plan is empty...
try changing the line below just to make sure that you are finding a plan...
#plan = PricingPlan.find_by_id(1)
if so, you are probabl trying to find by the wrong argument... do you have a column "plan" in your database?
#plan = PricingPlan.find_by_name(params[:______])
When I did a raise in my registration controller, I realize that when I was hitting /signup/:plan it wasn't hitting the registrations controller that I had overode from devises registration controller.
I figure out the reason:
Because I had made my own controller, the scope is no longer devises scope any more... So this was WRONG:
get "/signup/:plan" => "devise/registrations#new"
This however is CORRECT:
get "/signup/:plan" => "registrations#new"
So that part of my routes looks like this:
devise_scope :user do
delete "/logout" => "devise/sessions#destroy"
get "/login" => "devise/sessions#new"
get "/signup/:plan" => "registrations#new"
end
Everything else in the code stayed the same.
Thanks for #gabrielhilal for making me trace out the controller.
When a user who isn't signed in hits a url, devise will forward them to the sign-in page, after which it will forward the user on to their original page. How can I access this information (the original route/action) in the sign-in view? I'd like to show the gui differently depending on where the user is going.
So, you should extend/override devise's sessions controller. To do this, copy the latest new action code from here, and paste it in a controller (let's call it sessions) that inherits from devise's sessions controller, like this:
class SessionsController < Devise::SessionsController
def new
self.resource = build_resource(nil, :unsafe => true)
clean_up_passwords(resource)
#after_sign_in_url = after_sign_in_path_for(resource)
respond_with(resource, serialize_options(resource))
end
end
Since this controller inherits from Devise's, when an action isn't defined in your controller that action will be processed by Devise's controller. So you only have to override that new action.
Finally, edit your routes file so this change takes effect:
# routes.rb
devise_for :users, :controllers => { :sessions => 'sessions' }
Alternatively, if you are using a scope, like this:
# routes.rb
devise_scope :user do
get 'login' => 'sessions#new', :as => :new_user_session
end
You can now access #after_sign_in_url in your view!
I am using omniauth and found devise using a subfolder for this(in official example) controllers/users/omniauth_callbacks_controller.rb. I need to create a User show page as well as other actions for User so I decide to create a new UsersController inside a controllers/users folder. Now it looks like
class Users::UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
end
routes.rb
My::Application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
match 'users/:id' => 'users/users#show'
root :to => 'home#index'
end
it works but the route created is unnamed
rake routes gives
/users/:id(.:format) users/users#show
without GET and route_name
so I'm unable to use it for example after login redirect. Is there a better way to realize the subfolder routes structure and is it good idea to group controllers like this?
You just need name your route in your route.rb
match 'users/:id' => 'users/users#show', :as => 'user'
After that you can call this route by user_url(user.id)
See example on guides : http://guides.rubyonrails.org/routing.html#naming-routes