简体   繁体   中英

Why does ActiveRecord find_by return nil when using it together with select?

I found the following kind of usage of ActiveRecord#find_by written in a Rails 4.1 project:

booking = Booking.find_by(member_id: Member.where(id: 1).select(:id))

However, this query returned nil after upgrading the project to Rails > 4.2.

In Rails 4.2 the above query generates the following SQL:

SELECT "bookings".* FROM "bookings" WHERE "bookings"."member_id" = $1 LIMIT 1 [["member_id", nil]]

A 'Booking' belongs to a 'Member' and a 'Member' has many 'Booking'.

Does anyone know or see why? I would be interested in an explanation.

Replacing the select with pluck brings back the expected behavior:

booking = Booking.find_by(member_id: Member.where(id: 1).pluck(:id))

Generated query: SELECT "bookings".* FROM "bookings" WHERE "bookings"."member_id" = 1 LIMIT 1

Edit: A member record with ID 1 exists in the database.

Member.where(id: 1).select(:id) returns the following result and SQL statement with Rails 4.2:

=> #<ActiveRecord::Relation [#<Member id: 1>]>

SELECT "members"."id" FROM "members" WHERE "members"."id" = $1 [["id", 1]]

Because is the default behavior of find_by :

Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself.

If no record is found, returns nil.

The SQL produced shows the result of Member.where(id: 1).select(:id) is converted to nil at the moment of executing the query. Which is the case of being an empty array - denoting there are no members with id = 1 .


Note if you have the member ids you don't need to query them (again). It's supposed a book should have a member_id column, which allows you to do:

Book.where(member_id: <member_ids>)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM