4

I am working with Devise gem and I created a show page for users. My idea was to make a simple path like www.website.com/:id and I configured it as shown below:

  devise_for :users, path: '', path_names: {sing_in: "login", sing_out: 
     "signout", sing_up: "signup", edit: "edit"}, 
     :controllers => {:registrations => :registrations }
  resources :users, only: [:show]
  get '/:id' => 'users#show', as: :profile

My routes work fine but besides show page, I have pages under static controller for example about page. I want to be able to access it like www.website.com/about, here is how I define my static routes:

get '/about', to: 'static#about'

Now, if I am trying to redirect to about page, I am getting an error:

ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with 'id'=about

Here is my users_controller.rb:

class UsersController < ApplicationController

  def show
    @user = User.find_by_id(params[:id])
    @services = @user.services
  end

  ...
end

I tried to search for the similar errors but haven't found anything like this. Can someone please tell me what I am doing wrong?

Thank you for your help and time.

Anton S.
  • 969
  • 1
  • 11
  • 29
  • 4
    Your route `get '/about', to: 'static#about'` should be defined before ` get '/:id' => 'users#show', as: :profile` route – lightalloy Dec 13 '17 at 13:37
  • 3
    Assuming you expect digits in users calls and letters in static pages calls, you can use constraints: http://guides.rubyonrails.org/routing.html#specifying-constraints – Marek Lipka Dec 13 '17 at 13:38
  • 1
    @lightalloy it was my first thought, but it won't work, since it's really call to static pages controller, as Author wrote. – Marek Lipka Dec 13 '17 at 13:38
  • @MarekLipka Thank you for your answer. What if letter on I want to add numeric values to other pages (ex.:`www.website/123`)? Is there any other similar solution? – Anton S. Dec 13 '17 at 13:41
  • Routes are matched from top to bottom. Did @lightalloy’s suggestion not work for you? http://guides.rubyonrails.org/routing.html – inveterateliterate Dec 13 '17 at 14:00
  • @inveterateliterate it does, but I am trying to figure out the problem that Marek Lipka highlighted – Anton S. Dec 13 '17 at 14:02

1 Answers1

7

Two things here:

  • Routes are ignorant of param types
  • Routes are matched top to bottom

In this case, I suspect that your single level routes are being defined your get '/:id' route. Therefore, that route is catching all requests which are /anything because the router thinks anything is a parameter.

Simply move your route definition below any other /about etc routes so that they are matched first.

Like this:

get '/about', to: 'static#about'
get '/:id' => 'users#show', as: :profile
Daniel Westendorf
  • 3,375
  • 18
  • 23
  • added a code example and it's also good to be aware @AnthonyBrooks that you need to add validation to prevent user's from having the same id/slug/name as any defined route; this will prevent user frustration (just in case someone does try to put in 'about' as their username ;-) ) –  Dec 13 '17 at 19:57
  • @RudolfOlah wow, I haven't thought about it... good point! Thank you very much! – Anton S. Dec 14 '17 at 03:14