我认为导致此N + 1错误的原因是,由于视图必须呈现集合,因此每个状态更新都需要进行查询调用,以便显示相对于其他状态更新的变量。
这会产生很多疑问。我怎样才能一次性提供所有这些状态更新,只需从状态更新类中调用数组进行这些计算,而不是每次都进入数据库?
我可能会遗漏一些东西,所以任何见解都会很棒!我尝试使用include更改我的查询调用,以及大约100个其他内容。
这是错误的子弹给我:
user: Pablo
N+1 Query detected
StatusUpdate => [:client]
Add to your finder: :include => [:client]
N+1 Query method call stack
/Users/Nick/Code/Rails/gj/app/models/status_update.rb:27:in `prev'
/Users/Nick/Code/Rails/gj/app/models/status_update.rb:36:in `weight_change'
/Users/Nick/Code/Rails/gj/app/models/client.rb:11:in `weight_change'
/Users/Nick/Code/Rails/gj/app/views/status_updates/show.html.erb:39:in `_app_views_status_updates_show_html_erb__176120213182464780_70358939483460'
status_updates.rb
def prev
prev = self.client.status_updates.where("created_at < ?", self.created_at)[-1]
if prev == nil
prev = self
else
prev
end
end
def weight_change
weight_change = prev.total_weight - total_weight
cut weight_change
end
client.rb
def weight_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.weight_change
end
end
StatusUpdatesController#节目
def show
if status_updates?
current_client.id).limit(7).reverse
@status_updates = current_client.status_updates.limit(7).reverse
end
@status_update = current_client.status_updates.new
end
show.html
<% if @status_updates != nil %>
<%= render(partial: "status_updates", collection: @status_updates) %>
<% else %>
<p style="text-align:center">No status updates yet.</p>
<% end %>
_status_updates.html
<tr>
<td class="left"><%= status_updates.entry_date.strftime("%m/%d/%y") %></td>
<td class="left phase"><%= status_updates.phase %> <a href="#">+</a></td>
<td><%= status_updates.total_weight %></td>
<td><%= status_updates.weight_change %></td>
<td><%= status_updates.lbm_weight %></td>
<td><%= status_updates.lbm_change %></td>
<td><%= status_updates.total_lbm_change %></td>
<td><%= BigDecimal(status_updates.body_fat_pct * 100, 5)%>%</td>
<td><%= status_updates.fat_change %></td>
<td><%= status_updates.total_fat_change %></td>
<td><%= link_to('×'.html_safe, status_updates, method: :delete) %></td>
</tr>
client.rb
class Client < ActiveRecord::Base
belongs_to :trainer
has_many :status_updates
validates :firstname, :lastname, presence: true
def weight_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.weight_change
end
end
def fat_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.fat_change
end
end
def lbm_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.lbm_change
end
end
def bfp_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.bfp_change
end
end
def total_weight_change(stat_present)
if stat_present == false
0
elsif stat_present == true
self.status_updates.reverse.first.total_weight_change
end
end
end
答案 0 :(得分:1)
我建议您每次读取 weight_change
时不要计算status_update
,而是在写 {{1}时计算它在它自己的列(status_update
)。
通过这种方式阅读记录是直截了当的,并且不需要循环回旧记录。