Skip to content

Commit a5c26c1

Browse files
committed
Add Find Or Create A Record With FactoryBot as a Rails til
1 parent b61ac66 commit a5c26c1

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
1010

1111
For a steady stream of TILs, [sign up for my newsletter](https://tinyletter.com/jbranchaud).
1212

13-
_1138 TILs and counting..._
13+
_1139 TILs and counting..._
1414

1515
---
1616

@@ -692,6 +692,7 @@ _1138 TILs and counting..._
692692
- [Different Ways To Add A Foreign Key Reference](rails/different-ways-to-add-a-foreign-key-reference.md)
693693
- [Disambiguate Where In A Joined Relation](rails/disambiguate-where-in-a-joined-relation.md)
694694
- [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md)
695+
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
695696
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
696697
- [Generating And Executing SQL](rails/generating-and-executing-sql.md)
697698
- [Get An Array Of Values From The Database](rails/get-an-array-of-values-from-the-database.md)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Find Or Create A Record With FactoryBot
2+
3+
I have a bunch of tests throughout my test suite that rely on a particular kind
4+
of unique record. Let's say it is a special admin user.
5+
6+
```ruby
7+
admin = FactoryBot.create(:user, email: 'admin@company.com')
8+
```
9+
10+
If this user has already been created then trying to re-create it with
11+
[FactoryBot](https://github.com/thoughtbot/factory_bot) will result in a unique
12+
email validation error.
13+
14+
Another way to approach this would be to either find or create the admin user.
15+
In some standard Rails code that might look like this:
16+
17+
```ruby
18+
admin =
19+
User.find_by(email: 'admin@company.com') ||
20+
FactoryBot.create(:user, email: 'admin@company.com')
21+
```
22+
23+
There is some repetitiveness to this that I'd like to avoid. FactoryBot doesn't
24+
have an equivalent to ActiveRecord's `find_and_create_by`, but we can work
25+
around this.
26+
27+
We can add an `initialize_with` directive to the `User` factory.
28+
29+
```ruby
30+
FactoryBot.define do
31+
factory :user do
32+
sequence(:email) { |n| 'user#{n}@example.com' }
33+
34+
# a bunch of other attributes
35+
36+
initialize_with { User.find_or_create_by(email: email) }
37+
end
38+
end
39+
```
40+
41+
With this in place, we can call `FactoryBot.create` with the already existing
42+
_admin_ user and it will look up the record instead of raising a validation
43+
error.
44+
45+
[source](https://stackoverflow.com/a/11799674/535590)

0 commit comments

Comments
 (0)