Skip to content

Conversation

@jameskentdev
Copy link
Owner

@jameskentdev jameskentdev commented Sep 20, 2025

Summary

As mentioned in woylie#596, the goal is to attempt to do this without introducing additional dependencies. I thought of 3 ways to do this, and I wasn't entirely sure which one to go with, so initially I tried them all.

  1. Introduce a custom Ecto.Type and just cast this inside the main changesets. However, I ran into an issue with a circular dependency between Flop.Combinator requiring this custom type, and this custom type also requiring Flop.Combinator for its changeset.
  2. Introduce an additional embedded schema, as a union of the two:
    embedded_schema do
      field :field, ExistingAtom
      field :op, Ecto.Enum, default: :==, values: @operators
      field :value, Any
    
      field :type, values: @combinator_types
      field :filters, __MODULE__
    end
    The problem with this is that it resulted in a quirky internal API I didn't like, e.g.:
    %Flop.FilterOrCombinator{
      field: nil,
      op: nil,
      value: nil,
      type: :and,
      filters: [
        %Flop.FilterOrCombinator{...},
        %Flop.FilterOrCombinator{...}
      ]
    }
  3. Sort of a lightweight approach at polymorphic_embed just focusing on our use-case, this is the one in this PR.

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.

2 participants