Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails username in URL

Trying to use a username in my rails routes.

Routes that are working:

resources :users, only: [:show, :create, :update, :destroy]
get "/:username" => "users#show", as: :user
get "/:username/account" => "users#account", as: :user_account
get "/:username/interests", to: "users#interests", as: :user_interests
get "/:username/offers" => "users#offers", as: :user_offers
get "/:username/trades" => "users#trades", as: :user_trades

but now a route such as this:

get "/signup" 

is being matched to the /:username rule

I know I can reorder my routes so that /signup appears before, but this seems a bit hacky.

Are there any ways I can rewrite this? Or is the only method to have a reserved usernames validation?

Thanks

EDIT

I ended up adding a validation to the user model with reserved words. Namespacing is a good idea but I don't want to pollute my URLS.

For the record, Twitter namespace non-usernames like this: twitter.com/i/discover (goes to Twitter discover section) twitter.com/discover (goes to @discover's profile)

Pinterest reserve names such as 'search' as far as i can tell

I followed Pinterest's approach with code:

validation:

validate :reserved_username

private

    def reserved_username
      reserved_usernames = %w[index show create destroy edit update signup interests interest item items search offers offer community about terms privacy admin map authentication]
      errors.add(:reserved_username, "username is reserved for the app") if reserved_usernames.include?(username)
    end
like image 918
Adam Waite Avatar asked May 28 '13 15:05

Adam Waite


1 Answers

Routes have priority in order of definition, with earlier overriding later. If you want your /signup path to work, it needs to be defined before the /:username one. This isn't hacky, this is just how it works.

It is possible to exclude certain matches for :username, but this slows down your routing if the list gets to be long, or you'll have to re-write it as a regular expression, which is probably the definition of hacky here.

When you're creating root paths for arbitrary usernames, you should think about creating a prefix for all of your other routes so they won't conflict. For example, /=/signup or /-/signup. You could also use something like /_signup if you disallow underscores at the beginning of usernames, or some other way of defining an exclusion you can use to assign all your other routes through.

This way you won't have to worry about checking the user database before introducing a new feature, or creating a long, exhaustive list of invalid names.

like image 111
tadman Avatar answered Sep 20 '22 06:09

tadman