Posted by Piotr Solnica on October 24, 2017 under

We're happy to announce a new project that we've been working on - rom-factory. The project was originally started by Jānis Miezītis back in 2016, and then it was moved to rom-rb organization in March 2017. As you can probably guess, rom-factory is a data generator library, similar to FactoryBot (previously known as FactoryGirl) or Fabrication. It's built on top of rom-rb and has a sweet integration with Faker gem.

Let's see how it looks like.

Factories

In rom-factory you can define as many factories as you want, we do not store them under one singleton object. After you got rom container set up, you can easily configure a factory:

MyFactory = ROM :: Factory . configure do | c | c . rom = your_rom_container end AnotherFactory = ROM :: Factory . configure do | c | c . rom = your_rom_container end

After setting up a factory, you can start defining your builders:

MyFactory . define ( :user ) do | f | f . name "Jane" f . email "jane@doe.org" end

You can ask for an in-memory struct, in which case a primary key value will be auto-generated:

MyFactory . structs [ :user ] # #<ROM::Struct::User id=1 name="Jane" email="jane@doe.org"

...or you can ask for a struct which will be persisted in your database:

MyFactory [ :user ] # #<ROM::Struct::User id=1 name="Jane" email="jane@doe.org"

Dynamic values with sequences, re-using other values and faker

Having static values is often not enough, which is why rom-factory has a couple of neat features which allow you to define dynamic values. The first one is sequencing:

MyFactory . define ( :user ) do | f | f . sequence ( :email ) { | n | "user- #{ n } @rom-rb.org" } end

You can also re-use values from other attributes:

MyFactory . define ( :user ) do | f | f . name "Jane" f . email { | name | " #{ name } @rom-rb.org" } end

We also added support for faker, which makes defining builders more concise:

MyFactory . define ( :user ) do | f | f . name { fake ( :name ) } f . email { fake ( :internet , :email ) } f . age { fake ( :number , :between , 10 , 100 ) } end

Associations

Currently has_many , has_one and belongs_to are supported. Here are a couple examples:

MyFactory . define ( :user ) do | f | f . name { fake ( :name ) } f . email { fake ( :internet , :email ) } # this will use :group builder to create a group for a user f . association ( :group ) # this will create 2 posts for a user f . association ( :posts , count: 2 ) end

Extending existing builders

You can define a builder by extending another one, for example you may have a user and an admin, which sets admin attribute to true :

MyFactory . define ( :user ) do | f | f . name { fake ( :name ) } f . email { fake ( :internet , :email ) } f . age { fake ( :number , :between , 10 , 100 ) } f . admin false end MyFactory . define ( admin: :user ) do | f | f . admin true end

Status & Roadmap

This is still in beta phase, current release is 0.5.0. We're planning to turn this into a pure data generator which doesn't assume any specific persistence backend (currently it uses and requires rom-core). On top of this, we want to add support for persistence backends. Once this is done, we'll have 1.0.0 ready.

For now, give it a try and tell us what you think. If you have any questions or problems, reach out on our discussion forum.

Useful links: