Twice Nested Resource Form_For Issue - ruby-on-rails

I have a double nested resource:
resources :companies do
resources :orders do
resources :comments
end
end
Am having issues when trying to include a form to create a comment in my orders show view. This is what I've tried:
<%= form_for([#order, #order.comments.build]) do |f| %>
However this gives me a no method error.
Any chance you can recommend the best way to deal with this.

You have to define the company as well. If you write rake routes you can see that you dont have order_comments_path because its double nested, so you will se something like company_order_commments_path which takes minimum two parameters, a company_id and an order_id. So if you really want to use this 3 level nester resource you have to add a #company variable to the form path. Like:
<%= form_for([#company, #order, #order.comments.build] do |f| %>
But in the most cases it's useless to define both company and order to identify an order, so the other option which could be better to add separately another route for the orders and comments, and this makes sense.
In your routes.rb
...
resources :orders do
resources :comments
end
...
So you can manipulate orders, without specifying the company. Also in the most general cases you don't get any important advantage by defining 3 level nested routes.

Related

Creating link_to for sequential nested resources

I am creating a rails app whereby from a record's "show" page, the user is able to cycle through the record's nested resources (similar to a slideshow). For example, from the "show" page, the user will be able to link to the "show" for the first nested resource. From there, the user will be able to link to the "show" page of the next nested resource and so on. As the ids of each nested resource should be ordered smallest to largest, how can I create a link_to that looks for the next highest id (assuming nested resources are being created for multiple records simultaneously they may not necessarily be sequential) of a nested resource within a given record.
Because of Rails magic, you can pass the resource directly to the route helper, and it will use the correct id for that resource. For example:
<% #foo.bars.each do |bar| %>
<%= link_to bar.name, foo_bar_path(#foo, bar) %>
<% end %>
The above assumes that your route file looks something like:
resources :foos do
resources :bars
end
I highly recommend Rails Routing from the Outside In; it's been a very helpful resource for me!
To set the order of the child resource, you could use a scope, like this:
class Bar < ActiveRecord::Base
scope :ordered, -> { order(id: :asc) }
end
And then in your view, call foo.bars.ordered.each do |bar| etc.... Your nested resource will be returned from lowest to highest ID, skipping over any that have been deleted.
I hope this helps with what you were asking.
EDIT
I misread the question. To dynamically generate the "next" id, you could create method, next, on your child class. This answer seems to be something like what you want. Then in your view, you can just call:
<%= link_to "Next", bar_path(current_bar.next) %>

Failed to try to use 2 ids on nestes routes in rails

I'm trying to pass 2 ids to the controller within the update action, but it does not stop, I do not recognize the first id, student_id. This is the definition of the route within routes.rb
post 'registers/students/:student_id/notes/:note_id/edit', to: 'registers/students/notes#update', as: :update_registers_student_note
While this is the part of the form_for, using the corresponding helper
<%= form_for #note, url: update_registers_student_note_path(:student_id,:note_id), method: :post do |f| %>
My question is how can I correctly pass the 2 ids of the corresponding resources, since the form only recognizes me note_id, and not student_id
Thank you
The helper should works. You also can use update_registers_student_note_path(student_id: 1, note_id: 12).
But I suggest you to use nested resources in your routes instead.
You can write somethings like that:
namespace :registers do
resources :students do
resources :notes
end
end
The new url helper will be registers_student_note_path(<note_id>, student_id: <student_id>) with method PATCH.
yes, you did put a right thing for url_helpers. You can try to open rails console and try it with these command
include Rails.application.routes.url_helpers
update_registers_student_note_path(1,2)
you will see => "/registers/students/1/notes/2/edit"

Resource not generating helper method for create

I have a model called package, which has a controller package created under a name space admin.
so my resource in my routes is declared as below
namespace :admin do
resources :package
end
when I run rake routes
admin_package_index GET /admin/package(.:format) admin/package#index
POST /admin/package(.:format) admin/package#create
new_admin_package GET /admin/package/new(.:format) admin/package#new
edit_admin_package GET /admin/package/:id/edit(.:format) admin/package#edit
admin_package GET /admin/package/:id(.:format) admin/package#show
PUT /admin/package/:id(.:format) admin/package#update
DELETE /admin/package/:id(.:format) admin/package#destroy
If you see there is no helper method generated for create, which should have been admin_packages_path
controller
#newpackage = Package.new
view.html.erb
form_for [:admin,#newpackage] do |f|
end
is reporting that it is not able to find the admin_packages_path. Can somebody please explain how should we declare this in routes to generate the proper helper method for create ?
Your routes are named incorrectly, you're pairing a plural (resources) with a singular (:package).
If you will be working with multiple packages, you should declare resources :packages - this will generate you correctly named routes for all seven RESTful actions (index, show, new, create, edit, update, destroy).
If you are only working with a single package, you will need to specify the URL as an option for your form manually, eg.
form_for [:admin, #newpackage], url: admin_package_path do |f|
You really need to changes the routes to following:
namespace :admin do
resources :packages
end

Rails: Why am I getting "No route matches"?

Snippet from routes.rb:
resources :templates do
post :add_rates
resources :rates
delete :remove_rate
end
Now I try to use the "add_rates" path in my form.
Tried both:
<%= form_for(#template.template_id, :html => {:class=>"form-horizontal"},:url=> { :action=>:add_rates}) do |f| %>
and:
<%= form_tag(:template_add_rates) do %>
But I'm always getting: No route matches {:action=>"add_rates", :controller=>"templates"}
Any help would be appreciated.
You're doing it wrong:
form_for [#template, :add_rates], html: { class: "form-horizontal } do
or
form_for #template, url: template_add_rates_path(#template), html: {class: "form-horizontal" } do
The template, and its ID, and the action you want (add_rates) all have to be passed in as the same parameter. You can't give it the template ID as the first argument, and then try to tack additional URL parameters onto it. Additionally, in both cases, you're missing key parts of the URL. In the first one, you're just giving it an ID, and :add_rates; Rails can't take an arbitrary number and know that it's a template ID that you're giving it. In the second case, you're giving it :template_add_rates; how is Rails supposed to know which template you're trying to add rates to, without a template ID? You need to give it all three pieces of the route you're trying to match: /templates/:template_id/add_rates.
There are also a bunch of other weird issues/errors with the code you've posted:
#template.template_id should be #template.id, unless you've explicitly deviated from Rails' conventions, which you should almost never do.
Your routes are pretty weird. You shouldn't be adding a add_rate route, you should be using the routes provided by your nested resources :rates line.
Your routes should look like this:
resources :templates do
resources :rates
end
This gives you routes like POST /templates/:template_id/rates for creating rates (instead of your add_rate route), and DELETE /templates/:template_id/rates/:rate_id for deleting rates (instead of your remove_rate route).

Routing / in Rails

I'm writing a simple Rails app with one main controller and I want to map /(:action(:id)) to this controller (basically remove the controller prefix at the beginning), but still have the path helpers I get by using map.resources.
I tried map.root :controller => 'notes', but I get an error:
undefined method `note_path' for #<ActionView::Base:0x102038b50>
where I use the link_to_unless_current function in my view.
Edit: Here is the code in index.html.erb that gives the error.
<% for note in category.notes %>
<h3><%= link_to_unless_current h(numbered_title note), note %></h3>
<% end %>
UPDATE: I don't know how I came to this question, but author just pointed out that this is 3 years old, which I totally missed. I will leave this answer if somebody needs that behaviour in rails 3. In rails 2 it is not valid...
Route root will not work with whole controller as this has to point on specific action.
First parameter of resources will be used to determine path (normally it would be /notes) and at the same time to create helpers like notes_path. What you want to do is set this to '/', but also add :as option to give proper helpers names. So finally it should look like:
resources '/', controller: :notes, as: :notes
Also quite important thing to notice, if you want to use any other resources, you should put them above notes route. Otherwise rails will recognize resources name as id of notes action show.
Example:
resources '/', controller: :notes, as: :notes
resources :comments
Going to /comments will try to find note with id 'comments'.
resources :comments
resources '/', controller: :notes, as: :notes
Opening /comments will go to comments_controller#index.

Resources