ruby-on-rails – 为什么Foo.first返回最后一条记录?

我在Foo中有2条记录,id为1和2.两者都是按顺序创建的.请记住,在Postgres中,记录没有固有的顺序.

在Rails控制台中. Foo.first和Foo.last返回最后一条记录.我的印象是Foo.first会返回第一条记录.

这是捕获. SQL查询看起来像:

SELECT "foos".* FROM "foos" LIMIT 1
SELECT "foos".* FROM "foos" ORDER BY "foos"."id" DESC LIMIT 1

第二个查询(Foo.last)有一个ORDER BY DESC.那么为什么AR没有为.first提供ORDER BY ASC?这背后的逻辑是什么?似乎有点“不一致”.

我可以通过这样做来轻松解决这个问题:Foo.order(‘id ASC’).首先代替.但寻找解释.

解决方法

它没有任何逻辑,如果首先有任何意义(或最后那个问题),那么如果你忽略指定一个显式顺序作为第一个参数或作为当前的一部分,它将引发异常范围链.除非指定了明确的排序,否则在关系数据库的上下文中,无论是第一个还是最后一个都没有任何意义.

我的猜测是,如果没有明确的顺序,那么首先写入的人假定whatever_the_pk_is的顺序是隐含的.然后他们可能做了一些实验来经验验证他们的假设,它恰好按照他们所期望的特定表格和数据库进行工作(迷你咆哮:这就是为什么你永远不会假设未指明的行为;如果某个特定的行为是没有明确指定,即使当前实现的行为方式或者经验证据表明它的行为方式,也不要假设它.

如果你追踪一个简单的M.first,你会发现it does this

limit(1).to_a[0]

没有明确的排序,所以你得到数据库感觉使用的任何随机排序,可以通过pk排序,也可以是磁盘上表的块顺序.如果你追溯到M.last,你将到达find_last

def find_last
  #...
        reverse_order.limit(1).to_a[0]
  #...
end

reverse_order

def reverse_order
  relation = clone
  relation.reverse_order_value = !relation.reverse_order_value
  relation
end

@reverse_order_value实例变量未初始化,因此它将以nil和a开头!会把它变成真实的.如果您四处寻找@reverse_order_value的使用方法,那么您将进入reverse_sql_order

def reverse_sql_order(order_query)
  order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
  #...

还有作者关于订购的无效假设让所有人都知道.该行应该是:

raise 'Specify an order you foolish person!' if order_query.empty?

我建议你总是使用.order(…).limit(1).first而不是first或last,这样一切都很好而且明确;当然,如果你想要最后你反转.order条件.或者你总是可以说.first(:order =>:whatever)和.last(:order =>:whatever)再次使一切都清楚.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...