I've been banging my head on this issue for about 2 hours now. This makes no sense to me. I'm trying to to write a simple form helper that is 3 level nested. (I'm aware that 3 level nests are not recommended, but just roll with me here for a second.)
My routes.rb excerpt looks like this:
resources :vendors, path: '', except: [:new, :create] do
resources :item_links do
resources :messages
end
resources :projects do
resources :designs
end
end
Now when I render the following, it errors out:
<%= form_for [@vendor, @item_link, Message.new], url: vendor_item_link_messages_path, method: :post, remote: true do |f| %>
No route matches {:action=>"index", :controller=>"messages", :vendor_id=>"thearborist", :project_id=>"4fad5bd7", :id=>"77ec58b5"} missing required keys: [:item_link_id]
I'm specifying the url here because my Vendor class and my ItemLink class both have sub-classes (sti) and if I don't specify the url, I end up with the fully qualified route which I don't want.
Based on the error, its ignoring the method
param I specified entirely because its trying to access the "index" action instead of the "create" action. Secondly, its inserting a project_id
param into the equation for some reason that makes no sense. Nowhere in either the params specified or the url path I listed does it reference project.
Furthermore, I decided to go specific and list out routes to my specfic sub-classes:
resources :vendor_arborists do
resources :item_link_standards do
resources :messages
end
end
This still blows up with the same sort of error
<%= form_for [@vendor, @item_link, Message.new], url: vendor_arborist_item_link_standard_messages_path, method: :post, remote: true do |f| %>
No route matches {:action=>"index", :controller=>"messages", :vendor_id=>"thearborist", :project_id=>"4fad5bd7", :id=>"77ec58b5"} missing required keys: [:vendor_arborist_id, :item_link_standard_id]
Only when I remove the url param entirely does it finally start working:
<%= form_for [@vendor, @item_link, Message.new], method: :post, remote: true do |f| %>
To add to the mystery, as if this isn't screwed up enough, the second set of routes I specified above work just fine with or without the URL specified and with or without the subclasses specified.
<%= form_for [@vendor, @project, Design.new], url: vendor_project_designs_path, method: :post, remote: true do |f| %>
So I'm now completely confused as to what is going wrong. My models are all very basic, these are simple Rails 101-esque routes. I'll post any other details if anyone needs them to debug this, but I don't know where else to look. What the hell am I doing wrong???
Update:
So after continuing with the testing, it seems this works as well. I suppose I can move forward with this, but that doesn't explain why it works in the example above for Design, but fails in all the examples with Message. Overall, it seems something in Rails 4 is causing these route helpers to get screwed up, because these examples all behaved just fine in Rails 3.2 which I'm migrating over from.
Credit to: Rails 4 shallow routes resource form submission not working
<%= form_for Message.new, url: vendor_item_link_messages_path(@vendor, @item_link), method: :post, remote: true do |f| %>
Additional reading:
Rails 4 [Best practices] Nested resources and shallow: true
The Controller Method
This is the method that is rendering the view which contains my busted form helper. I tried nulling out the @project
param in case the form helper was somehow automagically accessing it, but setting it to null
doesn't seem to have any impact.
def show
@vendor = Vendor.find_by_subdomain( params[:vendor_id] )
@project = @vendor.projects.find( params[:project_id] )
@item_link = @project.item_links.find( params[:id] )
@item_link.increment!(:views)
respond_to do |format|
format.html
end
end
Rake Routes Output
vendor_item_link_messages GET /:vendor_id/item_links/:item_link_id/messages(.:format) item_links/messages#index
POST /:vendor_id/item_links/:item_link_id/messages(.:format) item_links/messages#create
new_vendor_item_link_message GET /:vendor_id/item_links/:item_link_id/messages/new(.:format) item_links/messages#new
edit_vendor_item_link_message GET /:vendor_id/item_links/:item_link_id/messages/:id/edit(.:format) item_links/messages#edit
vendor_item_link_message GET /:vendor_id/item_links/:item_link_id/messages/:id(.:format) item_links/messages#show
PATCH /:vendor_id/item_links/:item_link_id/messages/:id(.:format) item_links/messages#update
PUT /:vendor_id/item_links/:item_link_id/messages/:id(.:format) item_links/messages#update
DELETE /:vendor_id/item_links/:item_link_id/messages/:id(.:format) item_links/messages#destroy