Mysql N+;1视图错误

Mysql N+;1视图错误,mysql,ruby,ruby-on-rails-3,ruby-on-rails-4,Mysql,Ruby,Ruby On Rails 3,Ruby On Rails 4,我认为导致这个N+1错误的原因是,由于视图必须呈现集合,因此每个状态更新都需要进行查询调用,以便显示它相对于其他状态更新的变量 这导致了大量的查询。如何使所有这些状态更新一次可用,并从status update类中调用数组来进行这些计算,而不是每次都访问数据库 我可能会错过一些东西,所以任何洞察都会很棒!我尝试过使用include和大约100个其他东西来更改查询调用 这是bullet给我的错误信息: user: Pablo N+1 Query detected StatusUpdate =&

我认为导致这个N+1错误的原因是,由于视图必须呈现集合,因此每个状态更新都需要进行查询调用,以便显示它相对于其他状态更新的变量

这导致了大量的查询。如何使所有这些状态更新一次可用,并从status update类中调用数组来进行这些计算,而不是每次都访问数据库

我可能会错过一些东西,所以任何洞察都会很棒!我尝试过使用include和大约100个其他东西来更改查询调用

这是bullet给我的错误信息:

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 
状态更新控制器#显示

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('&times;'.html_safe, status_updates, method: :delete) %></td>
</tr>

%
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   
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
class客户端
我建议不要每次阅读
状态更新时都计算
权重变化
,而应该在自己的列中写入
状态更新时计算它(
权重变化


这种读取记录的方法是直接的,不需要任何循环回到旧记录。

为什么不在创建记录时将权重更改保存到
状态更新中呢?显示状态更新的内容,而不是使用
某些数组[-1]
,最好使用
some_array.last
如果只是为了清楚起见。好的,我编辑了这个问题,包括了部分调用和部分调用的模型调用,这样你就可以更全面地了解发生了什么。@UriAgassi我明白了。因此,与每次调用状态更新时搜索此信息不同,我可以在创建状态更新时将信息保存到每个状态更新中,因此我只在每个状态更新中调用信息,因为该信息与其他信息相关。
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