### Clone Repository and Install Dependencies Source: https://github.com/beam-community/ex_machina/blob/main/README.md Provides instructions for cloning the ExMachina repository and installing its dependencies using Mix. This is a standard setup procedure for contributing to the project. ```bash git clone https://github.com/beam-community/ex_machina.git cd ex_machina mix deps.get ``` -------------------------------- ### Main Factory Module Setup Source: https://github.com/beam-community/ex_machina/blob/main/README.md Example of setting up a main factory module that includes other factory modules, useful for organizing factories. ```elixir # test/support/factory.ex defmodule MyApp.Factory do use ExMachina.Ecto, repo: MyApp.Repo use MyApp.ArticleFactory end ``` -------------------------------- ### Start ExMachina Application in Test Helper Source: https://github.com/beam-community/ex_machina/blob/main/README.md Ensure the ExMachina application is started before ExUnit in your `test/test_helper.exs` file. ```elixir {:ok, _} = Application.ensure_all_started(:ex_machina) ``` -------------------------------- ### Flexible Factories with Pipes Source: https://github.com/beam-community/ex_machina/blob/main/README.md Illustrates using Elixir pipes with ExMachina factories. This example shows how to apply custom functions like `make_admin` and `with_article` to modify and insert data. ```elixir def make_admin(user) do %{user | admin: true} end def with_article(user) do insert(:article, user: user) user end build(:user) |> make_admin |> insert |> with_article ``` -------------------------------- ### Test Usage with Phoenix and ExMachina.Ecto Source: https://github.com/beam-community/ex_machina/blob/main/README.md Shows an example of using ExMachina factories within a Phoenix test case, including inserting records and making requests. ```elixir # Example of use in Phoenix with a factory that uses ExMachina.Ecto defmodule MyApp.MyModuleTest do use MyApp.ConnCase # If using Phoenix, import this inside the using block in MyApp.ConnCase import MyApp.Factory test "shows comments for an article" do conn = conn() article = insert(:article) comment = insert(:comment, article: article) conn = get conn, article_path(conn, :show, article.id) assert html_response(conn, 200) =~ article.title assert html_response(conn, 200) =~ comment.body end end ``` -------------------------------- ### Phoenix Controller Test with ExMachina Source: https://context7.com/beam-community/ex_machina/llms.txt Demonstrates testing GET and POST requests for articles using ExMachina to insert data and generate parameters. Ensure your Phoenix application and ExMachina are set up correctly. ```elixir defmodule MyAppWeb.ArticleControllerTest do use MyAppWeb.ConnCase import MyApp.Factory describe "GET /articles/:id" do test "renders article with comments", %{conn: conn} do article = insert(:article, title: "Hello ExMachina") _comments = insert_list(3, :comment, article: article) conn = get(conn, Routes.article_path(conn, :show, article.id)) assert html_response(conn, 200) =~ "Hello ExMachina" end end describe "POST /articles" do test "creates an article with valid params", %{conn: conn} do params = string_params_for(:article, title: "New Article") conn = post(conn, Routes.article_path(conn, :create), article: params) assert redirected_to(conn) =~ "/articles/" end end end ``` -------------------------------- ### Build, Transform, and Insert with Elixir Pipes Source: https://context7.com/beam-community/ex_machina/llms.txt Chain factory operations like building, transforming, and inserting records using Elixir's pipe operator for concise test setup. Ensure necessary imports are present. ```elixir import MyApp.Factory def make_admin(user), do: %{user | admin: true} def with_article(user) do insert(:article, author: user) user end # Build → transform → insert → attach article in one pipeline user = build(:user) |> make_admin() |> insert() |> with_article() # Pattern for posts with associated comments post = insert(:post) |> insert_pair_comments() # custom helper that calls insert_pair(:comment, post: post) ``` -------------------------------- ### Reset Sequence Counters Source: https://context7.com/beam-community/ex_machina/llms.txt Use `ExMachina.Sequence.reset/0` to reset all sequence counters, or `reset/1` to reset specific named sequences. This is useful in setup blocks for tests. ```elixir # Reset all sequences (useful in a setup block) setup do ExMachina.Sequence.reset() :ok end # Reset a single sequence by name ExMachina.Sequence.reset(:email) # Reset multiple sequences at once ExMachina.Sequence.reset([:email, :role, "username"]) ``` -------------------------------- ### Pass Options to Repo.insert! Source: https://github.com/beam-community/ex_machina/blob/main/README.md Demonstrates using `ExMachina.Ecto.insert/3` to pass options to `Repo.insert!/2`. This is useful for multi-tenancy or retrieving database-generated values. ```elixir # return values from the database insert(:user, [name: "Jane"], returning: true) # use a different prefix insert(:user, [name: "Jane"], prefix: "other_tenant") ``` -------------------------------- ### Insert a Record into the Database with insert/2 Source: https://context7.com/beam-community/ex_machina/llms.txt Use `insert/2` to build and persist a factory record using `Repo.insert!/2`. Associations built with `build/2` are automatically inserted. Attributes can be overridden, and options can be passed to `Repo.insert!/2`. ```elixir import MyApp.Factory user = insert(:user) article = insert(:article, title: "ExMachina Is Great") user = insert(:user, [name: "Alice"], prefix: "tenant_a") user = insert(:user, [name: "Alice"], returning: true) build(:user) |> make_admin() |> insert() ``` -------------------------------- ### Run Project Tests Source: https://github.com/beam-community/ex_machina/blob/main/README.md Command to run the test suite for the ExMachina project using Mix. This is a crucial step after making changes to ensure the project's integrity. ```bash mix test ``` -------------------------------- ### Configure Phoenix Factory Path Source: https://github.com/beam-community/ex_machina/blob/main/README.md Shows how to configure `mix.exs` to include a custom directory for factories when using ExMachina with Phoenix. This allows factories to be organized outside the default `test/support` directory. ```elixir # Add the folder to the end of the list. In this case we're adding `test/factories`. defp elixirc_paths(:test), do: ["lib", "test/support", "test/factories"] ``` -------------------------------- ### Define a Factory Module with ExMachina.Ecto Source: https://context7.com/beam-community/ex_machina/llms.txt Define factory modules using `use ExMachina.Ecto, repo: MyApp.Repo`. Each factory is a zero-arity function named `_factory`. Use `sequence` for unique values and `build` for associations. ```elixir defmodule MyApp.Factory do use ExMachina.Ecto, repo: MyApp.Repo def user_factory do %MyApp.User{ name: "Jane Smith", email: sequence(:email, &"email-#{&1}@example.com"), role: sequence(:role, ["admin", "user", "moderator"]), admin: false } end def article_factory do title = sequence(:title, &"Article Title #{&1}") %MyApp.Article{ title: title, slug: MyApp.Article.title_to_slug(title), tags: fn article -> if String.contains?(article.title, "Elixir"), do: ["elixir"], else: [] end, author: build(:user) } end def comment_factory do %MyApp.Comment{ body: "Great post!", article: build(:article) } end def featured_article_factory do struct!(article_factory(), %{featured: true}) end end ``` -------------------------------- ### Equivalent Code for Immediate Evaluation Source: https://github.com/beam-community/ex_machina/blob/main/README.md Illustrates the equivalent code when a factory call is evaluated immediately. ```elixir user = build(:user) insert_pair(:account, user: user) # same user for both accounts ``` -------------------------------- ### Splitting Factories Across Files Source: https://context7.com/beam-community/ex_machina/llms.txt Organize large test suites by splitting factories into focused sub-modules and composing them into a single entry point. Ensure the factories directory is compiled in the test environment. ```elixir # test/factories/article_factory.ex defmodule MyApp.ArticleFactory do defmacro __using__(_opts) do quote location: :keep do def article_factory do %MyApp.Article{title: "Default Article", body: "Lorem ipsum"} end end end end # test/factories/post_factory.ex defmodule MyApp.PostFactory do defmacro __using__(_opts) do quote location: :keep do def post_factory do %MyApp.Post{body: "Default body"} end def with_comments(%MyApp.Post{} = post) do insert_pair(:comment, post: post) post end end end end # test/support/factory.ex — single entry point defmodule MyApp.Factory do use ExMachina.Ecto, repo: MyApp.Repo use MyApp.ArticleFactory use MyApp.PostFactory end # mix.exs — compile the factories directory in test env defp elixirc_paths(:test), do: ["lib", "test/factories", "test/support"] ``` -------------------------------- ### Insert Pair with Immediate Evaluation Source: https://github.com/beam-community/ex_machina/blob/main/README.md Demonstrates immediate evaluation of a factory call within insert_pair. ```elixir insert_pair(:account, user: build(:user)) ``` -------------------------------- ### Custom Strategies with ExMachina.Strategy Source: https://context7.com/beam-community/ex_machina/llms.txt Define custom persistence or transformation strategies, such as JSON encoding, by implementing ExMachina.Strategy. The `handle_` callback processes the record. ```elixir # Define the strategy defmodule MyApp.JsonEncodeStrategy do use ExMachina.Strategy, function_name: :json_encode # Called as handle_(record, opts) def handle_json_encode(record, _opts) do Jason.encode!(record) end # Optional: with per-call options as third arg def handle_json_encode(record, _opts, encoding_opts) do Jason.encode!(record, encoding_opts) end end # Use the strategy in your factory defmodule MyApp.Factory do use ExMachina use MyApp.JsonEncodeStrategy def user_factory do %MyApp.User{name: "John", email: "john@example.com"} end end # Generates: json_encode/1, json_encode/2, json_encode_pair/2, json_encode_list/3 MyApp.Factory.json_encode(:user) # => "{\"name\":\"John\",\"email\":\"john@example.com\"}" MyApp.Factory.json_encode_list(3, :user) # => ["{...}", "{...}", "{...}"] ``` -------------------------------- ### Build String-Keyed Map for Controller Tests (Ecto) Source: https://context7.com/beam-community/ex_machina/llms.txt Use `string_params_for/2` to generate a map with string keys, ideal for simulating Phoenix controller parameters. It functions similarly to `params_for/2` but uses string keys. ```elixir import MyApp.Factory params = string_params_for(:user, name: "Bob") # => %{"name" => "Bob", "email" => "email-0@example.com", "role" => "admin", "admin" => false} # Use directly in a Phoenix controller test conn = post(conn, Routes.user_path(conn, :create), %{"user" => params}) assert json_response(conn, 201)["name"] == "Bob" ``` -------------------------------- ### Build Plain Map for Changeset/Controller Tests (Ecto) Source: https://context7.com/beam-community/ex_machina/llms.txt Use `params_for/2` to generate a plain map with atom keys, suitable for Ecto changeset tests. It omits Ecto metadata, primary keys, and nil values, and does not include `belongs_to` foreign keys. ```elixir import MyApp.Factory params = params_for(:user, name: "Alice") # => %{name: "Alice", email: "email-0@example.com", role: "admin", admin: false} # Note: no :id, no :__meta__, no nil-valued fields # Use in a changeset test changeset = MyApp.User.changeset(%MyApp.User{}, params) assert changeset.valid? ``` -------------------------------- ### Add ExMachina Dependency for Testing Source: https://github.com/beam-community/ex_machina/blob/main/README.md Add ExMachina as a development dependency in your `mix.exs` file. It will only be compiled in the test environment. ```elixir def deps do [ {:ex_machina, "~> 2.8.0", only: :test}, ] end ``` -------------------------------- ### Define Post and Video Factories Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines factories for Post and Video structs, including a `with_comments` function for each. This demonstrates how to handle associations or related data within factories. ```elixir defmodule MyApp.PostFactory do defmacro __using__(_opts) do quote location: :keep do def post_factory do %MyApp.Post{ body: "Example body" } end def with_comments(%MyApp.Post{} = post) do insert_pair(:comment, post: post) post end end end end ``` ```elixir defmodule MyApp.VideoFactory do defmacro __using__(_opts) do quote location: :keep do def video_factory do %MyApp.Video{ url: "example_url" } end def with_comments(%MyApp.Video{} = video) do insert_pair(:comment, video: video) video end end end end ``` -------------------------------- ### Insert Multiple Records into the Database with insert_pair/2 and insert_list/3 Source: https://context7.com/beam-community/ex_machina/llms.txt Use `insert_pair/2` to insert two records or `insert_list/3` to insert multiple records into the database. Associations can be passed to link records. ```elixir import MyApp.Factory article = insert(:article) [c1, c2] = insert_pair(:comment, article: article) ``` -------------------------------- ### Configure Compilation Paths for Non-Phoenix Projects Source: https://github.com/beam-community/ex_machina/blob/main/README.md For non-Phoenix projects, add `test/support` to your `elixirc_paths` in `mix.exs` for the test environment to ensure factory modules are compiled. ```elixir def project do [ app: ..., # Add this if it's not already in your project definition. elixirc_paths: elixirc_paths(Mix.env) ] end # This makes sure your factory and any other modules in test/support are compiled # when in the test environment. defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] ``` -------------------------------- ### Insert Records with ExMachina.Ecto Source: https://github.com/beam-community/ex_machina/blob/main/README.md Use `insert`, `insert_pair`, and `insert_list` to create and persist records using ExMachina.Ecto. Associated records are inserted as well. ```elixir # `insert*` returns an inserted comment. Only works with ExMachina.Ecto # Associated records defined on the factory are inserted as well. insert(:comment, attrs) insert_pair(:comment, attrs) insert_list(3, :comment, attrs) ``` -------------------------------- ### Define Basic Article Factory Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines a basic factory for creating Article structs. This factory can be included in other factory files to promote modularity. ```elixir defmodule MyApp.ArticleFactory do defmacro __using__(_opts) do quote location: :keep do def article_factory do %MyApp.Article{ title: "My awesome article!", body: "Still working on it!" } end end end end ``` -------------------------------- ### Add ExMachina to mix.exs Source: https://context7.com/beam-community/ex_machina/llms.txt Add ExMachina as a test-only dependency in your mix.exs file. For non-Phoenix projects, ensure the test/support directory is compiled in the :test environment. ```elixir def deps do [ {:ex_machina, "~> 2.8.0", only: :test} ] end defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] ``` -------------------------------- ### Factory Definition with Sequence Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines a user factory that uses a sequence for the email attribute. ```elixir def user_factory do %{name: "Gandalf", email: sequence(:email, &"gandalf#{&1}@istari.com")} end ``` -------------------------------- ### Configure Mix Compilation Paths Source: https://github.com/beam-community/ex_machina/blob/main/README.md Modifies the `mix.exs` file to include a custom directory for factory compilation. This ensures that factories defined outside the standard `test/support` directory are recognized. ```elixir # ./mix.exs ... defp elixirc_paths(:test), do: ["lib", "test/factories", "test/support"] ... ``` -------------------------------- ### Define Ecto Factory with ExMachina Source: https://github.com/beam-community/ex_machina/blob/main/README.md Use `ExMachina.Ecto` to define factories for Ecto schemas, specifying the repository. ```elixir defmodule MyApp.Factory do # with Ecto use ExMachina.Ecto, repo: MyApp.Repo # without Ecto use ExMachina def user_factory do %MyApp.User{ name: "Jane Smith", email: sequence(:email, &"email-{#&1}@example.com"), role: sequence(:role, ["admin", "user", "other"]), } end def article_factory do title = sequence(:title, &"Use ExMachina! (Part {#&1})") # derived attribute slug = MyApp.Article.title_to_slug(title) %MyApp.Article{ title: title, slug: slug, # another way to build derived attributes tags: fn article -> if String.contains?(article.title, "Silly") do ["silly"] else [] end end, # associations are inserted when you call `insert` author: build(:user) } end # derived factory def featured_article_factory do struct!( article_factory(), %{featured: true} ) end def comment_factory do %MyApp.Comment{ text: "It's great!", article: build(:article), } end end ``` -------------------------------- ### Build an Unsaved Record with build/2 Source: https://context7.com/beam-community/ex_machina/llms.txt Use `build/2` to construct a factory struct in memory without database interaction. Attributes can be overridden using a keyword list or a map. ```elixir import MyApp.Factory user = build(:user) admin = build(:user, name: "Bob", admin: true) article = build(:article, %{title: "Custom Title"}) ``` -------------------------------- ### Define Ecto Factory with Associations Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines an Ecto factory for an Article, using `build/2` for associations like `comments` and `author`. This is recommended to avoid performance issues and bugs by deferring the insertion of associated records. ```elixir def article_factory do %Article{ title: "Use ExMachina!", # associations are inserted when you call `insert` comments: [build(:comment)], author: build(:user), } end ``` -------------------------------- ### Non-Map Factory Definition and Usage Source: https://github.com/beam-community/ex_machina/blob/main/README.md Demonstrates defining and using a non-map factory. Note that non-map factories cannot be used with Ecto's insert. ```elixir # factory definition def room_number_factory(attrs) do %{floor: floor_number} = attrs sequence(:room_number, &"#{floor_number}0#{&1}") end # example usage build(:room_number, floor: 5) # => "500" build(:room_number, floor: 5) # => "501" ``` -------------------------------- ### Build Multiple Unsaved Records with build_pair/2 and build_list/3 Source: https://context7.com/beam-community/ex_machina/llms.txt Use `build_pair/2` to create exactly two unsaved records, or `build_list/3` to create a specified number of unsaved records. Attributes can be applied to all generated records. ```elixir import MyApp.Factory [user1, user2] = build_pair(:user) articles = build_list(5, :article, featured: true) IO.puts(length(articles)) ``` -------------------------------- ### Insert Pair with Delayed Evaluation Source: https://github.com/beam-community/ex_machina/blob/main/README.md Shows how to delay factory execution by passing it as an anonymous function to insert_pair. ```elixir insert_pair(:account, user: fn -> build(:user) end) ``` -------------------------------- ### Build Params with Foreign Keys Inserted (Ecto) Source: https://context7.com/beam-community/ex_machina/llms.txt Use `params_with_assocs/2` to generate a map that includes foreign key IDs for `belongs_to` associations after inserting them into the database. The string-keyed version is `string_params_with_assocs/2`. ```elixir import MyApp.Factory # Inserts an author and returns author_id in the map params = params_with_assocs(:article, title: "Hello World") # => %{title: "Hello World", slug: "hello-world", author_id: 42} # String-keyed version for controller tests str_params = string_params_with_assocs(:article) # => %{"title" => "...", "author_id" => 43} changeset = MyApp.Article.changeset(%MyApp.Article{}, params) assert changeset.valid? ``` -------------------------------- ### Custom Factory with Full Attribute Control Source: https://github.com/beam-community/ex_machina/blob/main/README.md Provides a custom factory that accepts attributes as an argument, requiring manual merging and lazy attribute evaluation. ```elixir def custom_article_factory(attrs) do title = Map.get(attrs, :title, "default title") article = %Article{ author: "John Doe", title: title } article |> merge_attributes(attrs) |> evaluate_lazy_attributes() end ``` -------------------------------- ### Generate String-Keyed Parameters for Phoenix Source: https://github.com/beam-community/ex_machina/blob/main/README.md Use `string_params_for` and `string_params_with_assocs` to generate maps with string keys, which is useful for Phoenix controller tests. These functions also handle associations. ```elixir # Use `string_params_for` to generate maps with string keys. This can be useful # for Phoenix controller tests. string_params_for(:comment, attrs) string_params_with_assocs(:comment, attrs) ``` -------------------------------- ### Factory with Parent Record Argument Source: https://github.com/beam-community/ex_machina/blob/main/README.md Illustrates a factory definition where the anonymous function accepts the parent record as an argument to influence attribute building. ```elixir def account_factory do %{user: fn account -> build(:user, vip: account.premium) end} end ``` -------------------------------- ### Define Custom JSON Encoding Strategy Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines a custom ExMachina strategy for JSON encoding using the Poison library. This strategy can be used with Ecto or standalone `build` functions. ```elixir defmodule MyApp.JsonEncodeStrategy do use ExMachina.Strategy, function_name: :json_encode def handle_json_encode(record, _opts) do Poison.encode!(record) end end defmodule MyApp.Factory do use ExMachina # Using this will add json_encode/2, json_encode_pair/2 and json_encode_list/3 use MyApp.JsonEncodeStrategy def user_factory do %User{name: "John"} end end # Will build and then return a JSON encoded version of the user. MyApp.Factory.json_encode(:user) ``` -------------------------------- ### Generate Parameters for Ecto Schemas Source: https://github.com/beam-community/ex_machina/blob/main/README.md Use `params_for` and `params_with_assocs` to generate plain maps for Ecto schemas. `params_with_assocs` also inserts belongs_to associations and sets foreign keys. ```elixir # `params_for` returns a plain map without any Ecto specific attributes. # This is only available when using `ExMachina.Ecto`. params_for(:comment, attrs) # `params_with_assocs` is the same as `params_for` but inserts all belongs_to # associations and sets the foreign keys. # This is only available when using `ExMachina.Ecto`. params_with_assocs(:comment, attrs) ``` -------------------------------- ### Build Unsaved Records with ExMachina Source: https://github.com/beam-community/ex_machina/blob/main/README.md Use `build`, `build_pair`, and `build_list` to create unsaved Elixir structs or Ecto schemas. Associated records defined in the factory are also built. ```elixir # `attrs` are automatically merged in for all build/insert functions. # `build*` returns an unsaved comment. # Associated records defined on the factory are built. attrs = %{body: "A comment!"} # attrs is optional. Also accepts a keyword list. build(:comment, attrs) build_pair(:comment, attrs) build_list(3, :comment, attrs) ``` -------------------------------- ### Derive Factory Name from Struct with name_from_struct Source: https://context7.com/beam-community/ex_machina/llms.txt Use `ExMachina.Strategy.name_from_struct/1` to dynamically derive a factory name from a struct's module name, useful for custom strategies requiring dynamic callbacks. ```elixir ExMachina.Strategy.name_from_struct(%MyApp.User{}) # => :user ExMachina.Strategy.name_from_struct(%MyApp.BlogPost{}) # => :blog_post ExMachina.Strategy.name_from_struct(%MyApp.Api.Token{})# => :token # Practical use: dynamic pre-encode callbacks defmodule MyApp.JsonEncodeStrategy do use ExMachina.Strategy, function_name: :json_encode def handle_json_encode(record, %{factory_module: factory}) do callback = :"before_encode_#{ExMachina.Strategy.name_from_struct(record)}" record = if function_exported?(factory, callback, 1), do: apply(factory, callback, [record]), else: record Jason.encode!(record) end end ``` -------------------------------- ### Factory with Full Attribute Control Source: https://context7.com/beam-community/ex_machina/llms.txt Define a factory function that accepts one argument to take full control of attribute merging and lazy evaluation. This allows for complex attribute definitions and overrides. ```elixir def article_factory(attrs) do title = Map.get(attrs, :title, "Default Title") slug = MyApp.Article.title_to_slug(title) %MyApp.Article{author: "John Doe", title: title, slug: slug} |> merge_attributes(attrs) # merge remaining overrides |> evaluate_lazy_attributes() # resolve any fn-valued fields end # Non-map factory (cannot be used with insert) def room_number_factory(attrs) do %{floor: floor} = attrs sequence(:room_number, &"#{floor}0{#&1}") end build(:room_number, floor: 3) # => "300" build(:room_number, floor: 3) # => "301" ``` -------------------------------- ### Generate Unique Sequential Values Source: https://context7.com/beam-community/ex_machina/llms.txt Use `sequence/1`, `sequence/2`, or `sequence/3` to generate unique values by incrementing a named counter. Supports string shorthands, custom formatter functions, cycling through lists, and `start_at` offsets. ```elixir import MyApp.Factory # String shorthand: appends incrementing integer sequence("username") # => "username0" sequence("username") # => "username1" # Custom formatter function sequence(:email, &"user-{#&1}@example.com") # => "user-0@example.com" sequence(:email, &"user-{#&1}@example.com") # => "user-1@example.com" # List (cycles through values) sequence(:role, ["admin", "user", "guest"]) # => "admin" sequence(:role, ["admin", "user", "guest"]) # => "user" sequence(:role, ["admin", "user", "guest"]) # => "guest" sequence(:role, ["admin", "user", "guest"]) # => "admin" (wraps around) # start_at option sequence(:invoice_no, &"INV-{#&1}", start_at: 1000) # => "INV-1000" sequence(:invoice_no, &"INV-{#&1}", start_at: 1000) # => "INV-1001" ``` -------------------------------- ### Factory Definition with Delayed Evaluation Source: https://github.com/beam-community/ex_machina/blob/main/README.md Defines a factory that delays the execution of another factory using an anonymous function. ```elixir def account_factory do %{user: fn -> build(:user) end} end ``` -------------------------------- ### Delayed / Lazy Attribute Evaluation Source: https://context7.com/beam-community/ex_machina/llms.txt Pass anonymous functions as attribute values to defer evaluation, ensuring each built record receives a freshly computed value. This prevents sharing a single result across multiple records. ```elixir import MyApp.Factory # Without lazy evaluation — both accounts share the SAME user struct insert_pair(:account, user: build(:user)) # With lazy evaluation — each account gets its OWN user insert_pair(:account, user: fn -> build(:user) end) # Access the parent record inside a lazy attribute def account_factory do %MyApp.Account{ # vip field is derived from the parent account's premium flag user: fn account -> build(:user, vip: account.premium) end, premium: false } end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.