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]

On Wed, Aug 31, 2011 at 7:04 AM, Bruno M. [email protected]
wrote:

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

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.

On Wed, Aug 31, 2011 at 7:27 AM, Conrad T. [email protected]
wrote:

Thanks :smiley:

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

Rails Routing from the Outside In — Ruby on Rails Guides

Conrad T. wrote in post #1019393:

On Wed, Aug 31, 2011 at 7:04 AM, Bruno M. [email protected]
wrote:

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:

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

On Wed, Aug 31, 2011 at 10:04 PM, Bruno M. [email protected]
wrote:

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 Rails Routing from the Outside In — Ruby on Rails Guides

–

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

On Wed, Aug 31, 2011 at 10:51 PM, 7stud – [email protected] wrote:

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.

–

–

Jim ruther Nill wrote in post #1019405:

On Wed, Aug 31, 2011 at 10:51 PM, 7stud – [email protected] wrote:

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 constraint pretty easily, though:

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”

That will match only urls of the form:

/1
/123

and won’t match urls of the form:

/2ab
/a2b
/2b

On Wed, Aug 31, 2011 at 7:51 AM, 7stud – [email protected] wrote:

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 T. wrote in post #1019461:

On Wed, Aug 31, 2011 at 12:01 PM, Conrad T. [email protected]
wrote:

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]  #one digit, not 0
   \d*    #zero 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

On Wed, Aug 31, 2011 at 12:01 PM, Conrad T. [email protected]
wrote:

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*/ }

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

-Conrad

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

Good luck,

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

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

First, why don’t you actually give an example of the url that you want
to map to the show action??? You need to learn how to ask questions.
You should also give examples of the urls you don’t want to match.

Second, that regex does not meet your stated requirements. You may
think it works well, but that just means you didn’t test it thoroughly.
That regex matches “SallieMae2”.

Sent from my iPhone

On Aug 31, 2011, at 1:21 PM, 7stud – [email protected] wrote:

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

Bruno M. 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.

On Wed, Aug 31, 2011 at 3:07 PM, Bruno M. [email protected]
wrote:

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