Question

I have a resource, say Product, which can be accessed by two different user classes: say Customer and Admin. There is no inheritance between these two.

I am using Devise for authentication:

# config/routes.rb

devises_for :customers
deviser_for :admins

I have these two controllers:

# app/controllers/customers/products_controller.rb

class Customers::ProductsController < ApplicationController

and

# app/controllers/admins/products_controller.rb

class Admins::ProductsController < ApplicationController

Now depending on who logs in (Customer or Admin), I want products_path to point to the corresponding controller. And I want to avoid having customers_products_path and admins_products_path, that's messy.

So I have setup my routes as such

# config/routes.rb

devise_scope :admin do
  resources :products, module: 'admins'
end

devise_scope :customer do
  resources :products, module: 'customers'
end

This doesn't work. When I login as a Customer, products_path still points to Admins::ProductsController#index as it is the first defined.

Any clue? What I want to do might simply be impossible without hacking.

UPDATE According to the code, it is not doable.

No correct solution

OTHER TIPS

It turns out the best way to achieve that is to use routing constraints as such:

# config/routes.rb

resources :products, module: 'customers', constraints: CustomersConstraint.new
resources :products, module: 'admins', constraints: AdminsConstraint.new


# app/helpers/customers_constraint.rb

class CustomersConstraint
  def matches? request
    !!request.env["warden"].user(:customer)
  end
end


# app/helpers/admins_constraint.rb

class AdminsConstraint
  def matches? request
    !!request.env["warden"].user(:admin)
  end
end

I stored the constraint objects in the helper folder because I don't really know the best place to put them.

Thanks to @crackofdusk for the tip.

For this you will need to override the existing after_sign_in_path_for method of devise. Put this in your app/controllers/application_controller.rb

def after_sign_in_path_for(resource)

      if resource.class == Admin   

          '/your/path/for/admins'

      elsif resource.class == Customer

        '/your/path/for/customers'

      end 
end

Note: If you want to implement previous_url that was requested by user then you can use it like this:

  session[:previous_url] || 'your/path/for/admins'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top