Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Devise 1.1.3 gotcha…

Mike Gehard
Friday, November 5, 2010

In the continued saga that is the Rails 2.3.10 to Rails 3.0.1 upgrade, I found this little nugget today…you want to add a custom action to a controller that inherits from a Devise controller. Here are the steps that you need to follow:

1) Create a custom controller that overrides some out of the box Devise actions as well as adds a new method.

class RegistrationsController < Devise::RegistrationsController
  def update
     # do something different here
  end

  def deactivate_owner
    # deactivate code here
  end
end

2) You have to tell Devise to use the new controller in routes.rb as well as add the new route to the new action.

devise_for :owners, :controllers => { :registrations => "registrations" } do
  post "deactivate_owner", :to => "registrations#deactivate_owner", :as => "deactivate_owner_registration"
end

When we initially implemented this, our route definition looked like this:

post "deactivate_owner", :to => "registrations#deactivate_owner", :as => "deactivate_owner_registration"
devise_for :owners, :controllers => { :registrations => "registrations" }

When it was implemented this way, we kept getting a AbstractController::ActionNotFound exception. Once we passed the block to devise_for seen in #2, everything worked fine.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

8 Comments

  1. José Valim says:

    Exactly! In Devise 1.0.x we used the URL to try to guess which scope was being accessed.

    In Devise 1.1 use the constraints API in the router to tell which scope is being accessed. So you can either define your route inside devise_for or use “devise_scope” or “as” method.

    This gives more flexibility to allow you to access whatever URL you want through Devise. :)

    In Devise master we also improved the error message when AbstractController::ActionNotFound is raised, so people have a better idea of what happened.

    November 7, 2010 at 2:36 pm

  2. Mike Gehard says:

    Thanks for the note Jose and thanks for making Devise great! I’m really enjoying using it, especially the new version for Rails3.

    November 7, 2010 at 3:00 pm

  3. John Bruce says:

    This was an absolute life saver, thank you for this post! I’m performing this exact customization now and couldn’t figure out the abstract controller error.

    November 9, 2010 at 12:13 pm

  4. Bharat Ruparel says:

    Hello Mike,
    I am trying to follow your advise for my customization work and not having much luck with it.
    So instead of RegistrationsController, I call my controller UsersController as shown below:

    class UsersController < Devise::RegistrationsController
    skip_before_filter :require_no_authentication <-- I override this

    def index
    # shows a list of users
    end

    def new
    @user = User.new
    @user.build_profile <-- for has one profile relationship
    end

    def change_status
    # marks a user as active or inactive
    end
    ...
    end

    To account for this and following your advise here, I have the following entries in the routes.rb file:

    FileManager::Application::routes.draw do

    devise_for :users, :controllers => {:registrations => “users”} do
    get “index”, :to => “users#index”, :as => “index”
    end

    resources :users <- if I don’t do this I get the following error
    # no route matches /users
    end

    If you can provide some further guidance, I will appreciate it.
    Thanks.

    Bharat

    December 1, 2010 at 2:57 pm

  5. Mike Gehard says:

    Bharat,

    I am confused about what further guidance you need. Is there a specific problem you are having or error you are seeing?

    Mike

    December 2, 2010 at 5:59 am

  6. Bharat says:

    Hello Mike,
    Thanks for your response and willingness to help out. I found a nice reference which is more inline with what I was trying to do and things are working now. Here is the reference:

    https://github.com/fortuity/rails3-mongoid-devise

    I will be posting my application on the github guite soon so that everyone can benefit from it. Currently, it uses authlogic which I am replacing with Devise and CanCan. Here is the URL:

    http://github.com/bruparel/file_manager3

    Regards,
    Bharat

    December 2, 2010 at 1:22 pm

  7. Steve says:

    Dang I wish I had seen this blog post before I dug into the Devise source code to figure out why it kept throwing UnknownAction exceptions.

    One thing to note is that if you want to add a route that might interfere with the other Devise routes (ie, users#show at “users/:id”), you need to define them after the call to `devise_for`):

    devise_for :users, :controllers => {:registrations => “users”}
    devise_scope :user do
    get “users/:id”, :to => “users#show”, :as => “user”
    end

    December 5, 2010 at 12:46 am

  8. Law says:

    Yes! It works. I’m starting to think Devise needs a serious round of documentation. Who’s on that? if no one, i volunteer. I just have to learn the hell out of it first. I’m still not convinced that it’s so much better than Authlogic. But then Authlogic has no documentation either.

    December 10, 2010 at 10:56 am

Add New Comment Cancel reply

Your email address will not be published.

Mike Gehard

Mike Gehard
Boulder

Recent Posts

  • Using Jasmine to test CoffeeScript in a Rails 3.1 App
  • Waiting for jQuery Ajax calls to finish in Cucumber
  • Mocking Fog when using it with Carrierwave
Subscribe to Mike's Feed

Author Topics

coffeescript (1)
rails3 (10)
capybara (6)
cucumber (12)
javascript (2)
jquery (1)
webdriver (5)
carrierwave (1)
fog (1)
s3 (2)
testing (1)
rspec2 (3)
omniauth (1)
ruby (5)
devise (1)
aruba (2)
generators (2)
solr (1)
sunspot (1)
concerns (1)
mixins (1)
resque (1)
thin (1)
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >