Rails 7 adds `Enumerable#sole` to return a sole item in the enumerable
source link: https://blog.saeloun.com/2021/05/26/rails-7-adds-enumerable-sole
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 7 adds `Enumerable#sole` to return a sole item in the enumerable
May 26, 2021 , by Prasad Walvekar 1 minute readRails 6.1
added
two query options, namely #sole
and #find_sole_by
to the ActiveRecord::FinderMethods
.
These methods assert that only one unique record is returned from the database.
In Rails 7,
Enumerable#sole
was
added
to the Enumerable
module which behaves similar to
ActiveRecord::FinderMethods
methods - #sole
and #find_sole_by
.
Before
Let’s say we have an app where User
can have multiple api_keys
associated with their accounts.
Each api_key
will be associated with a particular type
.
To implement the above scenario we will design our User and ApiKey models as shown below:
# app/models/user.rb
class User < ApplicationRecord
has_many :api_keys
end
# app/models/api_key.rb
class ApiKey < ApplicationRecord
belongs_to :user
scope :github, -> { where(key_type: "github") }
# == Schema Information
#
# Table name: api_keys
#
# key :string(255)
# user_id :integer
# key_type :string(255)
end
To verify if a user has only one API key of a particular type, we might implement the following code:
user = User.find(1)
keys = user.api_keys.github.pluck(:key)
if keys.length == 1
key = keys.first
elsif keys.length == 0
raise "No records found!"
else
raise "More than one matching record found!"
end
As seen, we have to write a lot of code to fetch a user API key of a particular type.
After
In Rails 7, with Enumerable#sole
we can replace the above code as shown below:
key = user.api_keys.github.pluck(:key).sole
=> "github key"
The Enumerable#sole
method returns one
and
only one element
and
raises an error if there are none or more than one element present in the Enumerable.
key = user.api_keys.github.pluck(:key).sole
# if no API key of particular type exists
=> Enumerable::SoleItemExpectedError (no item found)
# if multiple API keys of a particular type exist
=> Enumerable::SoleItemExpectedError (multiple items found)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK