Routing problem in ruby on rails - ruby-on-rails-3

I am new to ruby on rails.
I used the command 'rails generate controller Courses new'
Then, I edited routes.rb file with:
resources :courses
match '/courses', :to => 'courses#new'
When I access http://0.0.0.0:3000/courses. I get an error:
Unknown action
The action 'index' could not be found for CoursesController.
I think i am missing something. Please help
Thanks.

The line
resources :courses generates the routes for courses like so:
/courses -> coursescontroller#index
/courses/:id -> coursescontroller#show
...
and so on. This is known as 'restful routes'.
If you do not want to direct a url of form 'courses.html' to the 'index' action of your courses controller, but to the 'new' action of your courses controller (which would be highly unusual, by the way), just remove the first line from your routes.rb.
If you want to see what routes you have defined, just do
rake routes
from your rails app directory.

You could use this instead:
resources :courses, :except => :index
match '/courses', :to => 'courses#new'
The except option takes a symbol or an array of actions in the controller you do not want to define resource routes for. In this case, we turn off the route for the index action, /courses/.
Next, we define the same route that would have been defined for the index action, but point it at CoursesController#new.

Put your "match" line before your "resources" line.

Related

Ruby on Rails 3 nested routes: wrong action route

I have two models: team and project
routes.rb
resources :teams do
resource :projects
end
And two questions!
1- According to http://guides.rubyonrails.org/routing.html, I expect to get teams/:team_id/projects/:id path. However, this is not the case.
rake routes
team_projects POST /teams/:team_id/projects(.:format) projects#create
new_team_projects GET /teams/:team_id/projects/new(.:format) projects#new
edit_team_projects GET /teams/:team_id/projects/edit(.:format) projects#edit
GET /teams/:team_id/projects(.:format) projects#show
PUT /teams/:team_id/projects(.:format) projects#update
DELETE /teams/:team_id/projects(.:format) projects#destroy
so I had to name route to get it working
match 'teams/:team_id/projects/:id' => 'projects#show', :via => [:get], :as => :show_project
so how can take advantage of rails helper methods instead of naming them?
2- In project show action view, the debugger throws these parameters for me:
action: show
controller: projects
team_id: '1'
which is fine. but when I click on "new_team_projects_path" url, it redirects me to the same view and the debugger throws these parameters:
controller: projects
action: show
team_id: '1'
id: new
It doesn't redirect me to the new action, but it took "new" as an ID! why?
You need to use
resources :teams do
resources :projects
end
Note the plural! resource produces a singular route without id.
won't be relevant anymore with the first fix.

Passing :new to Rails url_for

Maybe I'm stupid but Rails provides this nifty syntax for generating URL's like so:
url_for([user, comment]) # => /users/1/comment/1
Passing :edit allows me to create something like this:
url_for([:edit, user, comment]) # => /users/1/comment/1/edit
but is there some way to do following?
url_for([:new, user, comments]) # => NoMethodError: undefined method `new_user_comments_url'
UPDATE: Added more information.
My routes.rb:
resources :users do
resources :comments
end
resources :posts do
resources :comments
end
My problem here is, that I can't use Rails auto-generated url helper (user_comments_url), because I'm sharing the views for both user comments and post comments.
There are two workarounds (but no one feels like the "Rails"-way) for my problem:
Adding logic to the view, e.g. some if conditions.
Defining my own url helpers like new_parent_comment(user_or_blog).
Ok, found a solution, but I'm not sure if this is the intended one:
url_for([:new, user, :comment]) # => '/users/1/comments/new'
url_for([:new, post, :comment]) # => '/posts/1/comments/new'
Stuck with the same problem, and found next solution (tested on Rails 5.2):
url_for([user, Comment, action: :new])
where Comment model class name.
By the way, action also could be :edit.
According to the Rails Docs url_for uses the class name of the object passed to generate the RESTful route. It also states that with nested routes it can not make this assumption correctly:
If you have a nested route, such as admin_workshop_path you’ll have to call that explicitly (it’s impossible for url_for to guess that route).
I would suggest using a named route here something like new_user_comment_path(). I am assuming you have set up your routes.rb something like:
resources :users do
resources :comments do
end
end
Additionally you can run rake routes to print out the proper names for all your routes.
Hope this helps,
/Salernost
Could this simply be a typo? I think the last line should read comment, not comments:
url_for([:new, user, comment])
(Assuming your comment variable has been defined.)

Questions about rails3 routes

I'm upgrading my app to rails 3, and I am a bit confused about some of the routes. The resourceful ones are easy enough, but how can I set a generic rule for all actions in a specific controller. I tried something like this:
get 'custom/:action/' => {:controller => :custom}
But that didn't work. It seems the new format is "controller#action", but how can I specify the action to be variable?
Also, other than using named routes or resources, is it possible to do shorthand notation to name routes in a specific controller?
i.e. rather than:
get '/tasks', :controller => :home, :action => :tasks, :as => 'tasks_home'
get '/accounts', :controller => :home, :action => :accounts, :as => 'accounts_home'
is it possible to do something a little cleaner, like:
controller => :home do
get :tasks
get :accounts
end
And that would automatically created the named routes?
You can use action as a variable like this:
resource :custom do
match ':action'
end
This will generate
/custom/:action(.:format) customs#:action
custom POST /custom(.:format) customs#create
new_custom GET /custom/new(.:format) customs#new
edit_custom GET /custom/edit(.:format) customs#edit
GET /custom(.:format) customs#show
PUT /custom(.:format) customs#update
DELETE /custom(.:format) customs#destroy
So it will handle your action as a variable URL-s and will add some default CRUD actions as well.
Note that the controller name here is in plural. If you would like to use a route for a controller which name is in singular, use resources instead of resource.
The answer to the second question is almost identical to the first one, use resource:
resource :home do
get :tasks
get :accounts
end
generates:
tasks_home GET /home/tasks(.:format) homes#tasks
accounts_home GET /home/accounts(.:format) homes#accounts
home POST /home(.:format) homes#create
new_home GET /home/new(.:format) homes#new
edit_home GET /home/edit(.:format) homes#edit
GET /home(.:format) homes#show
PUT /home(.:format) homes#update
DELETE /home(.:format) homes#destroy
Note that the matched controller names are in plural again, because of the convention.
Looks like this is related to the persisted field being set to false on nested ActiveResource objects: https://github.com/rails/rails/pull/3107

How can I add a test-environment route dynamically?

i would like to add a route that is only available in test environment, so i would prefer not to pollute routes.rb file. i cannot seem to find a working way to add a route dynamically after original routes were drawn. i tried this https://gist.github.com/1351762 but that didn't quite work
How can I add a new route after routes.rb has already loaded and processed all the routes?
The with_routing test helper redefines routes within a block.
with_routing do |map|
map.draw do
resources :test, only: [:show]
end
get :show
assert assigns(:test)
end
After some tries and errors, I found that:
Rails.application.routes.eval_block(Proc.new do
get "/backdoor", :to => "backdoors#backdoor"
end)

Rails -- rename restful route

I wanted to know what the easiest way to rename a restful route is. Basically I have a controller called Employees and rather than have employees/new I want employees/hire to be used and achieve the same thing and make employees/new an invalid url.
For your specific need, the guide has exactly this example for new, edit, this should work:
resources :employees, :path_names => { :new => 'hire' }
http://guides.rubyonrails.org/routing.html#overriding-the-new-and-edit-segments
One of the best sources of data on routes is the rails guide:
Rails Guide on Routes, also the command
rake routes
This command will show you all the current routes.
But in answer to this specification question
if you look into your routes file you can create new routes
manually.
match 'employee/hire' => 'Employees#new', :via => :get, :as => 'employee_path'
the first argument matches what the browser is looking for.
The second argument is the controller and method.
The third is if it is a get, put, post, or delete call.
The fourth is the name for the path so you can access with the standard name_path type of call from code.
This makes sense?