1

在 Rails 中,要自动计算关联,您可以:

class Script
  has_many :chapters
end
class Chapter
  belongs_to :script
end

然后在 Script 模型中添加一个 chapters_count 列。

现在,如果您想计算 Script 中的段落数而段落模型中没有 script_id 键怎么办?

class Script
  has_many :chapters
  has_many :paragraphs # not complete
end
class Chapter
  has_many :paragraphs
  belongs_to :script
end
class Paragraph
  belongs_to :chapter
end

你如何自动将脚本关联到段落并使用 Rails 的自动计数来计算它们?

4

2 回答 2

1

你在正确的轨道上。但首先你必须解决一个小错误。Rails 不会更新计数器缓存,除非您指示它这样做。

class Chapter
  belongs_to :script, :counter_cache => true
end

将在创建之前和销毁所有相关章节之后自动更新@script.chapter_count。

不幸的是,通过关系处理事情并不是那么简单。您将需要通过段落模型中的回调来更新关联脚本的段落计数器。

注意:以下假设您也想在章节中保留一个段落计数器。

首先将相同的理论应用于章节模型,并将段落计数列应用于脚本表。

class PrepareForCounterCache < ActiveRecord::Migration
  def self.up
    add_column :scripts, :paragraphs_count, :integer, :default => 0
    add_column :chapters, :paragraphs_count, :integer, :default => 0

    Chapter.reset_column_information
    Script.reset_column_information

    Chapter.find(:all).each do |c|
      paragraphs_count = c.paragraphs.length
      Chapter.update_counters c.id, :paragraphs_count => paragraphs_count
      Script.update_counters c.script_id, :paragraphs_count => paragraphs_count
    end
  end
  def self.down
    remove_column :scripts, :paragraphs_count
    remove_column :chapters, :paragraphs_count
  end
end 

现在设置关系:

class Script
  has_many: chapters
  has_many: paragraphs, :through => :chapters
end

class Chapter
  has_many: paragraphs
  belongs_to :script, :counter_cache => true
end

class Paragraph
  belongs_to :chapter, :counter_cache => true
end

剩下的就是告诉段落更新脚本中的段落计数器作为回调。

class Paragraph < ActiveRecord::Base
  belongs_to :chapter, :counter_cache => true
  before_save :increment_script_paragraph_count
  after_destroy, :decrement_script_paragraph_count

  protected
  def increment_script_paragraph_count
    Script.update_counters chapter.script_id, :paragaraphs_count => 1
  end
  def decrement_script_paragraph_count
    Script.update_counters chapter.script_id, :paragaraphs_count => -1
  end
end
于 2009-12-02T22:07:38.327 回答
0

不使用缓存的快速简单的方法是:

class Script
  has_many :chapters
  has_many :paragraphs, :through => :chapters
end

script = Script.find(1)
puts script.paragraphs.size #get the count
于 2009-12-03T04:44:14.557 回答