问题
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