Skip to content

Commit 7830727

Browse files
committed
Document UUID keys, polymorphic associations, and custom key strategies
1 parent 20d68a4 commit 7830727

1 file changed

Lines changed: 109 additions & 1 deletion

File tree

README.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ FixtureBot lets you define your test data in a Ruby DSL and compiles it into sta
99
- **Ruby DSL** for defining records, associations, and join tables
1010
- **Generators** for filling in required columns (like email) across all records
1111
- **Stable IDs** so foreign keys are consistent and diffs are clean across runs
12+
- **UUID support** for tables with UUID primary keys
13+
- **Polymorphic associations** with automatic type column resolution
1214
- **Schema auto-detection** from your Rails database (no manual column lists)
1315
- **Auto-generates** before your test suite runs (RSpec and Minitest)
1416

@@ -175,7 +177,13 @@ FixtureBot.define do
175177
end
176178
```
177179

178-
The generator block receives a `fixture` object as a block parameter with access to `fixture.key` (the record's symbol name). Bare methods inside the block refer to column values set on the record.
180+
The generator block receives a `fixture` object with a `key` method (the record's symbol name). Bare methods inside the block refer to column values set on the record:
181+
182+
```ruby
183+
FixtureBot.define do
184+
user.display_name { |fixture| "#{fixture.key} (#{email})" }
185+
end
186+
```
179187

180188
When a generator covers all the columns you need, records don't need a block at all:
181189

@@ -225,6 +233,46 @@ FixtureBot.define do
225233
end
226234
```
227235

236+
### Polymorphic associations
237+
238+
For polymorphic `belongs_to`, reference the target using its table helper to set both `_id` and `_type` columns:
239+
240+
```ruby
241+
FixtureBot.define do
242+
post :hello do
243+
title "Hello"
244+
end
245+
246+
comment :nice do
247+
body "Nice post"
248+
end
249+
250+
vote :upvote_post do
251+
votable post(:hello) # sets votable_id and votable_type: "Post"
252+
end
253+
254+
vote :upvote_comment do
255+
votable comment(:nice) # sets votable_id and votable_type: "Comment"
256+
end
257+
end
258+
```
259+
260+
In the manual schema, declare polymorphic associations with `polymorphic`:
261+
262+
```ruby
263+
FixtureBot::Schema.define do
264+
table :posts, singular: :post, columns: [:title]
265+
table :comments, singular: :comment, columns: [:body]
266+
267+
table :votes, singular: :vote, columns: [:votable_id, :votable_type, :voter_id] do
268+
polymorphic :votable
269+
belongs_to :voter, table: :users
270+
end
271+
end
272+
```
273+
274+
In Rails, polymorphic associations are auto-detected from `_id`/`_type` column pairs that don't have a foreign key constraint.
275+
228276
### Join tables (HABTM)
229277

230278
Reference multiple records for join table associations:
@@ -238,6 +286,66 @@ FixtureBot.define do
238286
end
239287
```
240288

289+
### Hardcoded IDs
290+
291+
By default, FixtureBot generates stable IDs deterministically from the table and record name. You can override this with an explicit value:
292+
293+
```ruby
294+
FixtureBot.define do
295+
user :admin do
296+
id 42
297+
name "Admin"
298+
end
299+
300+
post :hello do
301+
title "Hello"
302+
author :admin # author_id resolves to 42
303+
end
304+
end
305+
```
306+
307+
### UUID primary keys
308+
309+
Tables with UUID primary keys work automatically in Rails (detected from the column type). In the manual schema, pass `key: FixtureBot::Key::Uuid`:
310+
311+
```ruby
312+
FixtureBot::Schema.define do
313+
table :projects, singular: :project, columns: [:name], key: FixtureBot::Key::Uuid
314+
end
315+
```
316+
317+
FixtureBot generates deterministic UUID v5 values, so the output is stable across runs.
318+
319+
You can also provide your own key strategy — any object (or module) that responds to `generate(table_name, record_name)`. For example, Stripe-style prefixed IDs:
320+
321+
```ruby
322+
module PrefixedKey
323+
module_function
324+
325+
def generate(table_name, record_name)
326+
hash = Zlib.crc32("#{table_name}:#{record_name}").to_s(36)
327+
"#{table_name.to_s.chomp('s')}_#{hash}"
328+
end
329+
end
330+
331+
FixtureBot::Schema.define do
332+
table :customers, singular: :customer, columns: [:name], key: PrefixedKey
333+
# => customer_id: "customer_1a2b3c"
334+
end
335+
```
336+
337+
### Custom primary key column
338+
339+
If your table uses a column other than `id` as the primary key:
340+
341+
```ruby
342+
FixtureBot::Schema.define do
343+
table :users, singular: :user, columns: [:name], primary_key: :uid
344+
end
345+
```
346+
347+
In Rails, this is auto-detected from the database.
348+
241349
### Implicit vs explicit style
242350

243351
By default, the block is evaluated implicitly. Table methods like `user` and `post` are available directly:

0 commit comments

Comments
 (0)