Search code examples
ruby-on-railsrails-routing

Rails query parameter with same name as optional path parameter


Suppose, I have this code in routes.rb

get "/items/(:brand)", to: "items#index", as: :items

I can't change this route, because sometimes I need urls with brand in path (not in query). Can I create path like this:

/items?brand=TestBrand

but not this:

/items/TestBrand

via route helpers?

items_path(brand: "TestBrand") give 2'nd variant.


Solution

  • This is not a very good solution as it violates the RESTful conventions.

    In Rails flavor REST GET /resource_name/:id maps to the show route. In the case of get "/items/(:brand)", to: "items#index", as: :items this creates an ambiguity (is the segment an item id or a brand?) when the router matches the requests and the first declared route will win which is hardly desirable.

    A better solution is to declare it as a nested resource:

    resources :brands, only: [] do
      resources :items, only: [:index], module: :brands
    end
    

        Prefix Verb URI Pattern                       Controller#Action
    brand_items GET  /brands/:brand_id/items(.:format) brands/items#index
    

    # app/controllers/brands/items_controller.rb
    module Brands
      class ItemsController < ::ApplicationController
        before_action :set_brand
    
        # GET /brands/:brand_id/items
        def index
          @items = @brand.items
        end
    
        def set_brand
          @brand = Brand.find(params[:brand_id])
        end
      end
    end