New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.) |
@@ -793,6 +793,11 @@ def test_pluck_loaded_relation_sql_fragment | |||
end | |||
end | |||
|
|||
def test_pick | |||
assert_equal "The First Topic", Topic.order(:id).pick(:heading) | |||
assert_nil Topic.where(id: 9999999999999999999).pick(:heading) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Failing the assert will be fixed by #30000.
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
end So 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.