A situation where ActiveRecord and SQL do not return the same results due to unknown OID being treated as String

…衆ロ難τιáo~ 提交于 2019-12-24 05:55:22

问题


I have a problem. Earlier I posted a similar question to the one I am about to ask which was answered and can be found here for context ActiveRecord Count and SQL count do not match

That question had to do with counting a query result. In this question, instead of not getting the same count result, I am getting different object results.

Here is the ActiveRecord code:

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)")

This returns [#<Account:0x007f96bf143c70 id: >] and I get this message after the sql output unknown OID 2249: failed to recognize type of 'row'. It will be treated as String.

If I run the above sql code in the database, I retrieve what I need:

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

What causes this mismatch and how can I avoid it. I found this post about custom postgres types Custom postgres types but this looks like I would need to get to the nitty gritty of things and I would like to avoid this. Does someone know why this is a problem?


回答1:


You got this problem because ActiveRecord can't recognize this row as row from your account table. AR not parsing your sql and it's not sure what to do with anonymous cortage.

If you use find_by_sql your selected attributes not mapped to your model properly but still accessible, so try:

result.id
result.email

But you also have two ways to fix that.

First (it's very hackish but easy solution), transform your sql to Arel, that vaild for the scopes:

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"))

... and call AR distinct method:

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

Second (it's much better solution):

Don't use sql directly. Rewrite your scope with Arel (https://github.com/rails/arel) or with squeel (https://github.com/activerecord-hackery/squeel)



来源:https://stackoverflow.com/questions/37817143/a-situation-where-activerecord-and-sql-do-not-return-the-same-results-due-to-unk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!