I have a Post model:
我有一个Post模型:
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
.
现在我知道如何按日期排序: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 * 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.
几乎就是*的作用。例如,如果问题得到回复,则将其置于顶部,如果回答其他问题,则将其置于顶部,依此类推。问题按ASC排序。
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)
2 个解决方案
#1
2
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.
首先,您需要在帖子中添加另一个日期时间列。我们称之为content_changed_at或类似的东西。在新帖子中,它具有created_at的值。然后每次发布评论时都会更新它。当您需要显示帖子时,您只需按此列对其进行排序。
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
#2
6
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.
如果我是你,我会在你的Post模型中添加一个last_comment_at:datetime字段,并确保在创建评论时更新该日期时间。
This way you can simply use Post.order('last_comment_at, created_at DESC')
这样你就可以简单地使用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:
正如其他人所说,您可以向Comment模型添加after_save调用以更新Post模型中的last_comment_at字段。我会用这样的东西:
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
#1
2
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.
首先,您需要在帖子中添加另一个日期时间列。我们称之为content_changed_at或类似的东西。在新帖子中,它具有created_at的值。然后每次发布评论时都会更新它。当您需要显示帖子时,您只需按此列对其进行排序。
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
#2
6
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.
如果我是你,我会在你的Post模型中添加一个last_comment_at:datetime字段,并确保在创建评论时更新该日期时间。
This way you can simply use Post.order('last_comment_at, created_at DESC')
这样你就可以简单地使用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:
正如其他人所说,您可以向Comment模型添加after_save调用以更新Post模型中的last_comment_at字段。我会用这样的东西:
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