lambdaisland / lambdaisland/facai

Complex traits

Open
#1 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Clojure
Stars
48
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Problem statement

I would like to reference other traits and set field data conditionally within traits.

Background / Examples

In another fixture-replacement library factory_bot, traits are defined using Ruby blocks, which are basically anonymous functions/callbacks. This allows for a given trait to perform more complex logic than just column value substitution. Here are some examples.

A trait can reference another trait, allowing for deduplication:

factory :order do
  trait :completed do
    completed_at { 3.days.ago }
  end

  trait :refunded do
    completed
    refunded_at { 1.day.ago }
  end
end

A trait can set multiple attributes based on random data:

factory :order do
  trait :chaos do
    if rand(1) == 0
      status { :in_progress }
      completed_at { nil }
    else
      status { :complete }
      completed_at { 1.day.ago }
    end
  end
end

In factory_bot, they can also hold before/after handlers, but that's outside of the scope of this issue.

Potential solutions

Base idea is that trait definitions could take a function that returns a map instead of a map literal. Building on that are a number of other solutions:

  • Referencing other traits could be a "lazy reference", so it's not evaluated until the factory produces an instance. Not sure how to apply it without state.
  • There could be a helper function that accepts and returns a map (to be used as the return value of the trait function), but has overloads for referencing other traits or performing other actions.
  • The trait function itself could be a 1-parameter function that provides the factory map, allowing for threading changes to it directly (instead of relying on merging in values after). Along with helper functions, this could allow for referencing traits as well ((apply-trait factory-map ::trait-name)).

I'm willing and interested in helping build this functionality, if y'all are interested!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing facai’s current trait-definition API and factory-building path, then compare it with the factory_bot examples in the issue. Determine how trait references and conditional field maps should be represented, and define tests showing that referenced traits and conditional attributes work when a factory produces an instance.

Written by the indexing model from the issue text.

Assessment

Tech stack
clojure
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.