Rails get routing with parameter - ruby-on-rails

I want to create a new route in my routes.rb which points to a "courses" controller which has the method pdfdownload. The route is supposed to take 2 parameters: course_id and user_id. I thought it should be like this:
get "/courses/pdfdownload/:course_id/:user_id"
The courses controller and everything works fine until I add the line above. The courses controller has a method called pdfdownload. Nevertheless, when I try to start the server (rails s), I get the following error:
warning: already initialized constant Mime::PDF
warning: previous definition of PDF was here
Exiting
`default_controller_and_action': missing :controller (ArgumentError)
When I type rake:routes I get:
missing :controller
The courses controller is existing and is working very well with many methods. After I altered the line to this:
get "/courses/pdfdownload"
The server starts.
The rails guides says at "3.2 Dynamic Segments", it has to be written this way:
get ':controller/:action/:id/:user_id'
Whats wrong here? Thank you very much!
Update: I'm using the following link in the view:
<%= link_to "PDF", courses_pdfdownload_path(#course.id, user.id) %>

Please have a try
get "/courses/pdfdownload/:course_id/:user_id" => "courses#pdfdownload", :as => "courses_pdfdownload"

try match "/courses/pdfdownload/:course_id/:user_id" => "courses#pdfdownload"

The correct route would be:
get '/courses/pdfdownload/:course_id/:user_id', to: 'courses#pdfdownload'
But for a nicer REST route, I would rather change it to this:
get '/courses/pdfdownload/:id/:user_id', to: 'courses#pdfdownload'
The fact that the action deals with a Course resource is already implied by the name of the controller handling the action. So you don't need to call the Course id :course_id, simply :id is enough.
Edit
Note also that you can customize the name of the route helper like this:
get '/courses/pdfdownload/:id/:user_id', to: 'courses#pdfdownload', as: 'courses_pdfdownload'
Your route helper will then be courses_pdfdownload_path.

As for the errors,
warning: already initialized constant Mime::PDF
warning: previous definition of PDF was here
this is due to Rails registering PDF by default since 2011. No need to register them in config anymore.
https://github.com/rails/rails/commit/d73269ba53992d8a01e5721aad3d23bc2b11dc4f

Related

ruby on rails- non-existent route

I have a controller file,
abc_controller.rb.
I have defined the show method inside it.
I have a view file,
show.html.haml
inside app/views/abc/
In my routes.rb file, I am giving the following command
resources :abc
I have a button
= link_to 'abc', abc_path, class: 'btn btn-default'
But when I click on the button, its not going to the new page.
I am getting non-existent route error.
Since I am a newbie to rails, I am not able to figure what the problem is.
You are getting a error because there is no such path as abc_path. Run rake routes and you'll see the routes that Rails understands. In you example, resources :abc produces the following routes.
abc_index GET /abc(.:format) abc#index
POST /abc(.:format) abc#create
new_abc GET /abc/new(.:format) abc#new
edit_abc GET /abc/:id/edit(.:format) abc#edit
abc GET /abc/:id(.:format) abc#show
PATCH /abc/:id(.:format) abc#update
PUT /abc/:id(.:format) abc#update
DELETE /abc/:id(.:format) abc#destroy
The first column are the named routes. So in order to get to the index action of abc_controller, the route is named abc_index_path. There is an abc_path but it needs an id params which means that you need to pass something to it. In your case, there's no definitive value to pass to this method so as a trial just use abc_path(1) which will redirect you to /abc/1. This goes to the show action with params[:id] set to 1.
If you do resources (plural) the resulting route for show requires an id: /abc/:id(.:format), so abc_path requires that you pass that :id or a object. If you are dealing with a singular abc (resource :abc), the resulting path doesn't require that :id, so you code should work (this is less common, but hard to tell with your "abc" example.

Invalid route name for GET and POST

I'm working through an older tutorial that was done for Rails 3. I'm using Rails 4.1.4.
One of the instructions is to change the routes file to include the following:
get '/boards/:board_id/conversations/:id/reply' => "conversations#reply", :as => :reply_board_conversation
post '/boards/:board_id/conversations/:id/reply' => "conversations#save_reply", :as => :reply_board_conversation
Obviously that gives me an error:
Invalid route name, already in use: 'reply_board_conversation'
It seems to me that the route is somehow trying to replicate the behaviour of a new and create action. Get for new and Post for create with a single route.
The problem is I can't figure out how to rewrite the route so it works. I've googled for solutions but can't seem to find anything. If anyone could point me in the right direction it would be hugely appreciated.
It looks like the only issue is with the duplicated "named route" name reply_board_conversation. So you could simply change one. I'd probably rename the save version to save_reply_board_conversation. Then it should work. Just remember to refer to the route this way in the future. This would primarily be used in a form tag. So, for exmaple:
<= form_tag :url => save_reply_board_conversation_path do %>
Note the use of save_reply_board_conversation_path instead of reply_board_conversation_path given that the form would be submitting a POST request instead of a GET request.
The names for these routes should be different although since the composition of the URL is the same so you really only need a name for the first one.
The trick with named routes is they generate the URL only, they do not set the HTTP request method. That has to be done independently.
That means you can call the same named route two different ways:
<%= link_to('View', board_path(#board)) %>
<%= link_to('Delete', board_path(#board), method: :delete) %>
These actually render as the same URL but one will hit the GET route, the other the DELETE one.

Why did Ruby on Rails' URL Helper put a period in my URL?

I have the following code in my view (RoR 4):
tbody
- #order_submissions.each do |order_submission|
tr
td = order_submission.id
td.table-actions
span = link_to "Show", order_submissions_path(order_submission.id)
td = order_submission.id
successfully displays as the ID number (533ab7337764690d6d000000)
But...
order_submissions_path(order_submission.id)
Creates a URL that comes out as:
order_submissions.533ab7337764690d6d000000
I want it to be
order_submissions/533ab7337764690d6d000000
Where did that period come from?
This is my route:
get 'order_submissions/:id' => 'order_submissions#show'
And when I run rake routes I get:
GET /order_submissions/:id(.:format) order_submissions#show
The (.:format) is probably what's messing it up but I don't know why. I just want it to put a slash in there.
If I change my code to this it fixes it:
span = link_to "Show", order_submissions_path + '/' + order_submission.id
But that's a really, really stupid workaround.
EDIT: Here are my routes:
get 'order_submissions' => 'order_submissions#index'
get 'order_submissions/new' => 'order_submissions#new'
post 'order_submissions' => 'order_submissions#create'
get 'order_submissions/:id' => 'order_submissions#show'
get 'order_submissions/:id/edit' => 'order_submissions#edit'
patch 'order_submissions/:id' => 'order_submissions#update'
get 'order_submissions/:id/delete' => 'order_submissions#delete'
delete 'order_submissions/:id' => 'order_submissions#destroy'
The order_submissions_path (plural) points to /order_submissions. It takes two arguments, the first being the format for the request (e.g. html). Your ID is being passed in for this argument, leading to the resulting URL you're seeing.
You actually want the singular path helper, order_submission_path, which accepts an ID as the first argument.
Because it should be a singular form:
order_submission_path(order_submission.id)
Not
order_submissions_path(order_submission.id)
order_submissions_path points onto index action. You can also remove id from the end.
UPDATE:
Just notice you route file. Do you have any resources defined there? The route you posted wouldn't generate any url_helper as you dind't specify route name (most likely this entry is obsolete, as I expect there is resources :order_submissions somewhere there as well).
You don't get a named route by default. The route you showed from rake routes doesn't list a named route, for example.
GET /order_submissions/:id(.:format) order_submissions#show
Normally, you'd see the named route in front of GET there.
So you can define it yourself and then your route will work:
get 'order_submissions/:id' => 'order_submissions#show', as: :order_submission
Notice the as: :order_submission bit. Now, order_submission_path(order_submission.id) will work. (Note: .id is superfluous if your order_submission responds to to_path and returns id.)
I'm guessing you have another route in your rake routes output that uses the named route you supplied and that doesn't use /:id. Perhaps your index route?

Understanding what's going on with : and # in ruby, rails routes

In the answer to this question about routes in Devise: Devise & Custom Rails User URLs
There is a line of code:
match '/:user' => "users#show", :as => :user_profile
That apparently works for the question asker, but not for me. I end up with
NoMethodError in UsersController#show
undefined method `books' for nil:NilClass
when I go to localhost:3000/username instead of localhost:3000/user/username. I assume because the match line above isn't working correctly and that url does not refer to any user, according to my routes file.
The second url routes me to the user's show page, but I don't want the extra /user in the url.
So I'm trying to figure out exactly what '/:user', :as, and :user_profile mean because I think I'm supposed to substitute a few things here specific to my app. I think :as is some kind of aliased method. I can't find anything in the Devise documentation about a route called user_profile. And I don't know what '/:user' is referring to. An instance of the User object? A user attribute/unique column in my database that I use to refer to specific users? (I use permalink for my user-defined urls).
The route is working for you. Thats why ur getting error from users_controller#show.
In your show action you must be doing something like User.where(:id => params[:id]). But in this case, the attribute in your params is called :user . So to make make both routes work, without any change in the show action, change the route to
match '/:id' => "users#show", :as => :user_profile
Devise documentation won't refer to a 'user_profile' because it is a custom route being used to help address the issue that the questioner (in the linked question) was asking.
match '/:user' => "users#show" means "match any route with a single parameter after / that doesn't match a previously defined route, pair this route to the UsersController 'show' action (passing along the singe parameter as 'user')"
Modifying a route using :as => :anything will provide several helper methods to refer to this route that may be used in controllers, views, and mailers (in this case anything_path and anything_url).
As far as why this won't work for you, this is likely do to a problem with this entry in regard to the rest of your routes or because of your controller action itself. Posting these can help someone track down the exact reason...

Weird Routing Error in Rails When Manually Adding View

I am not sure what I am doing wrong but when I manually add the view "blah.html.erb" to my project and then visit myproject/dog/blah. It says the following:
Routing Error
No route matches "/dog/blah"
There is an action defined in DogController called "blah" which is the following:
def blah
end
NOTE: I add the view using TextMate. I add a new blank file. I think there is some wrong encoding attached to the .html.erb file.
For clarity, you need to either have each action listed explicitly in your routes.rb file; or you need a wildcard pattern to match the controller and action.
What's in your routes.rb file?
Better yet, you need to have something like this
match "/dog/blah", :to => "dog#blah", :as => :dog_blah
This tells your rails app that the url /dog/blah maps to the blah action in your DogController, and the :as option will give you a named route that you can use in your view in this case dog_blah_path.

Resources