我的控制器中有一个完美运行的查询:
@klasses_mon = Klass.order(:start).where(day:' MON')。find_each
我的结果是(在我看来<%= @klasses_mon.inspect %>
显示):
#<Enumerator: #<ActiveRecord::Relation
[#<Klass id: 9, name: "Cycling", teacher: "Tomek", day: "MON", start: 510, duration: 45>,
#<Klass id: 8, name: "LBT", teacher: "Monia", day: "MON", start: 600, duration: 60>,
#<Klass id: 11, name: "HIIT", teacher: "Aga", day: "MON", start: 930, duration: 45>]>
:find_each({:start=>nil, :finish=>nil, :batch_size=>1000, :error_on_ignore=>nil})>
但我试图在每个循环中显示它。由于某种原因,它不再被订购。看起来每个循环都不会保留查询结果的顺序:
<% @klasses_mon.each do |k| %>
<p><%= k.teacher %>,
<%= k.name %>
START: <%= k.start/60 %>:<%= k.start%60 %>
<% end %>
结果:
Monia,LBT START:10:0
Tomek,Cycling START:8:30
Aga,HIIT START:15:30
我该怎么做?
答案 0 :(得分:2)
来自fine manual:
find_each (start:nil,finish:nil,batch_size:1000,error_on_ignore:nil)
[...]
注意:无法设置订单。在主键(“id ASC”)上自动设置为升序,以使批量订购工作。这也意味着此方法仅在主键可订购时有效(例如整数或字符串)。
因此明确记录find_each
以忽略您尝试使用的任何排序。
find_each
不使用LIMIT和OFFSET将批处理窗口移动到结果集中,因为随着OFFSET的增加,它往往非常昂贵,而是按主键排序并包含{{1}用于设置批处理开始的WHERE子句中的condition和用于设置批处理大小的LIMIT子句。通过PK排序和查询PK通常都是廉价的,因为LIMIT条款。
id > last_one
是这项工作的错误工具,find_each
用于批处理工作,但您只是显示一个简短的记录列表,所以您想要一个简单的工具:
find_each
答案 1 :(得分:1)
方法#find_each
忽略任何作用域order
并强制按主键排序(通常为id
)。这在documentation中说明,因为#find_each
需要确保它在迭代期间不会重复任何记录。
如果您尝试:
,您可以在控制台中看到此信息> @klasses_mon = Klass.order(:start).where(day: 'MON').find_each
> @klasses_mon.map(&:start) # force the relation to execute and return rows.
Scoped order is ignored, it's forced to be batch order.
Klass Load (0.ms) SELECT "klasses".* FROM "klasses" WHERE "klasses"."day" = 'MON' ORDER BY "klasses"."id"
=> [600, 510, 930]
如果您不希望经历数千行,则可以删除find_each
:
@klasses_mon = Klass.where(day: "MON").order(:start)