1

我刚刚competitors_controller.rb从...更改了一个动作

def audit
  @review = Review.find(params[:review_id])
  @competitor = @review.competitors.find(params[:id])
  respond_with(@review, @competitor)
end

...至...

def audit
  @review = Review.find(params[:review_id])
  @competitor = Competitor.find(params[:id], :include => {:surveys => {:question => [:condition, :precondition]}})
  respond_with(@review, @competitor)
end

...因为页面在加载时超时。

基本关联是:

class Competitor < ActiveRecord::Base
  has_many :surveys
end

class Survey < ActiveRecord::Base
  belongs_to :competitor
  belongs_to :question
  delegate :dependencies, :precondition, :condition, :to => :question  
end

class Question < ActiveRecord::Base
  has_many :dependancies, :class_name => "Question", :foreign_key => "precondition_id"
  belongs_to :precondition, :class_name => "Question"
  has_many :surveys, :dependent => :delete_all
end

基本上,audit.html.haml 页面加载:

 @competitor.surveys.{sorting, etc}.each do |s|
    s.foo, s.bar
    s.{sorting, etc}.dependant_surveys.each do |s2|
       s2.foo, s2.bar
       s2.{sorting, etc}.dependant_surveys.each do |s3|
           s3.foo, s3.bar, etc etc

如果我将它嵌套得太远,页面在超时之前不会加载。

我需要知道的是,我插入的预加载competitor_controllers.rb理论上是否会加速以下两种方法中的每一种,这两种方法在构建时经常被调用audit.html.haml

class Survey < ActiveRecord::Base
  def dependant_surveys
    self.review.surveys.select{|survey| self.dependencies.include?(survey.question)}
  end
end

class Question < ActiveRecord::Base
  def dependencies
    Question.all.select{|question| question.precondition == self}
  end
end

(我说“理论上”,因为我知道这个问题也可以通过基准测试来回答。但在我走到那一步之前,我想检查一下我的理论是否正确。)

4

3 回答 3

1

急切加载看起来应该可以工作,但更重要的是,这些是您可以并且应该使用 SQL 做的事情。加载和迭代数据库中的所有 ActiveRecord 模型可能会非常耗时(正如您所发现的),而在 SQL 中弄清楚如何做到这一点将允许您直接从单个查询加载所有模型。处理这个问题可能需要一段时间,但这是值得的!

于 2013-06-19T12:55:33.527 回答
1

你在 ruby​​ 中做了很多处理,没有必要这样做。您应该移动所有操作,例如

Question.all.select{|question| question.precondition == self}
@competitor.surveys.{sorting, etc}

到数据库。

如果我理解正确,第一行是为了选择所有为给定问题设置了先决条件的记录。请记住,它Question.all返回一个数组,因此您可以在数组中执行选择,并且您可以在 db 中以简单的范围scope :has_precondition, -> {|q| where(precondition_id: q.id}左右执行此操作。

order鉴于您总是以相同的方式对模型进行排序,您可以考虑使用子句创建默认范围。在 ruby​​ 中执行此操作非常适得其反。

于 2013-06-19T12:55:44.430 回答
0

据我所知,您只能包含预先加载的关联。我认为你所拥有的根本不会起作用。您还没有向我们展示Question.condition定义的位置,或者Survey.review. 此外,您的方法不会使用您急切加载的关联,dependent_surveys因为dependencies它们正在执行自己的查询。

AFAICT,您的急切加载不会产生任何影响,或者可能会减慢速度。我认为您必须将您的关联重构dependent_surveys为一个关联并急切地加载它。在高层次上,我没有丝毫线索该方法试图做什么,所以我什至不打算尝试重构它。

于 2013-06-19T13:12:14.927 回答