How to Use find_or_create_by in Ruby on Rails: Syntax and Examples
In Ruby on Rails,
find_or_create_by tries to find the first record matching the given attributes. If no record is found, it creates a new one with those attributes and saves it to the database.Syntax
The find_or_create_by method takes a hash of attributes to search for an existing record. If none is found, it creates and saves a new record with those attributes.
It returns the found or newly created record.
ruby
Model.find_or_create_by(attribute1: value1, attribute2: value2)
Example
This example shows how to find or create a user by email. If a user with the given email exists, it returns that user. Otherwise, it creates a new user with the email and name provided.
ruby
class User < ApplicationRecord end # Usage user = User.find_or_create_by(email: 'jane@example.com') do |u| u.name = 'Jane Doe' end puts user.inspect
Output
#<User id: 1, email: "jane@example.com", name: "Jane Doe", created_at: "2024-06-01 12:00:00", updated_at: "2024-06-01 12:00:00">
Common Pitfalls
- Not using a block to set additional attributes can cause missing data on creation.
- Using
find_or_create_bywithout unique constraints may create duplicate records in race conditions. - It only searches by the attributes given; other fields are ignored in the search.
ruby
wrong_user = User.find_or_create_by(email: 'john@example.com') # This creates a user with only email set, name will be nil right_user = User.find_or_create_by(email: 'john@example.com') do |u| u.name = 'John Smith' end # This sets the name only if a new user is created
Quick Reference
| Method | Description |
|---|---|
| find_or_create_by | Finds the first record matching attributes or creates it if none found. |
| find_or_initialize_by | Finds the first record or initializes a new one without saving. |
| create | Creates and saves a new record with given attributes. |
Key Takeaways
Use find_or_create_by to find a record or create it if missing in one step.
Pass a block to set extra attributes only when creating a new record.
Ensure unique constraints to avoid duplicates in concurrent requests.
find_or_create_by only searches by the attributes you specify.
Use find_or_initialize_by if you want to build but not save a new record.