views:

548

answers:

1

Ok...I am new to rails so this may be a stupid question but need help. I just watched and implemented Ryan Bates screencaset about setting up a blog. You can see it here http://media.rubyonrails.org/video/rails%5Fblog%5F2.mov. Here is the skinny:

Two tables: Posts and Comments. Everything works great including the addition of comments via AJAX. The default development of this blog gives you the index.html.erb view where you can view all the posts

  def index
    @posts = Post.all


    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @posts }
      format.json { render :json => @posts }
      format.atom
    end
  end

The comments are only viewed via the show.html.erb page and is displayed via this code in that file:

<%= render :partial => @post %>
<p>
 <%= link_to 'Edit', edit_post_path(@post) %> |
 <%= link_to 'Destroy', @post, :method => :delete, :confirm => "Are You Sure" %> |
 <%= link_to 'See All Posts', posts_path %>
</p>

<h2>Comments</h2>
<div id="comments">
 <%= render :partial => @post.comments %>
</div>

<% remote_form_for [@post, Comment.new] do |f| %>
 <p>
  <%= f.label :body, "New Comment" %><br/>
  <%= f.text_area :body %>
 </p>
 <p><%= f.submit "Add Comment"%></p>
<% end %>

What I am trying to do is to get similair representation of the comments functionality to exist in the index.html.erb view (which I will hide with javascript). Which currently just looks like this:

<h1>Listing posts</h1>
<%= render :partial => @posts %>

<%= link_to 'New post', new_post_path %>

My initial thought was just to put this exact same code that is in the show.html.erb file in the index.html.erb file but that doesn't work. I have tried a bunch of things here but I am not familiar enough with Rails (or coding for that matter) yet to do this in a timely manner. I get two main errors. Either that I passed a nil.comments error or an undefined object/method (can't remember).

My question is what do I need to included in the post_controller, the comments_controller and the index.html.erb file to accomplish this. To be complete I have included the code in each below.

POSTS_CONTROLLER

class PostsController < ApplicationController
  before_filter :authenticate, :except => [:index, :show]

  # GET /posts
  # GET /posts.xml
  def index
    @posts = Post.all


    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @posts }
      format.json { render :json => @posts }
      format.atom
    end
  end

  # GET /posts/1
  # GET /posts/1.xml
  def show
    @post = Post.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @post }
    end
  end

  # GET /posts/new
  # GET /posts/new.xml
  def new
    @post = Post.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @post }
    end
  end

  # GET /posts/1/edit
  def edit
    @post = Post.find(params[:id])
  end

  # POST /posts
  # POST /posts.xml
  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        flash[:notice] = 'Post was successfully created.'
        format.html { redirect_to(@post) }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /posts/1
  # PUT /posts/1.xml
  def update
    @post = Post.find(params[:id])

    respond_to do |format|
      if @post.update_attributes(params[:post])
        flash[:notice] = 'Post was successfully updated.'
        format.html { redirect_to(@post) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.xml
  def destroy
    @post = Post.find(params[:id])
    @post.destroy

    respond_to do |format|
      format.html { redirect_to(posts_url) }
      format.xml  { head :ok }
    end
  end

  private

  def authenticate
    authenticate_or_request_with_http_basic do |name, password|
      name == "admin" && password == "secret"
    end
  end
end

COMMENTS_CONTROLLER

class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create!(params[:comment])
    respond_to do |format|
      format.html { redirect_to @post}
      format.js
    end
  end
end

INDEX.HTML.ERB

<h1>Listing posts</h1>
<%= render :partial => @posts %>

<%= link_to 'New post', new_post_path %>
+1  A: 

Here's one simple solution. Step 1, edit your index action to include all the comments belonging to each post.

def index
  @posts = Post.all(:include => :comments)

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @posts }
    format.json { render :json => @posts }
    format.atom
  end
end

Step 2, edit your index view to display each post, followed by its comments:

<h1>Listing posts</h1>

<% @posts.each do |post| %>
  <%= render :partial => post %>
  <%= render :partial => post.comments %>
<% end %>

<%= link_to 'New post', new_post_path %>

Edit: I'm not 100% sure of the best way to include the comment creation form also. What I'd try first is this (in index.html.erb):

Try changing your index view to:

<h1>Listing posts</h1>

<% @posts.each do |post| %>

  <%= render :partial => post %>
  <%= render :partial => post.comments %>

  <% remote_form_for [post, Comment.new] do |f| %>
    <p>
    <%= f.label :body, "New Comment" %><br/>
    <%= f.text_area :body %>
    </p>
    <p><%= f.submit "Add Comment"%></p>
  <% end %>

<% end %>

<%= link_to 'New post', new_post_path %>

This should render the "New comment" form for a given post under the comments for that post, but I'm not sure (without actually trying it out) whether the form submission AJAX will successfully update and refresh the index page.

PreciousBodilyFluids
Thank you so, so, so much man. I really appreciate this. It worked great. I am about to try an insert the form as well and see if that works.
bgadoci
Hey man...one more question, if I want to include the form for collecting a new comment that references the comment controller...how do I do that? The comment controller code is above. Basically, right below all the comments that are now being displayed because of the code you gave me...how can I also allow for a new comment to be submitted and associated with that past. Trying to do all this and then hide with javascript.
bgadoci