views:

599

answers:

3

I am new to rails so could use some help here. I have followed several tutorials to create a blog with comments and even some of the AJAX bells and whistles and I am stuck on something that I hope is easy. The default display for both blogs and comments is to list the oldest first. How do I reverse that to show the most recent entries and the most recent comments at the top. Don't really know if this is a function of the controller or model. I have done some customization so here is the code for the controller .rb files if it helps.

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

POSTS CONTROLLER

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

  # GET /posts
  # GET /posts.xml
  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

  # 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 { redirect_to @post}
      format.js
    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
A: 

It looks like you can reverse the order using find: something like Post.find(:all, :order => "created_at DESC"). The same should apply to comments.

jtbandes
I realized that I put the wrong code in the COMMENTS CONTROLLER above. Where would I place the order function in the above comments controller line?
bgadoci
+2  A: 
@posts = Post.find(:all, :include => :comments, :order  => "published_at DESC")
LymanZerga
I realized that I put the wrong code in the COMMENTS CONTROLLER above. Where would I place the order function in the above comments controller line?
bgadoci
+3  A: 

As jtbandes pointed out, to reverse the posts in the index, you'd change the line in your index action to read:

@posts = Post.all(:include => :comments, :order => "created_at DESC")

In order to reverse the listing of your comments, there are two possibilities.

Option 1: In your post model you can declare your relationship like so:

class Post < ActiveRecord::Base
  has_many :comments, :order => "created_at DESC"
end

Option 2: In your index view, simply reverse the array of each post's comments before displaying them:

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

The options have different use cases. In option 1, you're saying that throughout your entire application, any time you refer to the comments on a post, those comments should be retrieved from the database in the specified order. You're sort of saying that this is an intrinsic property of comments in your application - posts have many comments, which are by default ordered newest first.

In option 2, you're simply reversing the comments in the index page before they're rendered. They were still retrieved in the original order (oldest first) from the database, and they'll still appear in that order anywhere else you access the comments of a post in your application.

PreciousBodilyFluids
This was a really helpful answer and it worked. One more questin (sorry). I have AJAX setup to work on the show.html.erb. I can't get it to add the new comment at the top instead of the bottom. I have tried a couple of things but any quick words here?
bgadoci
How are you doing the AJAX? RJS or ??? If you're still following the blog tutorial, you just want to change :bottom to :top on the first line in create.js.rjs... If you switched your JS to something else it might be worth posting a new question.
Andy Gaskell
These is a third option which is to use the `default_scope` method within the `Comment` model itself. `default_scope :order => 'created_at desc'`
John Topley
Thanks Andy and John. I tried changing the :bottom :top thing prior to asking in the comment but didn't work. I will likely post a new question today. Thanks so much for all the help.
bgadoci
Actually, tried changing :bottom to :top and his morning it worked. Must have been to filled with coffee at 2am. Thanks and sorry.
bgadoci