Using Devise Gem with namespaces throwing ActionController::RoutingError - ruby-on-rails

Ok, I've seen a ton of different answers for how to get Devise working when using namespaces in your app, but none of them are working for me.
I have my app split up into three namespaces
Home (the public landing pages)
Account (the logged in profile/account of the user)
Admin (the admin backend which isn't written yet)
I've also split up all the partials into a base folder in each namespace. So each of my controllers inherit from the BaseController which inherits from the ApplicationController:
module Account
class UsersController < BaseController
end
end
And I created a sessions_controller.rb in both account and home that inherits from the devise sessions controller like this:
module Account
class SessionsController < BaseController < Devise::SessionsController
end
end
The goal is to have a login/ registration form in the Home namespace that lets users login to the users controller that is in the account namespace.
Right now when I click on the link generated by:
<%= link_to "register", new_user_registration_path %>
I'm getting
ActionController::RoutingError at /users/sign_up
uninitialized constant Account::RegistrationsController
My routes.rb file looks like this:
scope :module => "account" do
devise_for :users, :controllers => { :sessions => "account/sessions" }
resource :users
end
scope :module => "home" do
resources :home, :about, :jobs, :terms, :privacy, :android_availability, :about, :contact
end
get "home/index"
root :to => 'home::home#index'
end
The home controllers use a home layout and the account controllers use the application layout. I specify layout "home" in the home controllers, but I don't specify layout "application" in the account controllers because application is the default layout rails looks for.
Ok. I think I've covered all my bases. Any idea what I'm doing wrong here?
Thanks!
EDIT:
Ok, I've added a registrations_controller.rb file to the account namespace in the same way as the sessions_controller.rb file described above.
I also updated the routes.rb file:
scope :module => "account" do
devise_for :users, :controllers => {
:sessions => "account/sessions",
:registrations => "account/registrations" }
resource :users
end
Now I'm getting a new error that I don't understand. Here it is:
NoMethodError at /users/sign_up
undefined method `action' for Account::RegistrationsController:Class
It says the undefined method 'action' is in (gem) actionpack-3.2.11/lib/action_dispatch/routing/route_set.rb which doesn't make any sense.
Specifically is says the problem is here:
def dispatch(controller, action, env)
controller.action(action).call(env)
end
EDIT 2:
Here is the code from my registrations_controller.rb
module Account
class RegistrationsController < BaseController < Devise::RegistrationsController
end
end
EDIT 3:
module Account
class BaseController < ApplicationController
end
end
Ok, the above is my base_controller.rb, which just inherits from the ApplicationController. All the other controllers inherit from BaseController. Because I've split my app into three namespaces, the base_controller is there to tell the other controllers in the namespace that the partials are in a folder named base within their namespace. As shown in this RailsCast
I get a missing partial error if I don't incude the BaseController because the devise controllers can't find the partials.

Read your errors! :-)
For starters, looks like you need to define an Account::RegistrationsController, the same way you did your Account::SessionsController.

Related

Custom action route inheritance in Rails

I have the following controller inheritance chain (note that models do NOT inherit, but rather have a parent-child relationship): EmployeesController < SitesController < CompaniesController
I have an action, companies#dashboard that the subclasses inherit. Right now this is my routing:
get "/company/dashboard(/:disguised_id)" => "companies#dashboard"
get "/site/dashboard(/:disguised_id)" => "sites#dashboard"
get "/employee/dashboard(/:disguised_id)" => "employees#dashboard"
But I'm wondering if there's a more elegant way to set up this inheritance chain for a custom action?
You can use routing concerns to reuse sets of routes:
Rails.application.routes.draw do
concern :dashboard do
get '/dashboard(/:disguised_id)', action: :dashboard
end
scope :company, controller: :companies do
concerns :dashboard
end
scope :site, controller: :sites do
concerns :dashboard
end
scope :employee, controller: :employees do
concerns :dashboard
end
end
Concerns can be included in scope, namespace, resource and resources. A better solution here would be to use namespaces together with a separate dashboard controller:
Rails.application.routes.draw do
concern :dashboard do
get '/dashboard(/:disguised_id)', to: 'dashboard#show'
end
namespace :companies, path: 'company' do
concerns :dashboard
end
namespace :sites, path: 'site' do
concerns :dashboard
end
namespace :employees, path: 'employee' do
concerns :dashboard
end
end
This lets both lets you offload a responsibility from the normal controller which is already responsible for CRUD'ing the resource and use inheritance:
class DashboardController < ApplicationController
def show
# do something awesome
end
end
module Companies
class DashboardController < ::DashboardController
end
end
module Sites
class DashboardController < ::DashboardController
end
end
module Employees
class DashboardController < ::DashboardController
end
end
I guess what you would like to do, is just DRY the routes, isn't it?
You might do that easier by having the only route for 3 resources. Let's say it would be "pages#dashboard". So you need the pages controller with dashboard. I use pages controller for landing pages, faqs, dashboard and e.t.c. So these are static routes that usually never changes. Because I won't delete dashboard, landing page, or FAQ section.
Then in dashboard you might render company_dashboard, site_dashboard or employee_dashboard depending on the resource.
And finally, you might have the only path in routes or do it like:
get "/dashboard", to: "pages#dashboard"
Of course, you might create another controller "dashboard" with "index" and serve the logic up there. But because I don't know your code or future design ideas, I might be wrong by advising the most easiest solution for me. But what I mean, is that probably you don't need 3 different controllers for dashboard.

Can't find controller method in rails application

When I go to my page /step/3 I got this message
Unknown action
The action 'step3' could not be found for UsersController
My routes.rb:
get '/step/3', :to => 'users#step3'
This method define in controller Users
class UsersController < ApplicationController
def step3
...
end
end
Early it's work fine, but I can't understend why it stop work correctly
P.S. Other controllers works fine
try defining your route.rb as match '/step/3', :to => 'users#step3'

Reuse Devise authentication for custom controller

I am trying to create a custom controller in the admin section of Spree and reuse the devise authentication mechanism. How do I go about doing this. I have simply tried to do the following:
module Spree
module Admin
class WorkflowController < Spree::Admin::BaseController
end
end
end
And I created a route like this:
namespace :admin do
resources :workflow, :only => [:index, :show]
end
I am getting the following error:
ActionController::RoutingError (uninitialized constant Admin):
So, any thoughts on how to best create a custom controller or am I just doing something wrong with this?
This is happening because your controller is nested inside the Spree namespace, but your routes are not. If you want to extend Spree's routes, then do this:
Spree::Core::Engine.routes.draw do
namespace :admin do
resources :workflow, :only => [:index, :show]
end
end

Setup devise with custom registration controller

I'm working on a rails site using devise, where we do not want user sign ups just yet. User authentication is so we can login to access restricted parts of the site and add/edit things as we see fit. So for now, I created the following controller:
class Users::RegistrationController < Devise::SessionsController
def new
end
end
And setup my routes in this fashion:
devise_for :users, :controllers => { :registration => "users/registration" }
However, when I run rake routes, I still see a returned value for the create action on the registration controller. Any ideas on how to get rid of it?
Try using :registrations instead of :registration. Also, it seems like your custom controller class should be defined via:
class Users::RegistrationsController < Devise::RegistrationsController

Routing errors when adding an Admin namespace

I added an Admin namespace to my app so when logging in to the administration area, it would have to be like this: admin/websites and admin/page/8
So this is what I have in my routes.rb
namespace :admin do |admin|
match '/' => 'dashboard#index'
resources :websites
resources :pages
resources :sessions
get 'login' => 'sessions#new', :as => 'login'
get 'logout' => 'sessions#destroy', :as => 'logout'
end
I have admin_controller.rb in app/controllers directory.
class Admin::BaseController < ApplicationController
protect_from_forgery
include UrlHelper
...
I created an admin directory inside app/controllers. So I have this inside app/controllers/admin/websites_controller.rb
class Admin::WebsitesController < ApplicationController
Some other answers suggested class Admin::WebsitesController < Admin::BaseController, but that never worked for me. If I'm wrong please let me know.
So then in my layout file (app/views/layouts/application.html.erb) I have links like this one edit_admin_website_path(#website) that give me routing errors Routing Error No route matches {:action=>"edit", :controller=>"admin/websites"} Whyyyy?! :(
Add a file named application_controller.rb in the admin directory with this content:
class Admin::ApplicationController < ApplicationController
end
Then, for each controller on this directory, extend the Admin::ApplicationController class.
Did you try this?
admin_edit_website_path(#website)
Rails namespaces rely on folder structure for loading the right classes. You should structure it like this:
app/controllers
admin_controller.rb # class AdminController < ApplicationController
app/controllers/admin
websites_controller.rb # class Admin::WebsitesController < AdminController
The AdminController should be defined outside the admin folder. If put it in there you'd have to refer to it as Admin::AdminController which is a little odd. In fact, you could call it AdminNamespaceController to be clear.
You can also use rails generate which will set things up for you in the expected places, although I don't think it creates the namespace base class for you to inherit from.

Resources