传递轨道关联和神奇计数

发布于 2024-08-13 09:28:19 字数 481 浏览 3 评论 0原文

在 Rails 中,要自动对关联进行计数,您可以执行以下操作:

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

并将 Chapters_count 列添加到脚本模型中。

现在,如果您想计算脚本中的段落数,而段落模型中没有 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 的自动计数来计算它们?

In Rails, to automatically count associations, you do:

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

and you add a chapters_count column into the Script model.

Now, what if you want to count the number of paragraphs in a Script without having a script_id key in the paragraph model ?

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

How do you automatically associate script to paragraph and count them using the automatic count of Rails ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

往事随风而去 2024-08-20 09:28:20

你走在正确的轨道上。但首先你必须解决一个小错误。除非您指示,否则 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

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

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

You're on the right track. But first you've got to address a small error. Rails won't update a counter cache unless you instruct it to.

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

Will automatically update @script.chapter_count before creation and after destruction of all associated Chapters.

Unfortunately things aren't so simply when dealing :through relationships. You will need to update the associated script's paragraph counter through callbacks in the Paragraph model.

N.B.: The following assumes you want to keep a paragraph counter in Chapter as well.

Start by applying the same theory to the Chapter model, and a paragraphs count column to the Script table.

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 

Now to set up the relationships:

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

All that's left is to tell Paragraph to update the paragraph counters in script as a callback.

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
如果没结果 2024-08-20 09:28:20

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

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

script = Script.find(1)
puts script.paragraphs.size #get the count

The quick and simple way, without using a cache is to do:

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

script = Script.find(1)
puts script.paragraphs.size #get the count
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文