Sonny Black
Sonny Black

Reputation: 1617

First argument in form cannot contain nil or be empty (acts_as_commentable error)

So I'm trying to get the acts_as_commentable_with_threading gem working in my app. I would like to allow the users to comment on specific events (events/show.html). I don't think I've set it up properly as I'm getting the below error.

error:

Showing /Users/user/Sites/new_work/app/views/events/show.html.erb where line #36 raised:

First argument in form cannot contain nil or be empty
          

</div>
<div class="name"></div>
<div id="comments">
<%= form_for @comment do |f| %> <---- it's referring to this line
<div><%= f.hidden_field :event_id, value: @event.id %></div>
<div><%= f.text_field :body, row: 20, placeholder: "Leave a comment" %></div>
<%= f.submit "Post Comment" %>

comments_controller.rb

class CommentsController < ApplicationController
  before_filter :load_commentable

  def index
    @comments = @commentable.current_user.comments
  end

  def new
    @comment = @commentable.current_user.comments.new
  end

  def create
    @comment = @commentable.current_user.comments.new(params[:comment])
    if @comment.save
      redirect_to @commentable, notice: "Comment created."
    else
      render :new
    end
  end

  private

  def load_commentable
    resource, id = request.path.split('/')[1, 2]
    @commentable = resource.singularize.classify.constantize.find(id)
  end

end

comment.rb snippit only

class Comment < ActiveRecord::Base
  attr_accessible :title, :body, :subject

  acts_as_nested_set :scope => [:commentable_id, :commentable_type]

  validates :body, :presence => true
  validates :user, :presence => true

  # NOTE: install the acts_as_votable plugin if you                                                                                                           
  # want user to vote on the quality of comments.                                                                                                             
  #acts_as_votable                                                                                                                                            

  belongs_to :commentable, :polymorphic => true

  # NOTE: Comments belong to a user                                                                                                                           
  belongs_to :user

event.rb

class Event < ActiveRecord::Base
  attr_accessible :title, :description, :location, :date, :time, :event_date

  acts_as_commentable
  has_many :comments, as: :commentable
  belongs_to :user

  after_create :update_event_date

  def update_event_date
    date = self.date.to_s
    time = self.time

    hour = Time.parse(time).strftime("%H:%M:%S").to_s
    event_date = (date + ' ' + hour).to_time
    self.update_attributes(event_date: event_date)
  end
end

comments/form.html.erb

<%= form_for [@commentable, @comment] do |f| %>                                                                                                               
<% if @comment.errors.any? %>                                                                                                                                 
<div class="error_messages">                                                                                                                                  
  <h3>Please correct the following errors.</h3>                                                                                                               
  <ul>                                                                                                                                                        
    <% @comment.errors.full_messages.each do |msg| %>                                                                                                         
    <li><%= msg %></li>                                                                                                                                       
  </ul>                                                                                                                                                       
</div>                                                                                                                                                        
<% end %>                                                                                                                                                     
<div class="field">                                                                                                                                           
  <%= f.text_field :body, rows: 10, placeholder: "Leave a comment" %>                                                                                         
</div>                                                                                                                                                        
                                                                                                                                                              
<div class="actions">                                                                                                                                         
  <%= f.submit "Post comment", class: "btn" %>                                                                                                                
</div>                                                                                                                                                        
<% end %>              

events_controller.rb

class EventsController < ApplicationController
  before_filter :authenticate_user!

  def index
    @user = current_user
    @events = Event.all
  end

  def new
    @event = Event.new
  end

  # def create                                                                                                                                                
  #   @event = Event.new(params[:event])                                                                                                                      
  #   if @event.save                                                                                                                                          
  #     redirect_to :action => 'index'                                                                                                                        
  #   else                                                                                                                                                    
  #     @events = Event.find(:all)                                                                                                                            
  #     render :action => 'new'                                                                                                                               
  #   end                                                                                                                                                     
  # end                                                                                                                                                       

  def create
    @event = current_user.events.new(event_params)

    respond_to do |format|
      if @event.save
    format.html { redirect_to :back, notice: 'Event was successfully created.' }
    format.json { render action: 'show', status: :created, location: @event }
    format.js
      else
        format.html { render action: 'new' }
    format.json { render json: @event.errors, status: :unprocessable_entity }
    format.js
      end
    end
 end

  def show
    @event = Event.find(params[:id])
  end

  def edit
    @event = Event.find(params[:id])
  end

  def update
     @event = Event.find(params[:id])
    if @event.update_attributes(params[:event])
      flash[:success] = "Event updated."
      redirect_to @event
    else
      render 'edit'
    end
  end

  def destroy
    @event = Event.find(params[:id])
    @event.destroy

    respond_to do |format|
      format.html {redirect_to :back}
      format.js
    end
  end

  private
  # Use callbacks to share common setup or constraints between actions.                                                                                       
  def set_event
    @event = Event.find(params[:id])
  end

routes.rb

New_app::Application.routes.draw do

  # get 'auth/:provider/callback', to: 'sessions#create'                                                                                                      
  # get 'auth/failure', to: redirect('/')                                                                                                                     

  root to: "home#landing"

  devise_for :users, :controllers => {:registrations => "users/registrations",
    :sessions => "users/sessions",
    :passwords => "users/passwords",
    :omniauth_callbacks => "users/omniauth_callbacks"
  }

  get "welcome", to: "home#welcome", as: 'welcome'

  devise_scope :user do
  #  get "edit/edit_account", :to => "devise/registrations#edit_account", :as => "account_registration"                                                       
    get 'edit/edit_account' => 'users/registrations#account_registration', as: :edit_account
  end

  # patch '/users/:id', to: 'users#update', as: 'user'                                                                                                        
  get 'profile/:id' => "users#show", as: :profile
  get 'disconnect' => 'users#disconnect'

  resources :users do
    resources :questions
  end
  resources :photos

  resources :events do
    resources :comments
  end

  post "/events/add_new_comment" => "events#add_new_comment", :as => "add_new_comment_to_events", :via => [:event]

  resources :questions
end

rake routes for comments

event_comments GET      /events/:event_id/comments(.:format)          comments#index
                          POST     /events/:event_id/comments(.:format)          comments#create
        new_event_comment GET      /events/:event_id/comments/new(.:format)      comments#new
       edit_event_comment GET      /events/:event_id/comments/:id/edit(.:format) comments#edit
            event_comment GET      /events/:event_id/comments/:id(.:format)      comments#show
                          PATCH    /events/:event_id/comments/:id(.:format)      comments#update
                          PUT      /events/:event_id/comments/:id(.:format)      comments#update
                          DELETE   /events/:event_id/comments/:id(.:format)      comments#destroy

Upvotes: 0

Views: 607

Answers (2)

ply
ply

Reputation: 1141

Is @comment defined in the "show" action in your Events controller? Can you post the Events controller code as well?

One thing to double check is to ensure that the action that renders the view for show.html.erb has the @comment variable defined. You seem to be getting the message because the @comment variable in

<%= form_for @comment do |f| %>

Is currently nil when you render the view.

In the "show" action for the events controller, try setting the @comment variable by adding:

@comment = @event.comments.new

Edit 2: Make sure you've setup your routes.rb file to handle comments on events, so assuming youre using RESTful routes, something like this below in your routes.rb. If you could post the routes file that would be helpful too.

resources :events do
   resources :comments
end

Upvotes: 1

Uri Mikhli
Uri Mikhli

Reputation: 675

The error is on app/views/events/show.html.erb which means that your Events controller's show action is missing the @comment variable

def show   
    @event = Event.find(params[:id])
    @comment =  ....what ever you need to pull in the comments....
  end

Upvotes: 0

Related Questions