Rails 3 routes to wrong controller - ruby-on-rails

I wanted to create a new action and I call it "showemployees". That's what I did already:
-> in the controller:
def showemployees
end
-> creating app/views/employees/showemployees.html.erb
-> in config/routes
match "/employees/showemployees" => "employees#showemployees"
I thought this is enough for opening the showemployees.html.erb now via localhost:3000/employees/showemployees , but it seems like Rails still routes through the show action (from resources :employees) and doesn't take the showemployees-action, because it tells me
ActiveRecord::RecordNotFound in EmployeesController#show
Couldn't find Employee with ID=showemployees
What do I need to change so Rails takes the showemployees-action?
the source code of my route:
System::Application.routes.draw do
match "/employees/showemployees" => "employees#showemployees" #für showemployees.html.erb
root :to => "employees#index"
resources :course_to_dos
resources :current_qualifications
resources :expected_qualifications
resources :skills
resources :employees
resources :positions
resources :admin
end

try to walk by Rails-way, if you want to get collection, use the collection
resources :employees do
collection do
get :showemployees
end
end

If you post your full routes file we can make a definitive call, but based on the error message, it looks like you have a broader route definition mapping to employees#show defined above this route in such a way that it is getting matched.
Routes are evaluated in the order they are defined, so if you have a very broad route pattern defined above a narrow one, your narrow route will never be called.
edit: you'll want to take the forward slash out of your route and add the showemployees to the actual URL, so that it reads
match "employees/showemployees" => "employees#showemployees"

Related

How to add DELETE method inside 'do' keyword in config/routes.rb?

I know I can add a new DELETE method on http://localhost:3000/students by editing config/routes.rb:
resources :students
delete '/students',:to => 'students#destroymany'
Note: it is different from DELETE http://localhost:3000/students/1 because the default DELETE supports deleting 1 student only, while I also want to support DELETE on http://localhost:3000/students/ (without specific student id)
but it has a disadvantage: I need to repeat typing 'students'. Is there any syntax that changes the routing statement to become
resources :students do
xxx
end
but have the same effect as the beginning version? I tried:
resources :students do
delete '',:to => 'students#destroymany'
end
but the error occurs:
No route matches [DELETE] "/students"
because it adds the routing to
/students/:student_id
instead of
/students
It is different from DELETE http://localhost:3000/students/1, because
the default DELETE supports deleting 1 student only, while I also want
to support DELETE on http://localhost:3000/students/ (without specific
student id)
Well add it on a collection then
resources :students do
delete '', :to => 'students#destroymany', on: :collection
end
This will give the below route
DELETE /students(.:format) students#destroymany
So, you can call /students with method: :delete
You could do this instead, for what you are trying to accomplish :
resource :students do
collection do
delete '', to: 'students#destroymany'
end
end
Make use of singular resource. Singular resource will give you delete route without any ID
resource :students
DELETE /students students#destroy
please refer singular resource

Rails routes, how to specify this member proper

I currently have some routes that look like the following:
resources :contests do
member do
get :enter
end
end
This allows me to do an HTTP GET on a URL that looks like /contests/5/enter. Now, a user can go in, fill in some forms, and be able to submit an entry to the contest. So I'd also like to be able to POST to this URL. I tried doing the following:
resources :contests do
member do
get :enter
post :enter
end
end
This posts to the same controller#action as the GET member that I have specified, so it's not really intuitive. I'd like to be able to direct it to a separate action if at all possible. What's the best way of doing that? I am using Ruby on Rails 4 beta currently.
** UPDATE **
I tried the following but I get an ArgumentError exception when I start the server:
resources :contests do
member do
get :enter
post :enter => "contests#create_entry"
end
end
You can do something like this:
resources :contests do
member do
get :enter
post '/enter', to: "contests#create_entry", as: "create_entry"
end
end
However i agree with Ola Tuvesson, you should definitely create a new controller and routes for entries, even though you may not have a model, similiar to how you often have a session controller for login and logout. Something like this:
resources :contests do
resources :entries, only: [:new, :create]
end
You can specify the controller/action you want to point a route at.
get :enter => "controller#get_enter"
post :enter => "controller#post_enter"
I would suggest you make the entries for a contest a child model of contests. That would give you all the CRUD methods on entries and your routes would simply be:
resources :contests do
resources :entries
end
A GET of /contests/5/entries/new will give you the form for adding an entry and when this POSTs to /contests/5/entries it would create a new entry. It also makes it easy to list all entries for a competition etc. You can easily create the controller, model and the associated views with the scaffold generator, for example:
rails g scaffold Entry contest:references name:string email:string
The references column type tells the generator to link Contests to Entries in a one to many relationship. Job done.
Edit:
If you still want to rename your routes, here's how:
http://guides.rubyonrails.org/routing.html#overriding-the-named-helpers
HTH

Rails 3: Getting the ID of a Namespaced Model

I have a model called Contributor, which also acts as a namespace for several other models, such as Contributor::Alias and Contributor::Reassignment. I want to use a URL that includes the Contributor ID like so:
/contributors/1/reassignments/new
But I get this error:
No route matches [GET] "/contributors/1/reassignments/new"
My routes.rb file includes:
namespace :contributor do
resources :reassignments
end
resources :contributors
I've also tried:
resources :contributors do
resources :reassignments
end
This results in a different error:
uninitialized constant ReassignmentsController
Any idea how to approach this? Perhaps I shouldn't use a namespace that also acts as a model? I haven't seen this done in any tutorials, though it seems like it could be possible.
UPDATE:
How do you handle a deeply nested namespace model, such as:
resources :contributors do
resources :reassignments, :module => "contributor" do
resources :approvals, :module => "reassignment"
end
end
Using this approach, I get the error:
No route matches {:action=>"create", :controller=>"contributor/reassignment/approvals"}
My controller directory does have the following structure:
contributor ->
reassignment ->
approvals_controller.rb
This seems related to the first error, but perhaps it's something new.
It's not clear if you have a Contributor resource or not. If you do, the following in your routes.rb:
resources :contributors do
resources :reassignments, :module => "contributor"
end
If not, try:
resources :reassignments, :module => "contributor", :path => "/contributors/:contributor_id/reassignments"
Just note that in the 2nd case you will need to construct an url and explicitly pass :contributor_id to it in calls to link_to, form_for, and similar places.
If you want to use [#contributor,#reassignment] format there you better stick to the 1st approach where yu do have a Contributor resource.
UPDATE: for three-level nesting if your controllers directories don't also nest in parallel with resources you could specify controllers explicitly, e.g.:
resources :contributors do
resources :reassignments, :controller => "contributor/reassignments" do
resources :approvals, :controller => "reassignment/approvals"
end
end
But, please, don't do that. 3-and-more-level nesting is actively discouraged in Rails. See what is recommended instead here: http://weblog.jamisbuck.org/2007/2/5/nesting-resources

Ruby on Rails Routes: Namespace with more params

i have a namespace "shop". In that namespace i have a resource "news".
namespace :shop do
resources :news
end
What i now need, is that my "news" route can get a new parameter:
/shop/nike (landing page -> goes to "news#index", :identifier => "nike")
/shop/adidas (landing page -> goes to "news#index", :identifier => "adidas")
/shop/nike/news
/shop/adidas/news
So that i can get the shop and filter my news.
I need a route like:
/shop/:identfier/:controller/:action/:id
I tested many variations but i cant get it running.
Anyone can get me a hint? Thanks.
You can use scope.
scope "/shops/:identifier", :as => "shop" do
resources :news
end
You will get those routes below:
$ rake routes
shop_news_index GET /shops/:identifier/news(.:format) news#index
POST /shops/:identifier/news(.:format) news#create
new_shop_news GET /shops/:identifier/news/new(.:format) news#new
edit_shop_news GET /shops/:identifier/news/:id/edit(.:format) news#edit
shop_news GET /shops/:identifier/news/:id(.:format) news#show
PUT /shops/:identifier/news/:id(.:format) news#update
DELETE /shops/:identifier/news/:id(.:format) news#destroy
http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
If you have those nike, adidas etc. in the database then the most straightforward option is to use match.
namespace :shop
match "/:shop_name" => "news#index"
match "/:shop_name/news" => "news#news"
end
However it seems to me that shop should be a resource for you. Just create a ShopsController (you don't need a matching model for it, just a controller). Then you can do
resources :shops, :path => "/shop"
resources :news
end
Now you can access the news index page (/shop/adidas) like this:
shop_path("adidas")
In the NewsController use :shop_id to access the name of the shop (yes even though it's _id it can be a string). Depending on your setup you may want news to be a singular resource, or the news method to be a collection method.
Also are you sure just renaming the news resource isn't something you want?
resources :news, :path => "/shop" do
get "news"
end
Keep in mind also that controller names and the number of controllers need not match your models. For example you can have a News model without a NewsController and a ShopsController without a Shop model. You might even consider adding a Shop model to your database if that makes sense.
In case this is not your setup then you might have oversimplified your example and you should provide a more full description of your setup.

How to map a new CRUD action in 'routes.rb'?

In my 'routes.rb' file I have this code:
resources :users
that maps my user's controller like this.
If I want to map the "reset" view/url for users (Path: /users/reset) what code I have to insert in the 'routes.rb' file?
Two options - I'm assuming you're just going to act on the session user so you don't need to pass in an id to operate on? If so, you'll need to make a few additional changes...
Use an explicit route:
match "/users/reset" => 'users#reset', :as => 'reset_user'
The 'as' part is optional.
Add a new route that operations on a 'collection'. This gets you your route but feels like a hack, I wouldn't recommend it.
resources :users do
collection do
get 'reset'
end
end
Do this:
resources :user do
member do
get 'reset'
end
end
See this section in the Rails Guide you referred to.

Resources