0
0
RailsHow-ToBeginner · 3 min read

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_by without 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

MethodDescription
find_or_create_byFinds the first record matching attributes or creates it if none found.
find_or_initialize_byFinds the first record or initializes a new one without saving.
createCreates 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.