简体   繁体   中英

How to order by the date of the last comment and sort by last created otherwise?

I have a Post model:

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :tag_names

  belongs_to :user

  has_many :comments, :dependent => :destroy
end

  belongs_to :post, :counter_cache => true
  belongs_to :user
end

and a Comment model:

class Comment < ActiveRecord::Base
  attr_accessible :content, :user_id

  belongs_to :post, :counter_cache => true
  belongs_to :user
end

Right now I know how to sort by date: created_at ASC , created_at DESC .

Now I would like to know, how to order by the date of the last comment and sort by last created otherwise?

Pretty much how StackOverflow does. For instance, if a question gets replied it is placed at the top, if other question is replied this one is placed on the top and so on. Questions are sorted ASC otherwise.

Generated SQL:

Started POST "/posts/30/comments" for 127.0.0.1 at 2012-03-12 11:59:32 +0800
Processing by CommentsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"0zGpin7T/1aH/JBomGiqsEYCIgQ04HQWHZ/bIjm7WKs=", "comment"=>{"content"=>"sfsfwfewsdesd"}, "commit"=>"Create Comment", "post_id"=>"30"}
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1  [["id", "30"]]
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
   (0.2ms)  begin transaction
  SQL (1.1ms)  INSERT INTO "comments" ("content", "created_at", "post_id", "total_votes", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?)  [["content", "sfsfwfewsdesd"], ["created_at", Mon, 12 Mar 2012 03:59:32 UTC +00:00], ["post_id", 30], ["total_votes", 0], ["updated_at", Mon, 12 Mar 2012 03:59:32 UTC +00:00], ["user_id", 2]]
  Post Load (0.4ms)  SELECT "posts".* FROM "posts" WHERE "posts"."id" = 30 LIMIT 1
  SQL (0.5ms)  UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 30
   (130.3ms)  commit transaction
Redirected to http://localhost:3000/posts/30
Completed 302 Found in 156ms (ActiveRecord: 133.4ms) 

If I were you I would add a last_comment_at:datetime field to your Post model, and be sure to update that datetime whenever a comment is created.

This way you can simply use Post.order('last_comment_at, created_at DESC')

Update - in reply to your comment asking about the migration you'd need, the following should generate the migration for you:

rails generate migration add_last_comment_at_to_posts last_comment_at:datetime

As others have noted, you can add an after_save call to your Comment model to update the last_comment_at field in your Post model. I would use something like this:

class Comment < ActiveRecord::Base
  belongs_to :post

  after_save :update_post_last_comment_at

  private

  def update_post_last_comment_at
    self.post.touch(:last_comment_at) if self.post
  end
end

First, you need to add another datetime column to your post. Let's call it content_changed_at or something similar. In a new post it has value of created_at . Then you update it every time a comment gets posted. When you need to display posts, you just sort it by this column.

Here's untested code, but it should give you the idea.

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :tag_names

  before_create :init_sort_column

  belongs_to :user

  has_many :comments, :dependent => :destroy

  private 
  def init_sort_column
    self.content_changed_at = self.created_at || Time.now
  end
end

  belongs_to :post, :counter_cache => true
  belongs_to :user
end

class Comment < ActiveRecord::Base
  attr_accessible :content, :user_id

  after_create :update_parent_sort_column

  belongs_to :post, :counter_cache => true
  belongs_to :user

  private
  def update_parent_sort_column
    if post
      post.content_changed_at = self.created_at
    end
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM