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.