0

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.

3
  • 1
    get "/items/(:brand)", to: "items#index", as: :items is a pretty bad route as it violates the RESTful conventions and creates and ambiguity with the normal show route (GET /items/:id). Why can't you change it to something better like GET /brands/:brand_id/items? Commented Apr 16, 2018 at 13:33
  • I need support large chunk with legacy code :(, in reality this code is much complicated than my example Commented Apr 16, 2018 at 14:01
  • Well then you need to decide if its time for a breaking change since the existing code may not actually work as intended. Commented Apr 16, 2018 at 14:39

3 Answers 3

3

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
Sign up to request clarification or add additional context in comments.

Comments

0

Additional parameters in "get" are supported by default, so maybe you could use

get "/items", to: "items#index", as: :items

or

resources :items, only: [:index]

And use path helper which you provided:

items_path(brand: "TestBrand")

2 Comments

get "/items/(:brand)", to: "items#index", as: :items See my question please, I need use route with conditional parameter
If you need both variants, add them to routes: get "/items", to: "items#index", as: :items and get "/items/(:brand)", to: "items#index", as: :brand_items BTW, max right, it is not very RESTfull. Maybe it would be better to think about changing behavior.
0

To answer your question - Yes, you can

get "/items", to: "items#index", as: :items

and the following route helper will create

items_path(brand: "TestBrand")
#=> items?brand=TestBrand

NOTE:

If you are using:

recourses :items

You must alredy have this

1 Comment

get "/items/(:brand)", to: "items#index", as: :items I can't change this, because sometimes I need urls with brand in path (not in query)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.