Here are my routes:
equipment_index GET /equipment(.:format) {:action=>"index", :controller=>"equipment"}
POST /equipment(.:format) {:action=>"create", :controller=>"equipment"}
new_equipment GET /equipment/new(.:format) {:action=>"new", :controller=>"equipment"}
edit_equipment GET /equipment/:id/edit(.:format) {:action=>"edit", :controller=>"equipment"}
equipment GET /equipment/:id(.:format) {:action=>"show", :controller=>"equipment"}
PUT /equipment/:id(.:format) {:action=>"update", :controller=>"equipment"}
DELETE /equipment/:id(.:format) {:action=>"destroy", :controller=>"equipment"}
categories GET /categories(.:format) {:action=>"index", :controller=>"categories"}
POST /categories(.:format) {:action=>"create", :controller=>"categories"}
new_category GET /categories/new(.:format) {:action=>"new", :controller=>"categories"}
edit_category GET /categories/:id/edit(.:format) {:action=>"edit", :controller=>"categories"}
category GET /categories/:id(.:format) {:action=>"show", :controller=>"categories"}
PUT /categories/:id(.:format) {:action=>"update", :controller=>"categories"}
DELETE /categories/:id(.:format) {:action=>"destroy", :controller=>"categories"}
When I go to http://localhost:3000/equipment/new I get the following error:
No route matches {:action=>"show", :controller=>"equipment"}
This is my routes.rb file:
Equipmentmanager::Application.routes.draw do
resources :equipment
resources :categories
end
Everything else are set to the defaults, except that I used nifty:scaffold.
This is in 3.1, but it does it in 3.0 also
I am not sure what I am missing?
So localhost:3000/equipment/new is getting routed with this line:
equipment GET /equipment/:id(.:format) {:action=>"show", :controller=>"equipment"}
As it should be. Since you want it to actually go to the new route you need to call localhost:3000/new_equipment since you have defined that route.
As a bit cleaner syntax if you wanted localhost:3000/new_equipment to route to the new action you could put this line in your routes.rb file (above the resources :equipment line since its more specific):
get "new_equipment" => "equipment#new", :as => "new_equipment"
That line will also define helpers that give you access to new_equipment_path and new_equipment_url
Related
Statement
Imagine we have an inventory app, there it is a Movement model, it represent any movement like products purchase or products sale. So we have default REST routes.
movements GET /movements(.:format) {:action=>"index", :controller=>"movements"}
POST /movements(.:format) {:action=>"create", :controller=>"movements"}
new_movement GET /movements/new(.:format) {:action=>"new", :controller=>"movements"}
edit_movement GET /movements/:id/edit(.:format) {:action=>"edit", :controller=>"movements"}
movement GET /movements/:id(.:format) {:action=>"show", :controller=>"movements"}
PUT /movements/:id(.:format) {:action=>"update", :controller=>"movements"}
DELETE /movements/:id(.:format) {:action=>"destroy", :controller=>"movements"}
For mnemonic proposes, we want to have some descriptive routes, like:
new_purchase /purchase/new(.:format) {:controller=>"movements", :action=>"new_purchase"}
edit_purchase /purchase/:id/edit(.:format) {:controller=>"movements", :action=>"edit_purchase"}
If you can see purchase's are same model likemovement's, actually are processed by MovementsController, but there with have different flow and treatment, this specified by create_purchase instead of create.
Questions
How should I add restful routes for purchase's? Taking care of specify HTTP methods like GET, POST, PUT, DELETE, etc.
How should I write form_for tags? Using movement model we can write: <%= form_for(#movement) do |f| %> but how is to call purchase paths for create or update methods?
How should I specify validation rules for purchase's? I have specified some rules on Movement model, but they are not applied for purchase's when a form is submitted.
You could use some thing like this in your routes file
match '/purchase/new(.:format)' => 'movements#new_purchase' :via => :get
match '/purchase/:id/edit(.:format)' => 'movements#edit_purchase' :via => :post
and you can mention others like delete, put in :via
for more info look at this link
If you want to change create to create_purchases go to the movements controller and change the definition names.
for the second question you could do something like this
form_tag(:controller => "controller_name", :action => "action_name", :method => "get")
I don't think that you should be looking for a way to RESTfully build routes for a model that handles an object in two separate ways. That sounds to me like you're really looking for two objects. You can create a Purchase model that inherits its properties from a parent Movement model.
Alternatively, you could assume that they are the same object and handle them the same way with semantic paths that make sense. That said, what you're looking for may be a path alteration for the default RESTful routes of the Movement controller actions. Also, a typical rails convention is to use plural path routes, which makes semantic sense for index pages and identifying objects that are a subset of a table of objects in a database, so I'm using purchases instead of purchase.
resources :movements, :path => "/purchases"
will produce
movements GET /purchases(.:format) {:action=>"index", :controller=>"movements"}
POST /purchases(.:format) {:action=>"create", :controller=>"movements"}
new_movement GET /purchases/new(.:format) {:action=>"new", :controller=>"movements"}
edit_movement GET /purchases/:id/edit(.:format) {:action=>"edit", :controller=>"movements"}
movement GET /purchases/:id(.:format) {:action=>"show", :controller=>"movements"}
PUT /purchases/:id(.:format) {:action=>"update", :controller=>"movements"}
DELETE /purchases/:id(.:format) {:action=>"destroy", :controller=>"movements"}
Using this model, the form_for helper method can still be used just like you would normally. Assuming #movement is properly defined, the path with the purchases root will be called properly.
I have a nested route in rails 3 mapped as
resources :maps do
resource :versions
member do
post 'share'
get 'share'
end
end
but when i try to connect to http://localhost:3000/maps/35/versions/2 i obtains
No route matches "/maps/35/versions/2"
and in rake routes
GET /maps/:map_id/versions/:id(.:format) {:controller=>"versions", :action=>"show"}
or similar (with :id) is missing
other routes with versions works correctly
what's wrong?
EDIT 2:
This is the full rake routes output
maps_public GET /maps/public(.:format) {:controller=>"maps", :action=>"public"}
map_versions POST /maps/:map_id/versions(.:format) {:controller=>"versions", :action=>"create"}
new_map_versions GET /maps/:map_id/versions/new(.:format) {:controller=>"versions", :action=>"new"}
edit_map_versions GET /maps/:map_id/versions/edit(.:format) {:controller=>"versions", :action=>"edit"}
GET /maps/:map_id/versions(.:format) {:controller=>"versions", :action=>"show"}
PUT /maps/:map_id/versions(.:format) {:controller=>"versions", :action=>"update"}
DELETE /maps/:map_id/versions(.:format) {:controller=>"versions", :action=>"destroy"}
share_map POST /maps/:id/share(.:format) {:controller=>"maps", :action=>"share"}
GET /maps/:id/share(.:format) {:controller=>"maps", :action=>"share"}
maps GET /maps(.:format) {:controller=>"maps", :action=>"index"}
POST /maps(.:format) {:controller=>"maps", :action=>"create"}
new_map GET /maps/new(.:format) {:controller=>"maps", :action=>"new"}
edit_map GET /maps/:id/edit(.:format) {:controller=>"maps", :action=>"edit"}
map GET /maps/:id(.:format) {:controller=>"maps", :action=>"show"}
PUT /maps/:id(.:format) {:controller=>"maps", :action=>"update"}
DELETE /maps/:id(.:format) {:controller=>"maps", :action=>"destroy"}
It has to be resources :versions. Note the missing "s" in your case.
In addition to #Femaref's answer, the url you need to access is /maps/35/versions/2. If you want the singular (singleton) resource, then you'd do:
resources :maps do
resource :version
end
And then hit /maps/35/version (doesn't take an id). Which, if you have multiple versions for each map, you probably don't want to do.
I have a resource defined like so:
resources :referrals, :except => [:show, :edit, :destroy]
and I'd like to replace (not just add a named route) a default route that Rails produces, specifically the one for the update action.
Here is my rake routes:
referrals GET /referrals(.:format) {:action=>"index", :controller=>"referrals"}
POST /referrals(.:format) {:action=>"create", :controller=>"referrals"}
new_referral GET /referrals/new(.:format) {:action=>"new", :controller=>"referrals"}
referral PUT /referrals/:id(.:format) {:action=>"update", :controller=>"referrals"}
share /share(.:format) {:controller=>"referrals", :action=>"new"}
special /special(.:format) {:controller=>"referrals", :action=>"index"}
thanks /thanks(.:format) {:controller=>"pages", :action=>"thanks"}
/:shortlink(.:format) {:controller=>"referrals", :action=>"update"}
/:linktext(.:format) {:controller=>"referrals", :action=>"update"}
root /(.:format) {:controller=>"pages", :action=>"home"}
I'd like either the
/:shortlink(.:format)
or
/:linktext(.:format)
to hit the update action, but not the
/referrals/:id(.:format)
This is to implement a form of non-password "security". When the PUT goes to the update action, I want certain things to happen, but I don't want to require authorization to do this, and I don't want to allow easy guessing of the url based on controller name and simple low-numbered ids.
How can I fully replace the default route given by rails?
resources :referrals, :except => [:show, :edit, :destroy, :update]
match "/whatever_you_want/:variable_here" => "referrals#updated", :as=> the_link, :via=> :put
then in your controller you will access the param with
params[:variable_here]
here the param is whatever you want to compare against in the db, and the path will be create like this:
the_link_path or the_link_url
the :via part will constrain the path per HTTP method so only put request will match
more info here
http://guides.rubyonrails.org/routing.html
Here is a portion of my routes file:
resource :vendor do post 'modify_account' end
Running rake routes will generate the following line
modify_account_vendor POST /vendor/modify_account(.:format) {:action=>"modify_account", :controller=>"vendors"}
vendor POST /vendor(.:format) {:action=>"create", :controller=>"vendors"}
new_vendor GET /vendor/new(.:format) {:action=>"new", :controller=>"vendors"}
edit_vendor GET /vendor/edit(.:format) {:action=>"edit", :controller=>"vendors"}
GET /vendor(.:format) {:action=>"show", :controller=>"vendors"}
PUT /vendor(.:format) {:action=>"update", :controller=>"vendors"}
DELETE /vendor(.:format) {:action=>"destroy", :controller=>"vendors"}
/vendor(.:format) {:action=>"account", :controller=>"vendors"}
I can load the form and verify the URL is correct in the form's action, but when I submit, the app throws an error:
No route matches "/vendor/modify_account"
Any suggestions as to what I can do to troubleshoot? Firebug verifies that the error page is of type POST.
I had a simular issue with a singleton resource, check that you are passing in the url to the form_tag, we use simple_form and have the following
<%= simple_form_for #enterprise_account, :url => enterprise_account_path do |f| -%>
As it turns out, I believe the issue was with my choice of "action verb" - I should have been using PUT instead of POST. This is my new routes file, and the only thing I had to change was the _url helper method names.
resource :vendor do put 'account', :action => 'modify_account' end
How do I create a link using link_to, that links to a method in my controller. The link I want to create is something like this:
/meetings/10/contacts/2/send_invite
The send_invite method is in the Contacts controller. I'm unsure what the next step as far as how to setup the routes file. I've tried nesting resources but no luck so far. Also, what is the link to specify in the link_to? I've tried various combinations such as send_invite_path, meeting_contact_send_invite_path, but everything throws an error.
My routes file looks like this:
resources :meetings do
resources :contacts, :only => [:send_invite], :as => :send_invite
end
But then when I try to call send_invite_path, it doesn't work.
expanding on austin's answer. This nesting in config/routes.rb
resources :meetings do
resources :contacts do
member do
post :send_invite
end
end
end
would give you these routes
send_invite_meeting_contact POST /meetings/:meeting_id/contacts/:id/send_invite(.:format) {:action=>"send_invite", :controller=>"contacts"}
meeting_contacts GET /meetings/:meeting_id/contacts(.:format) {:action=>"index", :controller=>"contacts"}
POST /meetings/:meeting_id/contacts(.:format) {:action=>"create", :controller=>"contacts"}
new_meeting_contact GET /meetings/:meeting_id/contacts/new(.:format) {:action=>"new", :controller=>"contacts"}
edit_meeting_contact GET /meetings/:meeting_id/contacts/:id/edit(.:format) {:action=>"edit", :controller=>"contacts"}
meeting_contact GET /meetings/:meeting_id/contacts/:id(.:format) {:action=>"show", :controller=>"contacts"}
PUT /meetings/:meeting_id/contacts/:id(.:format) {:action=>"update", :controller=>"contacts"}
DELETE /meetings/:meeting_id/contacts/:id(.:format) {:action=>"destroy", :controller=>"contacts"}
meetings GET /meetings(.:format) {:action=>"index", :controller=>"meetings"}
POST /meetings(.:format) {:action=>"create", :controller=>"meetings"}
new_meeting GET /meetings/new(.:format) {:action=>"new", :controller=>"meetings"}
edit_meeting GET /meetings/:id/edit(.:format) {:action=>"edit", :controller=>"meetings"}
meeting GET /meetings/:id(.:format) {:action=>"show", :controller=>"meetings"}
PUT /meetings/:id(.:format) {:action=>"update", :controller=>"meetings"}
DELETE /meetings/:id(.:format) {:action=>"destroy", :controller=>"meetings"}
You will need to define the route in your routes.rb file and have setup your routes to be nested. As far as the name goes you can define that in your routes.rb file as well by using :as => "some_name" that will allow you to use link_to some_name_path.
For more info on routes: http://guides.rubyonrails.org/routing.html
Specifically on nested resources: http://guides.rubyonrails.org/routing.html#nested-resources