Just getting started with Rails and I am having a problem defining a route. None of the documentation I can seems to resolve the issue and I am getting an undefined local variable or method error.
I need to click on a link and take a specific action, sortit. sortit does not have a view because it sorts mystuff objects and then redirects to the index page. When I use one of the predefined actions then in fact everything works. Of course none of the predefined actions are what I want to do.
my /config/routes.rb file:
match "/mystuff/sortit'", :controller => "mystuff", :action => "sortit"
resources :mystuff
my /app/controllers/mystuff_controller.rb file
class MystuffController < ApplicationController
....
def sortit
#mystuff.sort
redirect_to_mystuff_path
end
....
end
my /app/views/mystuff/index.html.haml file:
-# This file is app/views/mystuff/index.html.haml
%h1 All My Stuff
%table#mystuff
%thead
%tr
%th= link_to raw("Type"), sortit
....
As I said, when I replace sortit with a predefined action, then that action is executed. However sortit fails with this error:
undefined local variable or method `sortit' for #<#<Class:0x9997a10>:0x997c0f8>
app/views/mystuff/index.html.haml:7:in `_app_views_mystuff_index_html_haml__61272557_87671610'
So what have I missed and how do I get sortit to execute when clicking on the generated link for Type?
Thanks!
PS: My rake routes output:
mystuff GET /mystuff (.:format) {:action=>"index", :controller=>"mystuff"}
....
mystuff_sortit /mystuff/sortit (.:format) {:controller=>"mystuff", :action=>"sortit"}
....
So rake routes shows my route with the name mystuff_sorit - but aren't actions prepended to the object name? Shouldn't it be sortit_mystuff instead?
Your action is sortit but your view is index
Change your action to index
redirect_to needs a space also, so use redirect_to mystuff_path...
which will actually be my_stuffs_path (plural) which you can see from rake routes (at the command line, most useful) which you get from defining it as a resource in routes.
Related
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.
As of Rails 4.2, I cannot do the following:
get 'profile', to: 'profile#index', as: 'profile'
get 'profile/:slug', to: 'profile#show', as: 'profile'
because it will raise error saying route is already defined. Why is that? Obviously profile_path and profile_path(User.last.slug) are not the same, and there should be no difficulty differentiating the two even if they happen to share the same base name (You check if a param is passed).
Thoughts?
In rails, the helper names for different routes should be different. And hence, as you rightly understood, you will receive an error if you use the same helper name (ie as: 'profile' in your case) for two different routes.
This restriction in Rails helps maintain sanity in your routes.rb file as well as in your application. For instance consider two methods for a controller:
class XyzController < ApplicationController
def method_a(param1)
end
def method_b(param1)
end
end
In your routes file if there was no restriction of keeping helper names different, you could have used :
get 'xyz/method_a', to: 'profile#method_a', as: 'profile_method'
get 'xyz/method_b', to: 'profile#method_b', as: 'profile_method'
Correspondingly in your view file:
link_to 'link_1', profile_method_path('param1') #intended to route for method_a
link_to 'link_2', profile_method_path('param2') #intended to route for method_b
As obvious, in the view file, not only is it difficult to make out which route is intended for which method, its also not possible to route to any other controller method using the helper 'profile_method' except the method that is first to use this helper in your routes.rb file (as routes are read sequentially).
Hope this helps :)
For both routes you specified as: 'profile' and that's your problem here. Besides that, use pluralized route names for #index action, e.g:
get 'profiles', to: 'profile#index'
I have a payments table. In the index view I list all payments in a table and in the show view I'd like to show a form of all payments where a user can select which ones to further process.
Above the table in the index action view I have:
<%= link to "Customise", show_payment_path %>
Then in the controller:
def show
#payments = Payment.all
end
In my routes file:
resources :payments
The error I am getting is:
undefined local variable or method `show_payment_path'
I have tried
<%= link_to 'Customise Sepa Mandate', show_payments_path %>
as well but that gives the same error. As does using url instead of path.
The path for resourceful-routed show actions is just payment_path (singular resource) or payment_path(id). Your “customize” link would lead me to believe you actually want edit_payment_path(id), though.
See Rails Guides — Generating Paths and URLs From Code for more info.
Run rake routes command to see available routes and correct syntax.
Pass show_payment_path(:id) to get the particular payment show page.
for that make your own routes and create their own path variable such as
resources :payments, except: [:show] do
get '/show' => "payments#show", on: collection, as: :show
end
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
I would like to do something to this effect, I believe:
map.connect 'show/:company_name/:id',
:controller => 'companies',
:action => 'show'
Basically, each time the show action is called, I would like it to take the company_name param and place it into the url as such (show/:company_name/:id)
However, it seems I am using old (rails 2.x routing api) and cannot use map.connect without getting an error. How can I upgrade this?
Is there some way to do this with "match"?
Thanks!
===================
This is the error I see when I try to use map.connect:
undefined local variable or method `map' for #<ActionDispatch::Routing::Mapper:0x103757458>
I think your routes lack a "/" symbol in the first line.
Try this:
match '/show/:company_name/:id' => 'companies#show'
You can check your routes path with command rake routes.
--
Besides, the show action is the default RESTful method in Rails. I'll suggest you change a equivalent word, and reserve "show" action for future or other situation.
In Rails convention, you can write resources :companies, and the path will be /companies/:id using show action.
Some adjustment, in app/models/company.rb
def to_param
self.name
end
So your url will look like http://yourdoamin.com/companies/37signals.
In app/controllers/companies_controller.rb
#company = Company.find_by_name(params[:id])
If I'm understanding your goal, try
match 'companies/show/:company_name/:id' => 'companies#show'