如何获取归属记录的大小

时间:2019-07-06 11:29:14

标签: ruby-on-rails

我遵循此tutorial在我的网站上进行了完全相同的评论,现在我想显示该文章的评论数,但我只能获得该文章的答案数而不包括该数字评论的答案。

我不想在带有引用文章ID的评论模型中添加一列,因为我的网站已经在线,并且所有旧帖子将有0条评论,因为他们将没有此新列。

我该怎么办?我认为这与belong_to有关,但是在官方文档中我找不到它。

我的model/comment.rb

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
  has_many :comments, as: :commentable
  serialize :report, Array

  validates :commenter, presence: true, length: { in: 1..500 }
end

我的model/article.rb

class Article < ApplicationRecord
  include BCrypt
  serialize :view, Array
  serialize :upvote, Array
  serialize :report, Array


  has_many :comments, as: :commentable, dependent: :destroy
  validates :title, presence: true, length: { in: 1..60 }
  validates :content, presence: true
  has_secure_password

end

编辑:

也许我可以在帮助器中执行一个循环,该循环将计算评论的每个评论,但是我不知道如何像Article.find(my_article_id).comments.each do这样循环,然后我不知道该怎么做。这样做,那么也许我应该喜欢Comment.comments.each do吗?

我本来想做一个递归方法,但是我总是努力做一个递归方法

EDIT2:

schema/article

  create_table "articles", force: :cascade do |t|
    t.string "title"
    t.string "author"
    t.string "author_ip"
    t.string "password_digest"
    t.text "content"
    t.string "upvote"
    t.integer "upvote_count", default: 0
    t.string "view"
    t.integer "view_count", default: 0
    t.string "report"
    t.integer "report_count", default: 0
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "activate", default: true
    t.integer "comments_count", default: 0, null: false
  end

schema/comment

create_table "comments", force: :cascade do |t|
    t.text "commenter"
    t.string "author"
    t.string "author_ip"
    t.string "date"
    t.integer "commentable_id"
    t.string "commentable_type"
    t.string "report"
    t.integer "report_count", default: 0
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "article_id"
  end

EDIT3:

comment migration

class AddCommentsCountToComments < ActiveRecord::Migration[5.2]
  def change
    add_column :comments, :comments_count, :integer, default: 0,  null: false

    Comment.reset_column_information # to reset cached values
    Comment.find_each do |comment|
      comment.update(comments_count: comment.comments.count) # updating old articles comments_counter
    end
  end
end

2 个答案:

答案 0 :(得分:0)

您可以这样获得评论和子评论的数量:

article.comments.sum { |comment| 1 + comment.comments.count }

但是,这将对您的文章的每个父注释执行一个查询,这并不理想。

执行此操作的其他方式:

  • 在所有评论中添加article_id,并在迁移时填充当前评论
  • 对评论使用计数器缓存

答案 1 :(得分:0)

您可以始终使用article.comments.size,但这并不理想,因为它将始终对数据库进行查询。

另一种方法是在comments_count模型中添加计数器缓存articles列,也可以为同一迁移中在计数器缓存之前创建的任何商品更新comments_count

您可以从添加迁移开始

  def change
    add_column :articles, :comments_count, :integer, default: 0, null: false

    Article.reset_column_information # to reset cached values
    Article.find_each do |article| 
      article.update(comments_count: article.comments.count) # updating old articles comments_count
    end
  end

现在,如果您运行迁移并在控制台中检查了在迁移之前撰写的文章,那么comments_count应该反映出文章的评论数。

现在,最后一步是向counter_cache模型添加comment选项。 counter_cache选项可确保无论何时添加或删除注释,comments_count列中的数字始终会更新。

belongs_to :commentable, polymorphic: true, counter_cache: true

现在要获取缓存的值,您可以使用:

  • article.comments.size,就像您在has_many关联上使用counter_cache一样,size将直接使用缓存的计数,根本不会进行任何查询。
  • article.comments_count

类似地,要缓存comment.comments.countcomment.comments_count,还需要为comments表添加另一个计数器缓存。

要获取所有注释,包括针对特定article的嵌套注释,您需要获取文章注释计数(外部注释)+每个注释注释计数。

article.comments_count + article.comments.sum(:comments_count)

要干燥代码(如果需要重用),可以按如下方式在article模型内添加实例方法:

def comments_count_including_nested
  comments_count + comments.sum(:comments_count)
end

然后您可以致电article.comments_count_including_nested