Search code examples
ruby-on-railsruby-on-rails-3routesruby-on-rails-3.1

Rails singular resource does't seem to generate 'user_path'


I have the following routes in my 3.1.0.rc5 app

# config/routes.rb
devise_for :users
resources :users, only: :index
resource :user

THe idea here is that I use devise for session management, the 'users' resource just to generate the users_path for the index action and then most other user actions would be accessible via routes like

  • GET user_path -> show action
  • GET new_user_path -> new action
  • POST user_path -> create action

The user_path route helper doesn't seem to be generated though, whenever I try to use it in a view, I get a weird error when rails tries to render it.

For example, on the /user/new page, I have the following

<%= form_for @user, :url => user_path do |f| %>
  # omitted form elements
<% end %>

When rails tries to render the page I get

ActionView::Template::Error (No route matches {:action=>"destroy", :controller=>"users"}):
    7: </div>
    8: 
    9: <div class="content_middle">
    10:   <%= form_for @user, :url => user_path do |f| %>
    11:   <fieldset>
    12:     <%= render partial: "form_errors" %>
    13: 
  app/views/users/new.html.erb:10:in `_app_views_users_new_html_erb___1548382046039026466_2191201580'

What's up with that!?

Edit Here is the content of rake routes. It's pretty massive so I cut it down to just the user related routes.

       new_user_session GET    /users/sign_in(.:format)                     {:action=>"new", :controller=>"devise/sessions"}
           user_session POST   /users/sign_in(.:format)                     {:action=>"create", :controller=>"devise/sessions"}
   destroy_user_session DELETE /users/sign_out(.:format)                    {:action=>"destroy", :controller=>"devise/sessions"}
          user_password POST   /users/password(.:format)                    {:action=>"create", :controller=>"devise/passwords"}
      new_user_password GET    /users/password/new(.:format)                {:action=>"new", :controller=>"devise/passwords"}
     edit_user_password GET    /users/password/edit(.:format)               {:action=>"edit", :controller=>"devise/passwords"}
                        PUT    /users/password(.:format)                    {:action=>"update", :controller=>"devise/passwords"}
                  users GET    /users(.:format)                             {:action=>"index", :controller=>"users"}
                        POST   /users(.:format)                             {:action=>"create", :controller=>"users"}
                   user DELETE /users/:id(.:format)                         {:action=>"destroy", :controller=>"users"}
                        POST   /user(.:format)                              {:action=>"create", :controller=>"users"}
               new_user GET    /user/new(.:format)                          {:action=>"new", :controller=>"users"}
              edit_user GET    /user/edit(.:format)                         {:action=>"edit", :controller=>"users"}
                        GET    /user(.:format)                              {:action=>"show", :controller=>"users"}
                        PUT    /user(.:format)                              {:action=>"update", :controller=>"users"}

Solution

  • It might make sense to have a Profile or CurrentUser controller in this situation. It would eliminate any routing conflicts you may be having with Devise, and also, it makes sense from a RESTful point of view as you're treating the current user as a distinct resource.

    devise_for :user
    resources :users, :only => :index
    resource :profile