3

I have a simple_form_for new_comment that results in a undefined methodcomments_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" }
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
  • 1
    what is in your routes file? – Igor Guzak Sep 13 '14 at 07:52
  • @IS04 updated with routes. I tried changing it to `resources :hacks do resources :comments, only: [:create, :update, :destroy] end` but it still results in the same error. restarted server too – ahnbizcad Sep 13 '14 at 08:05

2 Answers2

1

Since your comments are nested within hacks, you need both the comment and the hack. So, try this

show.html.slim

= render partial: "comments/form", locals: { new_comment: @new_comment, hack: @hack } if user_signed_in?

_form.html.slim

= simple_form_for [hack, new_comment], :remote => true do |f|
sjaime
  • 1,480
  • 9
  • 16
  • I remember struggling with this before. It's only coming back to me after seeing your answer. Thank you. – ahnbizcad Sep 13 '14 at 13:56
0

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:

enter image description here

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)

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • 1
    Is the choice of paths being signed to actions in order, regardless of what actions you omit a feature of rails, or is it an artifact? If you omit some actions in the types for a resource, the result is based on something like a loop through an array pg path names, rather than matched based on a hash than smartly matches helpers to actions consistently. It seems it would seem like it wouldn't be hard to change it so it does it smartly. – ahnbizcad Sep 13 '14 at 13:49