CatBrownie
CatBrownie

Reputation: 150

Rails 4 route constraints with query string or numbers only

I'm trying to implement these two routes with constraints:

get "products/:id", to: "products#show", constraints: { id: /\d/ }
get "products/:name", to: "products#search", constraints: { name: /[a-zA-Z]/ }

The first route should trigger with an URL like localhost:3000/products/3 and the last one should trigger with localhost:3000/products/?name=juice.

Doesn't work, I googled a lot about this problem but I seem to find solutions for the second or third version of Ruby on Rails, and most of them are deprecated now.

Any ideas? Thanks.

Upvotes: 2

Views: 3187

Answers (4)

Lucas Nelson
Lucas Nelson

Reputation: 2551

You can use the routes as-is if you like the look of the resulting URLs. No need for a query string.

In your controller, you'd have something along these lines:

def show
  @product = Product.find(params[:id])
  # do stuff
end

def search
  # I'm assuming your Product model has a `name` attribute
  @product = Product.find_by(name: params[:name])
  # do stuff
end

You probably want some error checking on find_by returning nil because :name did not match anything, but that's basically it.

Your routes.rb would have your original route definition:

get "products/:id", to: "products#show", constraints: { id: /[[:digit]]/ }
get "products/:name", to: "products#search", constraints: { name: /[[:alpha:]]/ }

Your application should respond to both:

  • localhost:3000/products/3
  • localhost:3000/products/juice

Upvotes: 5

PJSCopeland
PJSCopeland

Reputation: 3006

It might be easier and more Railsy just to specify a different route:

get "products/:id",          to: "products#show"
get "products/search/:name", to: "products#search"

Or, just have your products#index action handle params[:q] as the search string, that's quite common too. Then your URL would be www.example.com/products?q=juice.

Upvotes: 0

PJSCopeland
PJSCopeland

Reputation: 3006

I have a feeling the regex matching might be a little different in routes - I think it anchors to the start and end of the parameter every time.

With that in mind, your regexes are matching a single character each. Try id: /\d+/ and name: /.*\D.*/ instead.

Upvotes: 1

Auli
Auli

Reputation: 74

First you have to know what the query string and url. localhost:3000/products/3 this is url and the three is symbol :id when use question mark localhost:3000/products/3?name=juice, name=juice is query string.

So get "products/:name", to: "products#search", constraints: { name: /[a-zA-Z]/ } you should replace below

get "products/:id?name=:name", to: "products#search", constraints: { id: /\d/,
                                                                name: /[a-zA-Z]/ }

example: localhost:3000/products/3?name=xxxxx

Upvotes: 1

Related Questions