I defined nested resources like this
resources :item, :only => [:create, :destroy, :update] do
resources :item_image, :only => [ :new, :create, :show , :destroy, :index]
end
And my routes look like this (output of rake routes)
item_item_image_index GET /item/:item_id/item_image(.:format) item_image#index
POST /item/:item_id/item_image(.:format) item_image#create
new_item_item_image GET /item/:item_id/item_image/new(.:format) item_image#new
item_item_image GET /item/:item_id/item_image/:id(.:format) item_image#show
DELETE /item/:item_id/item_image/:id(.:format) item_image#destroy
I thought the first column of the output is "the named routes".
I want to show a path to /item/:item_id/item_image(.:format) in one of my view.
item_item_image_index GET /item/:item_id/item_image(.:format) item_image#index
I tried this:
<%= link_to "users", item_item_image_index %>
and also this
<%= link_to "users", item_images_path %>
Neither works
I got "undefined local variable or method `item_images_path/item_item_image_index'" error
you should try:
<%= link_to "users", item_item_image_index_url(#item) %>
or
<%= link_to "users", item_item_images_url(#item) %>
or
<%= link_to "users", item_item_image_index_path(#item) %>
or
<%= link_to "users", item_item_images_path(#item) %>
don't forget the url needs an :item_id, hence you need to pass an item as an argument.
actually, you should avoid naming that model "ItemImage". An Item has Images, that's what you need to know. you'll get better helper names like "item_images_url"
item_item_image_index GET /item/:item_id/item_image(.:format) item_image#index
In this route item_item_image_index, you need a item_id in the url
Lets you have an object of Item model named as #item, then your link will be
<%= link_to 'users', item_item_image_index_path(#item) %>
Here You need to append '_path' after the route helper "item_item_image_index". While passing the #item variable, it will take the #item.id as item_id and completes the URL of the link.
Related
I have a place model and a user model and a user_place model, user_place belongs to user and place both. Traditional has_many through association.
I have a page where you can view the users associated with a place. My routes look like:
resources :places do
resources :user_places
end
which generates these routes:
place_user_places GET /places/:place_id/user_places(.:format) user_places#index
POST /places/:place_id/user_places(.:format) user_places#create
new_place_user_place GET /places/:place_id/user_places/new(.:format) user_places#new
edit_place_user_place GET /places/:place_id/user_places/:id/edit(.:format) user_places#edit
place_user_place GET /places/:place_id/user_places/:id(.:format) user_places#show
PATCH /places/:place_id/user_places/:id(.:format) user_places#update
PUT /places/:place_id/user_places/:id(.:format) user_places#update
DELETE /places/:place_id/user_places/:id(.:format)
I don't love this but I'm ok with it for now.
But whenever I try to delete a user_place I have all sorts of issues.
<%= link_to "delete", place_user_place_url(place_id: #user_place.place_id, id: #user_place.id), method: 'delete' %>
No route matches {:action=>"show", :controller=>"user_places", :id=>nil, :place_id=>2}, possible unmatched constraints: [:id]
I had this working previously with slightly different routes and an actual form:
resources :places do
resources :user_places, as: 'user', only: %i[index create new]
delete 'remove_user', to: 'user_places#remove_user'
end
<% if user != current_user %>
<%= form_with model: #user_place, url: place_remove_user_path(#place.id), method: 'delete' do |form| %>
<%= form.hidden_field :user_id, value: user.id %>
<%= form.hidden_field :place_id, value: #place.id %>
<%= form.submit "delete" %>
<% end %>
<% end %>
But this feels hacky, I don't think I should need a specific form, and this was leading the form to be submitted with javascript which I don't want.
What might be a solution is to use shallow nesting in the routes (shallow: true).
resources :places do
resources :user_places, shallow: true
end
Make sure to run rails routes again. The delete method of a user_place will no longer be nested.
You can then simply delete the user_place passing a single variable (an instance of a user place, #user_place). There is no need to set the id (place_id or id) as Rails is smart enough to handle that. Just passing an instance variable is enough for the delete method to find the corresponding record.
<%= link_to "delete", user_place_url(#user_place), method: 'delete' %>
I have following routing problem in Rails 5:
<%= link_to product.id, product %>
generates a link like this
localhost:3000/products/12345
What I want is a link to the "ext" action in the products controller:
localhost:3000/products/ext/12345
If I try to build a link like this
<%= link_to 'To the product', :controller => :products, :action => :ext %>
it gives back following error:
No route matches {:action=>"ext", :controller=>"products"}
In the routes.rb I have
get "products/ext/:id", to: "products#ext"
Thanks for help!
Modify your routes to
get "products/ext/:id", to: "products#ext", as: :products_ext
and change your view to
<%= link_to products_ext_path(product) %>
I'm following this answer on how to clone a record.
I can't though workout how to phrase the link and route it.
It is in my #miniature show view so I thought it should be something like
<%= link_to 'clone', :controller => :miniatures_controller, :action => :clone %>
and the route
match 'clone', to: 'miniatures#clone', via: 'get'
but this is clearly wrong. I am using #miniature in place of the above answer's #prescription.
What if you just use clone_path:
<%= link_to 'clone', clone_path %>
Cause rake routes shows just clone route. It works with the same routes.
If you are not satisfied with route and you should pass parameters (like miniature_id), add member to your resource (probably nested), like:
resources :miniatures do
member do
get 'clone'
end
end
This will be clone_miniature_path where you should pass #miniature:
<%= link_to 'clone', clone_miniature_path(#miniature) %>
I created an form_tag form:
<%= form_tag(set_image_dokumente_path) do %>
<%= text_field_tag :shit,'', data: {autocomplete_source: search2_patients_path}, :class => "shit" %>
<% end %>
I try to route to set_image action of dokumente controller, but i get the error:
undefined local variable or method `set_image_dokumente_path' for #<#<Class:0x711ff60>:0x762d578>
By default my form_tag goes to dokumente controller index action!
My routes:
resources :images
get "dokumente/index"
post "dokumente/index"
match 'patients/list' => 'patients#list'
resources :patients do
collection do
get :search2
end
end
How do i have to change it?
You can add the as: parameter to you route in order to create a named path.
For example:
post "dokumente/index", as: 'set_image_dokumente'
or similar, I'm not sure what you are trying to achieve, but I hope you get the idea :)
More info:
http://guides.rubyonrails.org/routing.html#generating-paths-and-urls-from-code
I want to setup a custom nested controller actions but I can't figure out the routing.
I keep getting the following error
No route matches [GET] "/assets"
routes.rb
resources :companies do
resources :requests do
match :accept
end
end
index.html.rb
<% #requests.each do |request| %>
<ul class="users">
<li>
<%= full_name(request.profile) %>
<%= request.status %>
<%= link_to "Accept",
:controller => "requests", :action => "accept",
:id => request.id %>
</li>
</ul>
<% end %>
There are a couple of problems: routing to the accept action and building a URL to a nested resource.
Defining custom actions
You can add custom actions to your RESTful resources using this syntax:
resources :requests do
get 'accept', :on => :member
end
This will give you a route that looks like this:
requests/:id/accept
And you can generate paths in your views using:
accept_request_path(a_request)
The :on => :member part indicates that you're routing to a new action on each individual request, rather than the collection of all requests. If you used :on => :collection the route would be requests/accept
Nesting resources
When you nest resources:
resources :companies do
resources :requests do
get 'accept', :on => :member
end
end
You get routes that look like this, note that because the requests is nested inside companies the route includes both a company_id and an id:
companies/:company_id/requests/:id/accept
And helpers like this:
accept_company_request_path(a_company, a_request)
You could do this long-hand, as you're currently trying to do, with something like:
<%= link_to "Accept",
:controller => "requests", :action => "accept",
:id => request.id, :company_id => request.company.id %>
But it's easier to use the helpers:
<%= link_to "Accept", accept_company_request_path(request.company, request) %>
Appropriate verbs
Accept sounds a lot like something that updates your database in some way, and if that's the case you should consider using a PUT request rather than a GET request.
The HTTP/1.1 spec says that the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval (RFC2616, section 9) which has the real-world implication that non-human web clients — search engine indexers, browser extensions, etc. — are allowed to follow links (which make GET requests) but not allowed to submit forms that make other types of requests.
If you do switch to using a PUT request then the button_to helper will come in handy. As with link_to you can pass the controller, action, method, and all the parameters required by the route to button_to:
<%= button_to 'Accept',
{:controller => :requests, :action => :accept,
:company_id => request.company, :id => request},
:method => :put %>
Or you can use the helpers to generate the path which is much easier:
<%= button_to 'Accept',
accept_company_request_path(request.company, request),
:method => :put %>
More documentation
Adding more RESTful actions
Nested resources
in your route file:
match 'request/accept/:id' => 'requests#accept', :as => :accept
and in view
link_to "Accept", accept_path(request)