rails: Regression in rails 4 when generating routes with optional scope

Hi! I just upgraded one application to rails 4 and I’m getting an error I didn’t expect. I’m sorry if I’m missing something and this is an intentional change.

When there’s an optional scope, link_to resource doesn’t seem to work properly in rails 4. I can change every link to link_to resource_path(id: resource.id) but that’s a lot of links to change and that kind of shortcut seemed nice and readable…

To reproduce copy and paste the following into a terminal

rails new optional_scope_routes_rails4
cd optional_scope_routes_rails4
rails generate scaffold post title body:text published:boolean
rake db:migrate
echo 'Post.create(title: "Hi", body: "Hello", published: false)' | rails c
cat <<EOF > config/routes.rb
OptionalScopeRoutesRails4::Application.routes.draw do
  scope '(:locale)', locale: /en|es/  do
    resources :posts
    root 'posts#index'
  end
end
EOF
cat <<EOF > app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :set_locale

  private
    def set_locale
      I18n.locale = params[:locale] || I18n.default_locale
      Rails.application.routes.default_url_options[:locale] = I18n.locale
    end
end
EOF
rails s

When I open the browser at 0.0.0.0:3000 I get the error

No route matches {:controller=>"posts", :action=>"show", :locale=>#<Post id: 1, title: "Hi", body: "Hello", published: false, created_at: "2013-09-09 18:44:45", updated_at: "2013-09-09 18:44:45">, :id=>nil, :format=>nil} missing required keys: [:id]

in optional_scope_routes_rails4/app/views/posts/index.html.erb line #21

<td><%= link_to 'Show', post %></td>

But in rails3 it works just fine… Open another terminal and try it with the following

rails _3.2.14_ new optional_scope_routes_rails3
cd optional_scope_routes_rails3
rails generate scaffold post title body:text published:boolean
rake db:migrate
echo 'Post.create(title: "Hi", body: "Hello", published: false)' | rails c
cat <<EOF > config/routes.rb
OptionalScopeRoutesRails3::Application.routes.draw do
  scope '(:locale)', locale: /en|es/  do
    resources :posts
    root :to => 'posts#index'
  end
end
EOF
cat <<EOF > app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :set_locale

  private
    def set_locale
      I18n.locale = params[:locale] || I18n.default_locale
      Rails.application.routes.default_url_options[:locale] = I18n.locale
    end
end
EOF
rm public/index.html
rails s -p3001

Thanks a lot in advance!

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Reactions: 2
  • Comments: 22 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I just run into this issue it seems like it exists in master branch (6.1?) still. In my case I have these routes

scope "(:team)" do
    resources :courses
    resources :users
  end
  • If I am on example.com/users, edit_user_path(user) will generate example.com/users/1/edit (which is expected)
  • If I am on example.com/5/users, edit_user_path(user) will generate same example.com/users/1/edit. I would expect it to be example.com/5/users/1/edit
  • If I am on example.com/5/users and use edit_user_path(id: user.id) it then generates expected url, example.com/5/users/1/edit, but it feels cumbersome adding id: user.id everywhere

Closing as this is super old and Rails 4 is end of lifed. If it’s still a problem today, let’s open a new issue so that’s more clear.

deivid-rodriguez, thank you for posting your code - it helps a lot! Its strange that there is not so much comments regarding this bug. Its really important and makes some troubles. Thanks for future fixing it in 5.0.0!