How do I get my "show" page to render? - ruby-on-rails

I have Rails 5 installed. I'm having trouble getting my show page to render. My rake routes has this
votes_show GET /votes/show(.:format) votes#show
Then in my app/controllers/votes_controller.rb file I have
def show
id = params[:id]
# If there is no person selected based on the param, choose one randomly
if !id.present?
#person = Person.order("RANDOM()").limit(1).first
else
#person = Person.find(:id => params[:id])
end
but when I go to http://localhost:3000/votes/1, I get a
No route matches [GET] "/votes/1"
error. I'm missing something real obvious. What is it?

votes_show GET /votes/show(.:format) votes#show
this line is telling rails that "when you see a route that is /votes/show then go to the VotesController#show method."
When you then type in /votes/1, rails is checking that against the routes and not finding a route that looks like that... it is specifically looking only for /votes/show
As mentioned in the comments, you must add a line like:
get '/votes/:id(.:format)', to: 'votes#show'
or better yet, use resourceful routes like
resources :votes

Related

route is redirecting to wrong path

This is what my routes currently look like:
which gives
On my homepage I have a create vacancy button
<%= link_to "plaats", new_employer_vacancy_path(:employer_id)%>
Which should be linked to the line from the first image
get '/employers/:employer_id/vacancies/new', to: 'vacancies#new', as: 'new_employer_vacancy'
In the vacancies_controller#new - create I have:
def new
#vacancy = Vacancy.new
#employervacancy = Employervacancy.new
end
def create
#vacancy = Vacancy.create(vacancy_params)
createEmployervacancy
redirect_to employer_vacancy_path(current_employer, #vacancy)
end
def createEmployervacancy
#employer = current_employer
Employervacancy.create(vacancy_id: #vacancy.id, employer_id: #employer.id)
end
But whenever I click the button I get redirected to some other method in my vacancies_controller that is totally irrelevant.
How is this even possible? Don't I clearly define that when that path is clicked he should go to vacancies#new? and not to vacancies#show_specific_employer_vacancies?
EDIT
After following the answers I am indeed being linked to the correct route.
First, it gave me this error.
After trying to pass the current_employer.id instead of #employer like suggested I got following error:
For your routes, you'd better to change into nested route for easily maintaining routes.
Remove these codes:
get '/employers/:employer_id/vacancies/:id', to:"vacancies#show_specific_employer_vacancies", as: "employer_vacancy"
get '/employers/:employer_id/vacancies/edit/:id' ...
get '/employers/:employer_id/vacancies/index' ...
get '/employers/:employer_id/vacancies/new' ...
path '/employers/:employer_id/vacancies/:id' ...
change into:
resources :employers do
resources :vacancies
end
Try to use basic routes here because you use standard simple form url. For example:
<%= simple_form_for(#employee, #vacancy) %>
The simple_form_for will generate url well if you use nested routes above.
Finally, in your link you have to add #employer_id
<%= link_to "plaats", new_employer_vacancy_path(:employer_id => #employer_id)%>
I hope this help you
Your router cannot tell the difference between your employer_vacancy and new_emplyer_vacancy routes because the :id parameter accepts anything. Because of this, when you point your browser to "/employers/5/vacancies/new", the route is taking your employer_vacancy route and assigning {:employer_id => 5, :id => "new"} instead of going to your new_employer_vacancy route (because routes are first-come-first-serve).
To correct this, add a constraint to your first route to ensure that only numbers (and not the string "new") is accepted into the employer_vacancy route:
get '/employers/:employer_id/vacancies/:id',
to: 'vacancies#show_specific_emplyer_vacancies',
as: 'employer_vacancy',
constraints: { id: /\d+/ } # <- This line
As Wes Foster said rails router is trying to find a first match.
It means that given a path /employers/999/vacancies/new your router looks through the routes and when it sees get '/employers/:employer_id/vacancies/:id he thinks that this route matches. So :employer_id is 999 and :id is new.
I'd suggest to put the route with :id at the end of employers routes:
...
get '/employers/:employer_id/vacancies/new'
...
get '/employers/:employer_id/vacancies/:id'
Btw this is better than adding a constraint because:
It is easier
It doesn't pollute routes file
Later you may want to change ids to be hashed or alphabetic and then you'd have to change the constraint

Including attributes in custom Rails routes

I hope the title is not to misleading, as I don't know a better title for the problem I'm working on:
I have a doctor which belongs to location and specialty. I'd like to route to show action of the doc controller like this:
/dentist/berlin/7
I defined my routes like this:
get ':specialty/:location/:id', to: 'docs#show'
And in my views create the following url to link to the show action of the doc controller:
<%= link_to doc.name, "#{doc.specialty.name}/#{doc.location.name}/#{doc.id}" %>
Is this a good solution to the problem? If not, is there a cleaner way to construct urls like this possibly using resources? What the heck is the name for a this problem?
Thank your very much for your help in advance.
For references, you should have a look at this page (especially the end of section 2.6)
If it is only for a single route, it's okay as you did. But then if you want to have more than one route (like /dentist/berlin/7, /dentist/berlin/7/make_appointment, etc.) you might want to structure a bit more your routes so as to take advantage of rails resources.
For example, instead of
get ':specialty/:location/:id', to: 'doctors#show'
get ':specialty/:location/:id/appointment', to: 'doctors#new_appointment'
post ':specialty/:location/:id/appointment', to: 'doctors#post_appointment'
You could have something like this (the code is almost equivalent, see explanation below)
resources :doctors, path: '/:specialty/:location', only: [:show] do
member do
get 'new_appointment'
post 'create_appointment'
end
end
Explanation
resources will generate the RESTful routes (index, show, edit, new, create, destroy) for the specified controller (doctors_controller I assume)
The 'only' means you don't want to add all the RESTful routes, just the ones specified
Then you want to add member actions, ie. actions that can be executed on a particular item of the collection. You can chose different syntaxes
resources :doctors do
member do
# Everything here will have the prefix /:id so the action applies to a particular item
end
end
# OR
resources :doctors do
get 'new_appointement', on: :member
end
By default, the controller action is the same as the path name you give, but you can also override it
member do
get 'appointment', action: 'new_appointment'
post 'appointment', action: 'post_appointment'
end
Rails has some wonderful helpers when it comes to routing !
The correct approach is to give your route a name, like this:
get ':specialty/:location/:id', to: 'docs#show', as: 'docs_show'
Then you can use it like this:
<%= link_to doc.name, docs_show_path(doc.specialty.name, doc.location.name, doc.id) %>
Note 1:
Rails appends _path at the end of the route names you define.
Note 2:
You can see all the available named routes by executing rake routes.

How to display a friendly name in URL in rails

This is my new resource in routes file :
resources :staticpage do
collection do
get :aboutus
get :snacks
get :contactus
end
end
this generates my urls localhost:3000/staticpage/aboutus localhost:3000/staticpage/snacks/ localhost:3000/staticpage/contactus
Instead of this complex url i want to have localhost:3000/aboutus , localhost:3000/snacks/ localhost:3000/contactus in the URL.
using gem can change my action name, but i want to alter "controllername/action" to a simple string.
What modification should be done in the routes path declaration ?
You can simply write matchers for each route like this:
get 'aboutus', to: 'staticpage#aboutus'
get 'snacks', to: 'staticpage#snacks'
get 'contactus', to: 'staticpage#contactus'
Note that you don't need the resources or collection block if you do this.
As per the routes documentation, you will need to define the routes manually (like David Underwood's answer). However, there is an even better way to do it:
#config/routes.rb
static = %w(aboutus snacks contactus)
static.each do |page|
get page.to_sym, to: "staticpage#show", page: page
end
#app/controllers/staticpages_controller.rb
def show
page = params[:page]
render "staticpages#{page}"
end

Routing in rails - When to route to a crud method and when to route with the given parameter

I am in need of a little help regarding routing in rails. Traditionally if I have a route in routes.rb
resources:categories
it will match www.website.com/categories/id were id is an integer. But what happens if I wanted to route to a specific user or category like so:
www.example.com/categories/apple
instead of the traditional:
www.example.com/categories/4
I currently have these two lines in my routes.rb
match 'categories/:name' => 'categories#show'
resources :categories
so www.example.com/categories/apple will route to the show method in the categories controller correctly.
but
What if I want to create a new category? Here's the problem
www.example.com/categories/new
will route to the show method, and will not route to the new method
I can place an if statement in the show method checking is params[:name] == new, but I feel that there must be a better way to solve this problem.
My end goal is to route based on the string of the category (apple) and not based on it's ID (4) but also be able to create, update, and destroy a category.
Any tips?
Thanks!
you can pass a name as a parameter, for example you can try
link_to category_path(category.name) instead of link_to category_path(category)
and it will go to categories#show in controller, the route will look like example.com/categories/categoryName, in the show action of your cateogries controller, params[:id] will have the name, you'll need something like
Category.find_by_name params[:id] instead of Category.find params[:id]
Hope this helps you.
As #pdoherty926 says in the comment, you could use FriendlyId. If you want to manage it manually, you don't have to overwrite the routes, just put the needed code in the :show action:
class CategoriesControllers < ...
...
def show
if /^\d+$/ =~ params[:id]
# ... normal workflow for integer id
elsif /soe_regexp_that_matches_names>/
# ... do your thing with names
else
raise 404
end
end
...
end
I think the most simple way to do this your way is to define a route before your
match 'categories/:name' => 'categories#show'
like this:
match 'categories/new' => 'categories#new'
match 'categories/:name' => 'categories#show'
the order matters.

Rails route not working

I created a new route and a corresponding method in a controller and view:
routes.rb:
get "pictures/user/:username" => 'Pictures#user'
pictures_controller.rb:
def user
#pictures_user = User.where(username: params[:username]).first
render 'user.html.erb'
end
user.html.erb:
Just some simple html/erb
I get this following error. I know the user method is being entered, seems to be a problem rendering the view?
Routing Error
No route matches {:controller=>"pictures", :action=>"user", :username=>"my_username", :page=>nil}
What am I missing?
user.html.erb is inside the same directory of views/pictures? just do
render 'user'
should be fine i think
and I guess your Pictures downcase will be better ##
get "pictures/user/:username" => 'pictures#user'

Resources