Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: autogenerate schema associations with factories #5

Open
wants to merge 27 commits into
base: main
Choose a base branch
from

Conversation

cylkdev
Copy link

@cylkdev cylkdev commented Aug 31, 2022

I'm proposing an implementation in this pr for auto generating an Ecto.Schema's association fields for factories. The factories are great for a source of truth however with complex relations the amount of calls made to create one increases. The goal is reduce the amount of code required to setup relations while being simple enough to define in one function call.

The use the association building feature you need to specify the app to load the factory modules. There are two options for configuring the behavior:

app: OTP app name
prefix: The factory modules prefix.

for eg. MyApp.Support.Factory.Accounts.User has the app name my_app and the prefix Factory for the module name.

To use the factory generation for associations you must set the relational option to a list of association fields as atoms or :all and the validate option must be true. Associations are derived from an Ecto.Schema's Reflection and is handled by the FactoryEx.Utils.Ecto.Schema.Reflection module. Ecto.Changeset.cast_assoc/3 is used when validating to cast the associated fields generated in the changeset.params.

A map is created for Ecto one associations from the specified params. If the schema also exists in the schema factory and the relational key is set, the factory's build function is called and the specified params are merged on top of the result.

  iex> FactoryEx.build_params(FactoryEx.Support.Examples.Accounts.User, %{}, relational: [:role])
  %{
    birthday: ~D[2022-08-30],
    email: "abdiel1905@cummerata.name",
    gender: "female",
    location: "TN",
    name: "Aniya",
    role: %{code: "ROLE"}
  }

There are two conveniences when building the paramters for ecto many associations.

  1. Factory support when building associations parameters for a changeset/2 function
    using the default syntax. This allows you to apply many changes to many paramters.
  iex> FactoryEx.build_params(FactoryEx.Support.Examples.Accounts.User, %{labels: [%{}, %{label: "overwrite_second_label"}]}, relational: [:labels])
  %{
    birthday: ~D[2022-08-30],
    email: "terrell.pfeffer@steuber.net",
    gender: "female",
    labels: [%{label: "ut"}, %{label: "overwrite_second_label"}],
    location: "FL",
    name: "Rollin"
  }
  1. Tuple syntax of {count, params} for applying one set of changes to many paramters. This syntax only is expanded when the relational option is set for the key.
  iex> FactoryEx.build_params(FactoryEx.Support.Examples.Accounts.User, %{labels: {2, %{label: "same_label"}}}, relational: [:labels])
  %{
    birthday: ~D[2022-08-30],
    email: "federico2006@muller.org",
    gender: "female",
    labels: [%{label: "same_label"}, %{label: "same_label"}],
    location: "TN",
    name: "Berniece"
  }

The parameters are created before being converted to a struct or changeset.

Changelog

  • Added FactoryEx.AssociationBuilder and FactoryEx.FactoryStore for generating parameters
    for Ecto Associations with Factory.
  • FactoryEx.SchemaCounter.start is now automatically when the factory_ex application starts.
  • validate when false deep converts params to ecto schema structs.
  • Moved previous schemas from test/support to test/support/schema
  • Created factories for schemas under test/support/factory
  • Created ecto migrations
  • Added ecto repo config for testing

@cylkdev cylkdev changed the title feat: factory gen for schema associations feat: autogenerate schema associations with factories Aug 31, 2022
@MikaAK
Copy link
Contributor

MikaAK commented Sep 1, 2022

Just a note I'm currently working with @cylkdev to refactor this a bit before review

@MikaAK MikaAK marked this pull request as draft September 1, 2022 04:51
@cylkdev cylkdev force-pushed the feat/ecto-association-builder branch from 8d3ba29 to c5c3797 Compare September 4, 2022 20:02
@cylkdev cylkdev force-pushed the feat/ecto-association-builder branch from c5c3797 to 1c3e75c Compare October 16, 2022 21:42
@cylkdev cylkdev force-pushed the feat/ecto-association-builder branch 2 times, most recently from 04b0fa7 to 789e171 Compare November 24, 2022 20:30
@cylkdev cylkdev force-pushed the feat/ecto-association-builder branch from 41fd08b to 2f8cd35 Compare March 31, 2023 15:40
config/config.exs Outdated Show resolved Hide resolved
lib/factory_ex.ex Outdated Show resolved Hide resolved
@cylkdev cylkdev force-pushed the feat/ecto-association-builder branch from e6dffdf to 4b8b38c Compare October 30, 2023 23:09
@cylkdev cylkdev marked this pull request as ready for review October 30, 2023 23:12
@cylkdev cylkdev requested a review from MikaAK October 31, 2023 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants