Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tristandunn/factory_manager

A manager for factory_bot to simplify creating nested factories.
https://github.com/tristandunn/factory_manager

factory factory-bot rspec rspec-rails ruby ruby-on-rails

Last synced: 12 days ago
JSON representation

A manager for factory_bot to simplify creating nested factories.

Awesome Lists containing this project

README

        

# factory_manager [![Build Status](https://github.com/tristandunn/factory_manager/workflows/CI/badge.svg)](https://github.com/tristandunn/factory_manager/actions?query=workflow%3ACI)

A factory manager of factory bots.

#### Why?

Creating a deeply nested set of records for seeding or testing can be difficult.
factory_manager creates a DSL based on available [factory_bot][] factories,
allowing deeply nested records to be created easily.

## Examples

### Single-use

Provide a block to `build` or `create` to generate the factories within the
block.

Create a forum, with a single category, a first post for the category, post with
a sequence generated title, an administrative user, and one-hundred approved
posts by the administrator. Then create a featured category with a single post.

```ruby
result = FactoryManager.create do |locals|
forum do
category(name: "News") do
post(title: "First!")
post(title: generate(:title))

locals.administrator = user(:admin)

post(100, :approved, user: locals.administrator)
end

featured_category do
post
end
end
end

result.administrator
# => User(id: 1, name: "DHH", admin: true)
result.administrator.posts.count
# => 100
result.administrator.forum.categories.first.posts.count
# => 102
```

View the factories for the example.

```ruby
FactoryBot.defined do
factory :forum do
name { "Ruby on Rails" }
end

factory :category do
association :forum

name { "Announcements" }

factory :featured_category do
featured { true }
end
end

factory :user do
association :forum

name { "DHH" }

trait :admin do
admin { true }
end
end

factory :post do
association :category
association :user

title { "How to install Ruby." }

trait :approved do
approved { true }
end
end

sequence(:title) { "Title ##{rand}" }
end
```

View the example with inline comments.

```ruby
# Starts a manager that will create records. Alternatively use
# +FactoryManager.build+ to build records.
result = FactoryManager.create do |locals|
# Creates a +Forum+ record using the default attributes from the factory.
forum do
# Creates a +Category+ record with the default attributes but overrides the
# name. The +category.forum+ association will automatically be set to the
# +Forum+ record created above.
category(name: "News") do
# Create a +Post+ record with a custom title, automatically setting the
# +post.category+ association to the news category created above.
post(title: "First!")

# Create a +Post+ record with a sequence generated title, also automatically
# setting the # +post.category+ association to the news category created above.
post(title: generate(:title))

# Create a +User+ record using the +:admin+ trait. The +user.forum+
# association will automatically be set to the +Forum+ created above but
# a category will not be assigned. The +locals.administrator+ assignment
# will result in the user being available on the +result+ object.
locals.administrator = user(:admin)

# Create one-hundred +Post+ records using the +:approved+ trait setting
# the +post.user+ association to the administrator user created above and
# the +post.category+ to the news category created above.
post(100, :approved, user: locals.administrator)

# Create a +Category+ using the +featured_category+ factory and it
# automatically knows the parent factory is a +category+ to correctly
# associate child records, such as the single post created in it.
featured_category do
post
end
end
end
end
```

### Multi-use

Provide a name and block to `register` to register a manager, allowing you to
provide the name to `build` and `create` to generate the factories within the
registered block multiple times. Think of it as a factory of factories.

```ruby
FactoryManager.register(:lumbergh) do |locals|
locals.user = user do
tps_report(2, :incomplete)
end
end

peter = FactoryManager.create(:lumbergh).user
samir = FactoryManager.create(:lumbergh).user

peter.id == samir.id
# => false
peter.tps_reports == samir.tps_reports
# => false
peter.tps_reports.count == samir.tps_reports.count
# => true
```

## License

factory_manager uses the MIT license. See LICENSE for more details.

[factory_bot]: https://github.com/thoughtbot/factory_bot