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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With