Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 即时加载、模型方法、字段u for、each和N+;1._Ruby On Rails_Ruby_Ruby On Rails 4 - Fatal编程技术网

Ruby on rails 即时加载、模型方法、字段u for、each和N+;1.

Ruby on rails 即时加载、模型方法、字段u for、each和N+;1.,ruby-on-rails,ruby,ruby-on-rails-4,Ruby On Rails,Ruby,Ruby On Rails 4,我有一个相当复杂的应用程序(超过30个表),它有一些持久的N+1问题,我认为这是因为我没有按照Rails的方式做一些事情™' 我将给出一个更复杂的例子。这个表包括四个表:clin、positions\u tasks、tasks和labour\u hours positions\u tasks是clin、positions(本例中不需要)和tasks之间的三向多对多联接,它有很多:工时。工时表有一个整型字段,用于一年中的每个月和一些其他数据。一种方法,total_hours,将所有月份相加为一年的

我有一个相当复杂的应用程序(超过30个表),它有一些持久的N+1问题,我认为这是因为我没有按照Rails的方式做一些事情™'

我将给出一个更复杂的例子。这个表包括四个表:
clin、positions\u tasks、tasks
labour\u hours

positions\u tasks
clin、positions
(本例中不需要)和
tasks
之间的三向多对多联接,它
有很多:工时
。工时表有一个整型字段,用于一年中的每个月和一些其他数据。一种方法,
total_hours
,将所有月份相加为一年的总小时数。在clin视图中,它显示clin信息和所有相关任务的表[以及其他相关数据],并对每个任务的小时数求和,
有许多:工时,:到=>:位置\u任务
。我急切地加载了所有相关的表,包括工时,除工时外,所有的N+1问题都消失了

下面是代码片段

clins_控制器的紧急负载:

@clin = Clin.includes(:proposal).includes(:positions_tasks).includes(:tasks).includes(:labor_hours).includes(:wbss).find(params[:id])`
在clins/_form.html.erb中显示表格行:

    <tbody>
        <% @clin.tasks.distinct.each do |t| %>
          <%= f.fields_for :task, t do |builder| %>
            <%= render "tasks/task_row", f: builder %>
          <% end %>
        <% end %>
    </tbody>
我认为正在发生的事情是,在_form.html.erb中的和字段_中,急切的加载正在消失,因为它传递的是任务对象而不是clin对象,和/或对total_hours的调用导致它所调用的每个对象的加载,但我不知道如何确定它是什么,也不知道如何解决它们


在没有N+1工时加载的情况下,如何为表中的每个任务提供总计的
任务、工时、总工时?
,我不确定,但我有一个理论。您有这个(我已经删除了刚才与我们无关的
includes
调用:

@clin = Clin.includes(:tasks).includes(:labor_hours).find(params[:id])
您在这里所做的是急切地加载与每个临床相关的任务,以及到目前为止与每个临床相关的工时,非常好,但在您看来,您正在这样做(或多或少):

在这里,您不是访问与每个临床相关联的劳动时间,这是您希望加载的内容,而是访问与每个临床相关联的每个任务相关联的劳动时间。要访问与每个临床相关联的劳动时间,您必须执行以下操作:

@clin.labor_hours.each do |labor_hour|
  # ...
end
但是,由于您正在呈现任务(而不仅仅是工时),我认为这不是您想要的。相反,您需要告诉Rails您想要加载二阶关联,即与任务关联的工时,而不是通过将哈希传递给
includes
,来加载与CLIN关联的工时:

@clin = Clin.includes(:tasks => :labor_hours).find(params[:id])

另外,您还可以做一些额外的改进,例如,看起来您实际上并没有使用LaborHours中的任何属性,您实际上只是使用了
total_hours
列的总和。但是,在Ruby中计算总和是一种浪费,因为您可以让数据库来做。然而,这超出了这个答案。

Protip(这根本无助于解决您的问题):您可以将多个参数传递给
includes
Clin.includes(:提案,:职位任务,:任务,:工时,:wbss)。find(参数[:id])
从现在起我将使用该约定。谢谢!你太棒了。我将控制器更新为:
@clin=clin.includes(:proposal,:positions\u tasks,:wbss)。includes(:tasks=>:labor\u hours)。find(params[:id])
并且N+1已解决。太棒了!你还可以执行
clin.includes(:proposal,:positions\u tasks,:wbss,:tasks=>:labor\u hours)。find(params[:id])
我尝试了
Clin.includes(:proposition,:positions\u tasks,:tasks=>:labor\u hours,:wbss)。find(params[:id])
和NetBeans不喜欢它,所以我做了另一个,但在最后,当您键入它时,它很好。另一方面,我必须在模型/迁移中放入什么才能让数据库为我做添加?
class PositionsTask < ActiveRecord::Base
  nilify_blanks

  belongs_to :task
  belongs_to :position
  belongs_to :clin

  has_many :labor_hours

  has_one :company, :through => :position
  has_one :proposal, :through => :clin
  has_one :wbs_line_item, :through => :task
  delegate :wbs, :to => :wbs_line_item

  delegate :pws_line_items, :to => :wbs_line_item
  delegate :pwss, :to => :wbs_line_item

  validates_presence_of :task
  validates_presence_of :position
  validates_presence_of :clin

  accepts_nested_attributes_for :labor_hours, allow_destroy: true
end
class Task < ActiveRecord::Base
  nilify_blanks

  belongs_to :wbs_line_item
  belongs_to :task_category

  has_many :positions_tasks

  has_many :labor_hours, :through => :positions_tasks
  has_many :positions, :through => :positions_tasks
  has_many :clins, :through => :positions_tasks
  has_many :proposals, :through => :positions_tasks

  delegate :wbs, :to => :wbs_line_item
  delegate :pws_line_items, :to => :wbs_line_item
  delegate :pwss, :to => :wbs

  accepts_nested_attributes_for :positions_tasks, allow_destroy: true
  accepts_nested_attributes_for :labor_hours, allow_destroy: true

  validates_associated :positions_tasks

end
Started GET "/clins/11/edit" for 127.0.0.1 at 2015-07-20 17:48:49 -0400
Processing by ClinsController#edit as HTML
  Parameters: {"id"=>"11"}
  Clin Load (0.2ms)  SELECT  "clins".* FROM "clins" WHERE "clins"."id" = $1 LIMIT 1  [["id", 11]]
  Proposal Load (0.2ms)  SELECT "proposals".* FROM "proposals" WHERE "proposals"."id" IN (1)
  PositionsTask Load (0.4ms)  SELECT "positions_tasks".* FROM "positions_tasks" WHERE "positions_tasks"."clin_id" IN (11)
  Task Load (0.6ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" IN (1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 20, 23, 24)
  LaborHours Load (1.1ms)  SELECT "labor_hours".* FROM "labor_hours" WHERE "labor_hours"."positions_task_id" IN (1, 2, 3, 6, 7, 8, 9, 10, 12, 13, 14, 18, 19, 20, 21, 23, 24, 25, 26, 27, 30, 35, 36, 37)
  WbsLineItem Load (0.5ms)  SELECT "wbs_line_items".* FROM "wbs_line_items" WHERE "wbs_line_items"."id" IN (310, 312, 314, 316, 317, 318, 319, 413, 320, 321, 322, 324, 325, 326, 327, 328, 330, 333, 334)
  Wbs Load (0.4ms)  SELECT "wbss".* FROM "wbss" WHERE "wbss"."id" IN (1)
  Clin Load (0.2ms)  SELECT "clins".* FROM "clins"
  Rendered tasks/_task_header.html.erb (0.0ms)
  LaborHours Load (0.4ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 1]]
  Rendered tasks/_task_row.erb (2.6ms)
  LaborHours Load (0.3ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 2]]
  Rendered tasks/_task_row.erb (1.7ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 3]]
  Rendered tasks/_task_row.erb (1.4ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 5]]
  Rendered tasks/_task_row.erb (1.3ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 6]]
  Rendered tasks/_task_row.erb (1.4ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 7]]
  Rendered tasks/_task_row.erb (1.5ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 8]]
  Rendered tasks/_task_row.erb (1.3ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 9]]
  Rendered tasks/_task_row.erb (1.3ms)
  LaborHours Load (0.4ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 10]]
  Rendered tasks/_task_row.erb (1.9ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 11]]
  Rendered tasks/_task_row.erb (1.5ms)
  LaborHours Load (0.4ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 12]]
  Rendered tasks/_task_row.erb (2.2ms)
  LaborHours Load (0.5ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 14]]
  Rendered tasks/_task_row.erb (2.6ms)
  LaborHours Load (0.4ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 15]]
  Rendered tasks/_task_row.erb (2.2ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 16]]
  Rendered tasks/_task_row.erb (1.5ms)
  LaborHours Load (0.3ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 17]]
  Rendered tasks/_task_row.erb (1.9ms)
  LaborHours Load (0.3ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 18]]
  Rendered tasks/_task_row.erb (1.6ms)
  LaborHours Load (0.3ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 20]]
  Rendered tasks/_task_row.erb (1.9ms)
  LaborHours Load (0.2ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 23]]
  Rendered tasks/_task_row.erb (1.6ms)
  LaborHours Load (0.3ms)  SELECT "labor_hours".* FROM "labor_hours" INNER JOIN "positions_tasks" ON "labor_hours"."positions_task_id" = "positions_tasks"."id" WHERE "positions_tasks"."task_id" = $1  [["task_id", 24]]
  Rendered tasks/_task_row.erb (1.9ms)
  Rendered clins/_form.html.erb (47.6ms)
  Rendered clins/_errors.html.erb (0.0ms)
  Rendered clins/edit.html.erb within layouts/application (48.6ms)
  Rendered layouts/_header.html.erb (60.5ms)
  Rendered layouts/_sidenav.html.erb (0.4ms)
  Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 140ms (Views: 106.4ms | ActiveRecord: 8.8ms)
@clin = Clin.includes(:tasks).includes(:labor_hours).find(params[:id])
@clin.tasks.distinct.each do |task|
  # inside the partial...
  task.labor_hours...
end
@clin.labor_hours.each do |labor_hour|
  # ...
end
@clin = Clin.includes(:tasks => :labor_hours).find(params[:id])