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.
Related
Explanation
I am wanting to set a user's security level when they register for an account. I don't want this to be a hidden field in the signup form as a person can then send in their own value to try and gain administrative privileges. So, it needs to be in the RegistrationController.
Versions
Ruby: 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
Rails: 4.2.0
Files
Here is what I have so far.
Added the following line to the app/config/routes.rb file:
devise_for :users, :skip => [:sessions, :registrations],
:controllers => { registrations: 'users/registrations' }
devise_scope :user do
get "login", to: "devise/sessions#new", as: :new_user_session
post "login", to: "devise/sessions#create", as: :user_session
delete "logout", to: "devise/sessions#destroy", as: :destroy_user_session
get "register", to: "devise/registrations#new", as: :new_user_registration
post "register", to: "devise/registrations#create", as: :user_registration
get "account/delete", to: "devise/registrations#cancel", as: :cancel_user_registration
get "user/profile/edit", to: "devise/registrations#edit", as: :edit_user_registration
patch "user", to: "devise/registrations#update"
put "user", to: "devise/registrations#update"
put "register", to: "devise/registrations#update"
delete "user/delete", to: "devise/registrations#destrony"
get "user/profile", to: 'devise/registrations#edit', as: :user_root
end
Here is my RegistrationController in the app/controllers/users/registration_controller.rb file:
class Devise::RegistrationsController < DeviseController
before_filter :configure_permitted_parameters, :only => [:create]
def create
super
resource.update_attribute(:security_level, '1')
end
end
My database does have a field called 'security_level' for all users.
Thank you in advance for any help that you can provide.
If you want to set security_level = 1, by default i would suggest you write it to the rails migration.
Code for migration
change_column_default :users, :security_level, '1'
If you want to do more by overriding the default devise crete function use the bellow code.
class RegistrationsController < Devise::RegistrationsController
def create
super do
resource.security_level = '1'
resource.save
end
end
end
You can face logic duplication problem in future (e.g. creating user from console will not force Rails to fill security level attribute, so you will need to control this in every place). Better to use callbacks in User model:
class User < ActiveRecord::Base
before_save :set_security_level
def set_security_level
self.security_level = 1
end
end
So, everytime User is going to be saved, :set_security_level will be executed.
Callbacks manual http://guides.rubyonrails.org/active_record_callbacks.html
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
struggling for a few hours on this one now. I have integrated the Devise gem into my Rails project after originally making my own auth system but I am facing an issue I can't understand.
When the user signs in the method:
def after_sign_in_path_for(resource_or_scope)
user = resource_or_scope
user_path(user.username)
end
Is triggered to redirect the user to their profile.
I have an edit user route which takes the user to a page in which they can edit their details and add a 'wanted item'. Two separate forms with two separate controllers and actions.
The 'add wanted item' method posts to a different controller that rendered the view called WantsController and adds a wanted item for the user through an association.
For some reason the after_sign_in_path_for method is called when submitting this form? It has nothing to do with signing in...
Here are my routes:
#users/auth
devise_for :users, :skip => [:sessions, :registrations]
devise_scope :user do
# registration
get "/signup", to: "users#new", as: :sign_up
post "/signup", to: "users#create", as: :sign_up_create
# account
get "/:username/account", to: "users#edit", as: :user_account
put "/users/:id", to: "users#update", as: :user_update
# shows
get "/:username", to: "users#show", as: :user
get "/:username/interests", to: "users#interests", as: :user_interests
get "/:username/offers", to: "users#offers", as: :user_offers
get "/:username/trades", to: "users#trades", as: :user_trades
# auth
post "/signin" => 'devise/sessions#create', as: :sign_in
delete "/signout", to: "devise/sessions#destroy", as: :sign_out
#wants
resources :wants, only: [:create, :destroy]
end
If I place the wants resource outside of the devise scope (which is where I expect it should go) I receive the following:
Could not find devise mapping for path "/wants"
What's happening here? Stumped!
Thanks.
Argh, silly mistake. Why is it after hours of struggling that when you post a question on Stack Overflow you figure it out after like 5 minutes?!
I had copied and pasted my RegistrationsController into the WantsController file to save typing the controller code but forgot to make it inherit from ApplicationController rather than Devise::RegistrationsController.
Lesson: Don't copy and paste!
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
It seems simple, in my model I have:
class CustomerAccount < ActiveRecord::Base
acts_as_url :name
def to_param
url # or whatever you set :url_attribute to
end
end
And in my controller, I have:
class CustomerAccountsController < ApplicationController
def show # dashboard for account, set as current account
#account = CustomerAccount.find_by_url params[:id]
no_permission_redirect if !#account.has_valid_user?(current_user)
set_current_account(#account)
#latest_contacts = Contact.latest_contacts(current_account)
end
end
What's currently in the routes.rb is:
resources :customer_accounts, :path => :customer_accounts.url do
member do
get 'disabled'
post 'update_billing'
end
end
That gives me the following error when I try to generate data via rake db:seed, or at least I assume the entry in routes is what's doing it.
undefined method `url' for :customer_accounts:Symbol
So what do I need to do to get the route set up? What I'd like is http://0.0.0.0/customeraccountname to map to the view for the customer account page.
UPDATE:
Here is the code that ended up working in routes.rb, which I discovered after looking at the examples in the answer below:
resources :customer_accounts, :path => '/:id' do
root :action => "show"
member do
get 'disabled'
post 'update_billing'
end
end
If you want to set it up so you have a route like you show, do this:
get '/:id', :to => "customer_accounts#show"
If you want the disabled and update_billing actions underneath this:
get '/:id/disabled', :to => "customer_accounts#disabled"
post '/:id/update_billing', :to => "customer_accounts#update_billing"
Alternatively (and much neater):
scope '/:id' do
controller "customer_accounts" do
root :action => "show"
get 'disabled'
get 'update_billing'
end
end