Firmin
Firmin

Reputation: 15

No route matches {:action=>"show"

I have a view which lists all my comparisons

index.html.erb

<% @comparisons.each do |comparison| %>
 <div class="col-xs-6 col-sm-4 col-md3">
  <p><%= comparison.title %></p>
  <p><%= comparison.id %></p>
  <p><%= comparison.description %></p>
 </div>
<% end %>

Up to now, all is going well : title, description and id are displayed for each comparison.

I tried to add a Show link :

<% @comparisons.each do |comparison| %>
 <div class="col-xs-6 col-sm-4 col-md3">
  <p><%= comparison.title %></p>
  <p><%= comparison.id %></p>
  <p><%= comparison.description %></p>
  <p><%= link_to 'Show', comparison_path(comparison) %></p>
 </div>
<% end %>

But now, when I load index.html.erb I have this error :

No route matches {:action=>"show", :controller=>"comparisons", :format=>nil, :id=>nil, :locale=>#<Comparison id: 1, title: "coucou", description: "", created_at: "2015-07-04 10:33:47", updated_at: "2015-07-04 10:33:47", user_id: 1>} missing required keys: [:id]

I don't understand why...

comparisons_controller.rb

class ComparisonsController < ApplicationController
 before_action :set_comparison, only: [ :show ]
 skip_before_action :authenticate_user!, only: [ :index, :show ]

 def index
  @comparisons = policy_scope(Comparison)
 end 

 def show
 end

 def new
  @comparison = current_user.comparisons.new
  authorize @comparison
 end

 def create
  @comparison = current_user.comparisons.new(comparison_params)
  authorize @comparison

  if @comparison.save
   # redirect_to comparison_path(@comparison)
   # redirect_to @comparison
   render :show
  else
   render :new
  end
 end

 private

 def set_comparison
  @comparison = Comparison.find(params[:id])
  authorize @comparison
 end

 def comparison_params
  params.require(:comparison).permit(:title, :description, :user_id)
 end
end

By the way, as you can see, in create action, I have not been able to use a redirect_to. But render :show works : the show.html.erb view is loaded. Any risks to use render rather redirect_to ?

My routes

                  Prefix Verb   URI Pattern                          Controller#Action
        new_user_session GET    /users/sign_in(.:format)               devise/sessions#new
            user_session POST   /users/sign_in(.:format)             devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)            devise/sessions#destroy
           user_password POST   /users/password(.:format)            devise/passwords#create
       new_user_password GET    /users/password/new(.:format)        devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)       devise/passwords#edit
                         PATCH  /users/password(.:format)            devise/passwords#update
                         PUT    /users/password(.:format)            devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)              devise/registrations#cancel
       user_registration POST   /users(.:format)                     devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)             devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)                devise/registrations#edit
                         PATCH  /users(.:format)                     devise/registrations#update
                         PUT    /users(.:format)                     devise/registrations#update
                         DELETE /users(.:format)                     devise/registrations#destroy
                    page GET    (/:locale)/pages/:id                 high_voltage/pages#show {:locale=>/fr/}
             comparisons GET    (/:locale)/comparisons(.:format)     comparisons#index {:locale=>/fr/}
                         POST   (/:locale)/comparisons(.:format)     comparisons#create {:locale=>/fr/}
          new_comparison GET    (/:locale)/comparisons/new(.:format) comparisons#new {:locale=>/fr/}
              comparison GET    (/:locale)/comparisons/:id(.:format) comparisons#show {:locale=>/fr/}
                    home GET    /home(.:format)                      redirect(301, /)
                    root GET    /                                    high_voltage/pages#show {:id=>"home"}

routes.rb

Rails.application.routes.draw do
 devise_for :users

 scope '(:locale)', locale: /fr/ do
  get 'pages/:id' => 'high_voltage/pages#show', :as => :page, :format => false
  resources :comparisons, only: [ :index, :show, :new, :create ]
 end
end

Thanks in advance for your help.

Upvotes: 0

Views: 875

Answers (4)

Firmin
Firmin

Reputation: 15

Previous answers made me realize I had a routing issue with i18n : locale parameter was not considered in urls building.

In application_controller.rb I still have

before_action :set_locale

private

def set_locale
 I18n.locale = params[:locale] || I18n.default_locale
end

I add this second method which automatically add the locale parameter to urls

def default_url_options
 { locale: I18n.locale == I18n.default_locale ? nil : I18n.locale }
end

Now, it works fine.

Thanks for your help.

Upvotes: 1

Elvn
Elvn

Reputation: 3057

It seems to me using :shallow_path would be the answer. From the documentation.

The :path, :as, :module, :shallow_path and :shallow_prefix options all default to the name of the namespace.

I think this will remove (/:locale) from the raked routes

 scope '(:locale)', locale: /fr/, :shallow_path => '(:locale)' do
  get 'pages/:id' => 'high_voltage/pages#show', :as => :page, :format => false
  resources :comparisons, only: [ :index, :show, :new, :create ]
 end

Upvotes: 0

Prashant4224
Prashant4224

Reputation: 1601

Alternatively you can use like this:

<% @comparisons.each do |comparison| %>
  <div class="col-xs-6 col-sm-4 col-md3">
    <p><%= comparison.title %></p>
    <p><%= comparison.id %></p>
    <p><%= comparison.description %></p>
    <p><%= link_to 'Show', comparison %></p>
  </div>
<% end %>

Upvotes: 0

aash
aash

Reputation: 1323

Seeing from your routes files, it looks to me that to construct a route, you need two parameters - locale and id. Since you are using comparison_path(comparison), rails is assuming that the first parameter you are passing refers to locale.

To construct a correct route, use a cleaner way to construct a route - like this:

comparison_path(locale: 'en', id: comparison.id)

Upvotes: 1

Related Questions