Routing Question

I have the following problem: - I have a controller called UsersController and I need to restrict the show URL to use only numbers, How can I do that? my routes.rb has this line: resources :users, :except=>[:destroy] How I add this constraint in this line? I know that there is a command :constraints, but I dont know how to use in resources ;/ Thanks :smiley:

How about:

match '/:id' => 'users/show' resources :users, :except=>[:destroy]

I have the following problem:

  • I have a controller called UsersController and I need to restrict

the show URL to use only numbers, How can I do that?

my routes.rb has this line:

resources :users, :except=>[:destroy]

How I add this constraint in this line?

I know that there is a command :constraints, but I dont know how to

use in resources ;/

Thanks :smiley:

Bruno, I would recommend reading section 4.2 of the Rails routing guide:

http://guides.rubyonrails.org/routing.html

Good luck,

-Conrad

7stud -- wrote in post #1019391:

How about:

match '/:id' => 'users/show' resources :users, :except=>[:destroy]

Sorry, that doesn't meet your requirements because both '/1' and '/show/1' will match.

I have the following problem:

  • I have a controller called UsersController and I need to restrict

the show URL to use only numbers, How can I do that?

my routes.rb has this line:

resources :users, :except=>[:destroy]

How I add this constraint in this line?

I know that there is a command :constraints, but I dont know how to

use in resources ;/

look at http://guides.rubyonrails.org/routing.html#segment-constraints

I have the following problem:

  • I have a controller called UsersController and I need to restrict

the show URL to use only numbers, How can I do that?

my routes.rb has this line:

resources :users, :except=>[:destroy]

How I add this constraint in this line?

I know that there is a command :constraints, but I dont know how to

use in resources ;/

Thanks :smiley:

Bruno, I would recommend reading section 4.2 of the Rails routing guide:

http://guides.rubyonrails.org/routing.html

http://guides.rubyonrails.org/routing.html#specifying-constraints

Conrad Taylor wrote in post #1019393:

Conrad Taylor wrote in post #1019393:

Bruno, I would recommend reading section 4.2 of the Rails routing guide:

I read that, and I don’t see how applying a regex to the id will help.

How about adding :show to the :except clause and doing this:

match ‘/:id’ => ‘users/show’

having this line will match any controller’s index action so i think that’s not fine

unless you place this at the bottom of your routes file.

resources :users, :except=>[:destroy, :show]

in the Segments Constraints section of the rails guide, you’ll see the first line of code.

following that code, you can use

match ``'users/:id' => ``'users#show'``, ``:constraints => { ``:id => /``\d``/ }, :via => :get

the via option is important so that it will only match get requests.

Hi All, Thanks for answer my question. I read Rails Routing from the Outside In — Ruby on Rails Guides and I guess that the best way to resolve my problem is do like Jim said, put the route in match and add except constraint in resource. Thanks All ;D

Jim ruther Nill wrote in post #1019405:

match '/:id' => 'users/show'

having this line will match any controller's index action

Ah, I see. :id will match anything, e.g.

/dog /frog /users /pages /hello_world /1 /200

in the Segments Constraints section of the rails guide, you'll see the first line of code. following that code, you can use

match 'users/:id' => 'users#show', :constraints => { :id => /\d/ }, :

..and the constraint there says to only match a number in the :id position of the url. But is that route any different than the show route created by resources()? It was my understanding that the op wanted a url consisting of only a number, so I think the route should be more like:

match '/:id' => users#show, :constraints => {:id => /\d+/}, :via => 'get'

via => :get

the via option is important so that it will only match get requests.

I wonder why people post ambiguous questions and expect people who read them to know what they are thinking--instead of giving a simple example that leaves nothing in doubt.

However, that will still match routes like:

/a2b

It looks like you can write a custom matcher pretty easily, like this:

class UserShowConstraint   def matches?(request)

    request.path =~ /        \A #start of string        \/ #forward slash        \d+ #one or more digits        \z #end of string     /x

  end end

And then use the route:

match "*id" => "user#show", :constraints => UserShowConstraint.new, :via => "get"

Conrad Taylor wrote in post #1019393:

Bruno, I would recommend reading section 4.2 of the Rails routing guide:

I read that, and I don’t see how applying a regex to the id will help.

How about adding :show to the :except clause and doing this:

match ‘/:id’ => ‘users/show’

resources :users, :except=>[:destroy, :show]

If you apply the regex to the :id, then one can restrict the value of

the :id to one or more digits. In the above, :id is simply a placeholder

and can accept any value. Thus, the following should work for the

original poster:

match ‘/:id’ => ‘users#show’, :constraints => { :id => /[0-9]+/ } resources :users, :except=> [ :destroy, :show ]

Good luck,

-Conrad

Conrad Taylor wrote in post #1019393:

Bruno, I would recommend reading section 4.2 of the Rails routing guide:

I read that, and I don’t see how applying a regex to the id will help.

How about adding :show to the :except clause and doing this:

match ‘/:id’ => ‘users/show’

resources :users, :except=>[:destroy, :show]

If you apply the regex to the :id, then one can restrict the value of

the :id to one or more digits. In the above, :id is simply a placeholder

and can accept any value. Thus, the following should work for the

original poster:

match ‘/:id’ => ‘users#show’, :constraints => { :id => /[0-9]+/ }

A much better regular expression which matches a value of an :id should be something like the following:

match ‘/:id’ => ‘users#show’, :constraints => { :id => /[1]\d*/ }

Note: The above says that I have at least one digit >= 1 starting with the first digit.

-Conrad


  1. 1-9 ↩︎

Conrad Taylor wrote in post #1019461:

I read that, and I don't see how applying a regex to the id will help.

match '/:id' => 'users#show', :constraints => { :id => /[0-9]+/ }

A much better regular expression which matches a value of an :id should be something like the following:

match '/:id' => 'users#show', :constraints => { :id => /^[1-9]\d*/ }

There are still a couple problems with that regex:

1) There is no ending anchor so an id of '10A' would match. 2) You can't use anchors in a regexp for a constraint anyway.

This works for me:

class UserShowConstraint   def matches?(request)     dirname, id = File.split(request.path)     return false unless dirname == '/users'

    id =~ /        \A #start of string        [1-9] #not 0        \d* #one or more digits, including 0        \z #end of string     /x

  end end

TestApp::Application.routes.draw do

  root :to => "pages#home"

  resources :users, :except => [:show]   match "/users/*id" => "users#show", :constraints => UserShowConstraint.new, :via => "get"

I do like Conrad said and the code works well. Thx ;D

My constraint stayed like that: :constraints => { :id => / [1-9]\d*/ }

First, why don't you actually give an example of the url you want to map to the show action???

Second, that regex does not meet your requirements. You may think it works well, but that just means you didn't test it well enough.

Hi 7stud, I wanted a URL like that: /users/:id, where :id could only be one or more integers, actually the user id. I don't have in mind any case that this line could'nt be resolve. Could you give me an example? Thx ;D

Conrad Taylor wrote in post #1019461:

I read that, and I don't see how applying a regex to the id will help.

match '/:id' => 'users#show', :constraints => { :id => /[0-9]+/ }

A much better regular expression which matches a value of an :id should be something like the following:

match '/:id' => 'users#show', :constraints => { :id => /^[1-9]\d*/ }

The above can easily be fixed by adding a $ after the *. For example,

/^[1-9]\d*$/

The x after the final / isn't needed being that the begin and end tokens take care of that for you. Also, you can do all this in the context of a routes.rb using the constrains option to match. Thus, one shouldn't have to define a method in a separate file unless there's plan to do this for other controller actions. If this is the case, then this becomes a one line method that returns a regex. In short, the Rails 3 routing provides much of what you're doing below out of the box.

Good luck,

-Conrad

Hi 7stud,

I wanted a URL like that: /users/:id, where :id could only be one or

more integers, actually the user id.

I don’t have in mind any case that this line could’nt be resolve.

Could you give me an example?

Thx ;D

If this is the case, then I would recommend just simply using the following and deal with the error case within the action:

resources :users

For example,

def show

@user = User.find( params[:id] ) # This will generate an exception if the value of the params[:id] doesn’t exist (i.e. AR::RecordNotFound).

…

end

def show

@user = User.find_by_id( params[:id] ) # This will return nil if the value of the params[:id] doesn’t exist.

…

end

In both cases above, you’ll have to deal with the case where the record does not exist. For example, this would be in the form of

a ‘Page Not Found’ for your site or something similar. In short, I would just use resources as resources and provide a good user

experience when an error does occur. However, there are cases when constrains work well but I don’t think this is a good use case

for it.

Good luck and have fun,

-Conrad

Bruno Meira wrote in post #1019487:

Hi 7stud, I wanted a URL like that: /users/:id, where :id could only be one or more integers, actually the user id. I don't have in mind any case that this line could'nt be resolve. Could you give me an example? Thx ;D

Sure, your route+constraint matches the url:

  /users/SallieMae5

and therefore it does not meet your stated requirements.