首页 > 解决方案 > rails find_by 返回不正确的记录?

问题描述

我有一个应用程序,其中 aUser创建一个TransactionItem不同的User. 我突然对 .in find_byone 方法有困难Item。我想找到第一个Transaction涉及Item调用它的对象,并且我想通过搜索许多无效状态来进一步限制该结果。

class Item < ApplicationRecord
 def first_find
  Transaction.find_by("item_id = ? AND recipient_id = ? AND state != ? OR state != ? OR state != ?", self.id, author.id, :ignored, :declined, :unapproved)
 end
end

无论如何,它的作用是返回Transaction我的数据库中的第一个。这不是预期的行为。所以在控制台中,如果我想t = Transaction.last缓存Transactionid #5(它的 anitem_id为 7,arecipient_id为 4),然后调用t.item.first_find,我大概会得到Transaction#5。对此的 SQL 输出是 query is Transaction Load (1.1ms) SELECT "transactions".* FROM "transactions" WHERE (item_id = 7 AND recipient_id = 4 AND state != 'ignored' OR state != 'declined' OR state != 'unapproved') LIMIT $1 [["LIMIT", 1]]

太棒了!这就是我想要的输出。但令我困惑的是,它返回了这个:

#<Transaction id: 2, sender_id: 1, recipient_id: 2, item_id: 9 ..... >

有谁知道为什么?谢谢!


编辑 1

所以我想我已经解决了?在将太多搜索参数放入where子句中之前,我遇到过这个问题,因为某种原因会弄乱它。

所以虽然这不起作用

Transaction.find_by("item_id = ? AND recipient_id = ? AND state != ? OR state != ? OR state != ?", self.id, author.id, :ignored, :declined, :unapproved)

这确实

Transaction.where("item_id = ? AND recipient_id = ?", self.id, author.id).where("state != ? OR state != ? OR state != ?", :ignored, :declined, :unapproved).first

不过,我不完全确定为什么。有人知道吗?


编辑 2

AND 运算符应与 OR 运算符分开。

标签: ruby-on-rails

解决方案


answering why. that's how SQL operator precedence works. more explanation is here. so when you break it to another "where" clause that builds a new relation, which is the result of filtering the current relation according to the conditions in the arguments. the source code is here.

let me show other solutions.

1.

    Transaction.where(item_id: self.id, recipient_id: author.id).where.not(state: [:ignored, :declined, :unapproved]).first

2.

recipient_transactions = Transaction.where(item_id: self.id, recipient_id: author.id)
active_transactions = Transaction.where.not(state: [:ignored, :declined, :unapproved])
result = recipient_transactions.merge(active_transactions).first # this buils a single query

推荐阅读