由于未知OID被视为String,ActiveRecord和SQL不会返回相同结果的情况

我有个问题。 之前我发布了一个类似的问题,我要问的是哪个问题得到解答,可以在这里找到上下文ActiveRecord Count和SQL计数不匹配

这个问题与计算查询结果有关。 在这个问题中,我得到了不同的对象结果,而不是没有得到相同的计数结果。

这是ActiveRecord代码:

scope :unverified_with_no_associations, -> { find_by_sql("SELECT DISTINCT(accounts.id, accounts.email) FROM accounts WHERE level = 0 AND id NOT IN (SELECT DISTINCT(account_id) FROM verifications) AND id NOT IN (SELECT DISTINCT(account_id) FROM positions) AND id NOT IN (SELECT DISTINCT(account_id) FROM edits) AND id NOT IN (SELECT DISTINCT(account_id) FROM posts) AND id NOT IN (SELECT DISTINCT(account_id) FROM reviews) AND id NOT IN (SELECT DISTINCT(sender_id) FROM kudos) AND id NOT IN (SELECT DISTINCT(account_id) FROM stacks WHERE account_id IS NOT NULL)") 

这将返回[#]并在sql输出unknown OID 2249: failed to recognize type of 'row'. It will be treated as String.之后收到此消息unknown OID 2249: failed to recognize type of 'row'. It will be treated as String. unknown OID 2249: failed to recognize type of 'row'. It will be treated as String.

如果我在数据库中运行上面的sql代码,我会检索我需要的东西:

  -------row------- (1234,me@gmail.com) 

导致这种不匹配的原因是什么,我该如何避免它。 我发现这篇post关于自定义postgres类型自定义postgres类型,但这看起来我需要了解事情的细节,我想避免这种情况。 有人知道为什么这是一个问题吗?

您遇到此问题是因为ActiveRecord无法将此行识别为您帐户表中的行。 AR没有解析你的sql而且它不确定如何处理匿名的cortage。

如果您使用find_by_sql您选择的属性未正确映射到您的模型但仍可访问,请尝试:

 result.id result.email 

但是你也有两种方法来解决这个问题。

首先 (这是非常hackish但很简单的解决方案),将您的sql转换为Arel ,即范围的vaild:

 scope :unverified_with_no_associations, -> { send(:default_scoped).from(Arel.sql("(SELECT * FROM accounts WHERE level = 0 AND id NOT IN (SELECT DISTINCT(account_id) FROM verifications) AND id NOT IN (SELECT DISTINCT(account_id) FROM positions) AND id NOT IN (SELECT DISTINCT(account_id) FROM edits) AND id NOT IN (SELECT DISTINCT(account_id) FROM posts) AND id NOT IN (SELECT DISTINCT(account_id) FROM reviews) AND id NOT IN (SELECT DISTINCT(sender_id) FROM kudos) AND id NOT IN (SELECT DISTINCT(account_id) FROM stacks WHERE account_id IS NOT NULL)) AS accounts")) 

…并调用AR不同的方法:

 Account.unverified_with_no_associations.select(:id, :email).distinct 

第二 (这是更好的解决方案):

不要直接使用sql。 用Arelhttps://github.com/rails/arel )或squeelhttps://github.com/activerecord-hackery/squeel )重写你的范围