I have a simple_form_for new_comment that results in a undefined method
comments_path'` error in the browser, when I simply try to view the form (not submit)
_form.html.slim
= simple_form_for new_comment, :remote => true do |f|
This is in a partial, so the local variable passed is from the show page of hacks scaffold
show.html.slim - hacks
= render partial: "comments/form", locals: { new_comment: @new_comment } if user_signed_in?
I define @new_comment in the hacks controller
hacks_controller.rb
def show
@hack = Hack.find(params[:id])
@comments = @hack.comment_threads.order('created_at DESC')
@new_comment = Comment.build_from(@hack, current_user.id, "") if user_signed_in?
#build_from is a method provided by the acts_as_commentable_with_threading gem
end
Why would new_comment want to route to comments_path? I'm not even submitting the form.
routes.rb
root 'hacks#index'
concern :commentable do
resources :comments, only: [:create, :update, :destroy]
end
resources :hacks, concerns: [:commentable]
resources :users
devise_for :users, :skip => [:sessions, :registration]
devise_for :user, :path => '', :path_names => { :sign_in => "login",
:sign_out => "logout",
:sign_up => "register",
:account_update => "account-settings" }
Routes
Firstly, I don't believe your form will be routing to the index
action
The call to comments_path
is dependent on the CRUD actions you have defined in your routes. Specifically, form_for
will automatically populate for the create
action, which Rails will attempt to call from the set of resource
based routes you'll have defined in your routes.rb
file:
Notice from the example above, how it will go to /photos
using the POST
verb? This may appear to
be sending to the "index" action (photos_path
) - but actually, by virtue of the HTTP Verb, it will be going to the create
action
Form
simple_form_for
is a basically an abstraction of form_for
:
In the examples just shown, although not indicated explicitly, we still need to use the :url option in order to specify where the form is going to be sent. However, further simplification is possible if the record passed to form_for is a resource, i.e. it corresponds to a set of RESTful routes, e.g. defined using the resources method in config/routes.rb. In this case Rails will simply infer the appropriate URL from the record itself
Basically, form_for
attempts to build the url
to submit to from the objects it has. You have a nested route, which means you need to provide nested objects:
= simple_form_for [hack, new_comment], :remote => true do |f|
This should send the path to hacks_comments_path
, which is what you want, right? Alternatively, you can stipulate the url
option:
= simple_form_for new_comment, remote: true, url: hacks_comments_path(hack) do |f|
Notice how both of these fixes require the hack
local variable?
= render partial: "comments/form", locals: { new_comment: @new_comment, hack: @hack } if user_signed_in?
Fix
You need to pass your nested
path to the simple_form_for
helper (as detailed above)