Data generation framework for Elixir.
In testing, sometimes it's useful to create records in the form of maps. Blacksmith makes it easy.
First, install Blacksmith:
In your mix.exs file, add the blacksmith dependency:
defdepsdo[{:blacksmith,"~> 0.1"}]endYou will also have to add :blacksmith to your application list:
defapplicationdo[applications: applications(Mix.env)]enddefpapplications(:test),do: applications(:all)++[:blacksmith]defpapplications(_all),do: [:logger]Next, tell Blacksmith how to save one record, or many records:
defmoduleBlacksmith.Configdodefsave(model)doMyRepo|>save(model)enddefsave_all(list_of_models)doMyRepo|>save_all(list_of_models)endendNext, perhaps in test_helper for convenience or somewhere in lib for speed, register each of your new models with Forge. Use Faker for fake values, and sequences to maintain unique values:
defmoduleForgedouseBlacksmithregister:user,name: Faker.Name.first_name,email: Sequence.next(:email,&"test#{&1}@example.com"),description: Faker.Lorem.sentence,roles: [],always_the_same: "string"# this will create a user with roles set to [:admin]register:admin,[prototype: :user],roles: ["admin"]endNow you can create a user, generating all of the default values:
user=Forge.useror a saved user, with the name attribute overridden, and a new attribute of favorite_language:
user=Forge.saved_username: "Will Override",favorite_language: "Elixir"or a list of 5 users
user=Forge.user_list5or a saved list of 5 admins
admin=Forge.saved_admin_listrepo,5Create a list using a few common data elements:
Forge.havingsurvey_id: some_survey.id,author: Forge.userdoquestion=Forge.question# will share the same survey id and user from aboveendNext release: allow nesting of having blocks.
Blacksmith can be used easily with a database persistence library such as Ecto.
defmoduleUserdouseEcto.Modelschema"users"dofield:name,:stringfield:email,:stringendendThe @save_one_function and @save_all_function attributes are used to delegate to your persistence layer. We delegate to Blacksmith.Config defined below. You'll also notice that we directly create a struct in register :user, that's because Ecto works with models built on structs instead of plain maps.
defmoduleForgedouseBlacksmith@save_one_function&Blacksmith.Config.save/1@save_all_function&Blacksmith.Config.save_all/1register:user,%User{name: "John Henry",email: Sequence.next(:email,&"jh#{&1}@example.com")}endBlacksmith.Config defines the callback functions that delegate to the Ecto repository for persistence.
defmoduleBlacksmith.Configdodefsave(map)doMyRepo.insert(map)enddefsave_all(list)doEnum.map(list,&MyRepo.insert/1)endendForge.saved_user will generate a User model that have been inserted in the database backed by MyRepo.