简体   繁体   中英

Rails model_path routing error, no route matching “model.2”; should be “model/2”

There seems to be something wrong with my routing paths. Normally I should be able to do something like <%= link_to Profile, user_path(@user||current_user) %> and I move on with my day. For whatever reason I'm failing to understand my user_path is not returning /user/:id like I would expect it to do. Instead it is returning /user.:id To test this, I loaded a partial with the following code.

app/view/users/_test.html.rb

<%= @user %><br>
<%= @user.id %><br>
<%= link_to user_path(@user), user_path(@user) %><br>
<%= new_user_path %><br>
<%= edit_user_path(@user) %><br>
<%= url_for(@user) %>

This returned

localhost:3000/test

#<User:0x007fb6cd341f08>
1
/user.1
/users/new
/users/1/edit
/user.1

I can't figure out what is causing this to happen. The edit_user_path(@user) works perfectly, but the show doesn't. I have read the Rails Routing Guide from top to bottom about three times and I can't figure it out. The closest I found to my problem was on an old Rails 3.1 gem problem with Devise , but I'm not even using the Devise gem (maybe I should be?).

Why is my route failing? I'm not really looking for a workaround (though I suppose I'd rather have a workaround than no solution), I want to understand why this is happening and fix it. What's going on?

My routes are pretty vanilla, nothing special going on there, but just in case the problem is there and I missed it, here it is.

config/routes.rb

Rails.application.routes.draw do

  root 'static#home'

  %w( 404 406 422 500 503 ).each do |code|
    get code, :to => "errors#show", :code => code 
  end 

  #USER PAGES
  get '/test' => 'users#test'
  get '/signup' => 'users#new'
  post '/user' => 'users#create'
  get '/user/list' => 'users#index'
  post '/user/' => 'users#update'
  get '/user/:id' => 'users#show'
  get 'profile', to: 'users#show'

  resources :users
end

I'd suggest updating your routes as follows:

config/routes.rb

Rails.application.routes.draw do

  root 'static#home'

  %w( 404 406 422 500 503 ).each do |code|
    get code, :to => "errors#show", :code => code 
  end 

  #USER PAGES
  get '/test' => 'users#test'
  get 'profile', to: 'users#show', as: :user_profile

  resources :users
end

...as resources :users creates all of the routes I've removed.

The duplicates may have been overwriting a default path, causing the behaviour you're seeing - if you pass an object to a url helper that doesn't expect a parameter, you see the behaviour you're getting (ie doesnt_have_an_id_path(@object) => /doesnt_have_an_id.1 ).

I've also added a name to the user profile path to avoid this clashing. See if this works (perhaps one step at a time to get the cause and effect) - otherwise, try temporarily removing the profile route.

Re that path, you may have a problem in that the users#show action will expect an :id parameter, yet that route doesn't allow for one. This might be causing the current problem, though if not, may cause issues down the line.

Hope that fixes it - shout if you've any questions / feedback when you've tried it out.

In your case the two conflicting routes are:

post '/user/' => 'users#update'
get '/user/:id' => 'users#show'

You are trying to use user_path helper method, thus you need to have user named route. If you run rake routes for these two routes you will see this:

Prefix Verb URI Pattern         Controller#Action
  user POST /user(.:format)     users#create
       GET  /user/:id(.:format) users#show

The Prefix column shows you the named routes which are defined for your application. In this case Rails auto-generated named route user for POST /user endpoint. That means user_path will return /user instead of /user/:id as you expected. Rails generate routes like these when it sees a route definition without parameters. For example if you have get /user/some/more in your routes, Rails will auto-generate named route user_some_more for you and they you will be able to use user_some_more_path helper.

In order to fix your particular case you can stop rails from generating route for POST endpoint by doing this: post '/user/', as: nil and give GET endpoint a name you want: get '/user/:id', as: 'user' . Then you will be able to use user_path(user) to generate paths of format /user/:id.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM