Rails 3“last”方法从ActiveRecord输出返回不正确的结果

时间:2011-05-03 01:03:59

标签: ruby-on-rails ruby-on-rails-3

我的控制器中有以下代码:

@items = Item.where(:user_id => 1).order("updated_at DESC").limit(2)
@oldest_item = @items.last

出于某种原因,我猜这与我最近升级到Rails 3有关,@ oldest_item没有被设置为@items中的最后一项,而是被设置为匹配的最后一项{ {1}}。

所以想象有3个项目匹配,A,B和C. @items被设置为[A,B],然后@oldest_item被设置为C.

奇怪的是,当我在视图中调用Item.where(:user_id => 1).order("updated_at DESC")时,它正确地返回B.

当我将控制器中的两行粘贴到控制台时,它也会正确返回B.

有人可以向我解释这里到底发生了什么事吗?

2 个答案:

答案 0 :(得分:5)

出于某种原因,ActiveRecord :: Relation忽略了limit选项。

在Rails 3中,ActiveRecord实际上不会执行您的查询,直到需要访问结果。调用last执行此操作(但同样,忽略限制)。

您可以通过在查询中调用all来告诉ActiveRecord执行查询。然后,当您在其上运行last时,它会为您提供您正在寻找的“最后”记录。

@items = Item.where(:user_id => 1).order("updated_at DESC").limit(2)
# @items is an ActiveRecord::Relation here
@oldest_item = @items.last
# Returns "C" instead of "B". This is actually ignoring the `limit` parameter

@items = Item.where(:user_id => 1).order("updated_at DESC").limit(2).all
# @items is an Array of ActiveRecord objects here
@oldest_item = @items.last
# Returns "B"

这对我来说似乎不是预期的行为。我在rails issues tracker中提交了一个错误。

更新:@BaroqueBobcat提交了一个patch已被接受,因此应该在即将发布的Rails 3.1版本中修复。

答案 1 :(得分:0)

我正在使用Rails 6,并且遇到类似的问题。我在记录上使用了reload从数据库中重新加载了它。

account = Account.new
# => #<Account id: nil, email: nil>
account.id = 1
account.reload
# Account Load (1.2ms)  SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1  [["id", 1]]
# => #<Account id: 1, email: 'account@example.com'>