Add Relation#pick as short-hand for single-value plucks#31941
Conversation
|
Might we want Person.where(id: 1).pick(:name, :email)
# SELECT people.name, people.email FROM people WHERE id = 1 LIMIT 1
# => ['Daniel', 'i@heart.rails'](I was unreasonably nervous to leave this comment. I actually wrote it, then deleted it, then wrote it again.) |
|
|
||
| def test_pick | ||
| assert_equal "The First Topic", Topic.order(:id).pick(:heading) | ||
| assert_nil Topic.where(id: 9999999999999999999).pick(:heading) |
This reminds me of some of the philosophy behind #26206. Might it be worth codifying that rule? def pick(*column_names)
rows = limit(2).pluck(*column_names)
raise "Too many rows" if rows.size > 1
rows.first
end |
|
The specific relation that I extracted #pick from actually does comprise multiple rows, but I know that I just want to deal with the first one (because I ordered the relation in such a way. Here's the actual source: module Person::Creator
extend ActiveSupport::Concern
def last_created_at_from(recordings)
recordings.where(creator: self).reverse_chronologically.pick(:created_at)
end
endSo a guard clause against multiple rows wouldn't really work for this. I don't think it's necessary in any case. |
|
@composerinteralia Totally. Just added that 👌 @kamipo I just changed the test for now 🙏 |
|
Will it raise |
|
@rafaelfranca It was only my theoretical guess. I think the test is good idea anyway. Thanks! |
(local tests on mysql2 gem showed performance improvements too) Will be happy to pitch in and get this into Rails if this seems worth a while. |
|
While the database clients supports C typecasting |
|
@rafaelfranca I assume you refer mostly to the more "exotic" types, right? Given the significant performance boost, I personally think it's good to have, or at least have as an option. I believe most people won't see any difference switching to native typecasting. But that's for Rails core team to decide, not me. |
|
Could a name like (I also considered Rails currently has a few bits of naming that can be confusing not only to new devs but also experienced ones – I've worked in Rails for quite a few years now and I still get unsure about |
Pick the first value from the named column in the current relation. This is short-hand for
relation.limit(1).pluck(column_name).first, and is primarily useful when you have a relation that's already narrowed down to a single row.Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also more efficient. The value is, again like with pluck, typecast by the column type.