This is the use case (to understand why I need the info) I’m working on how to validate forms in “dead views” (sometimes Liveview is overkill if 99% of stuff can be cached in a CDN). It is a combination of using HTMX to call Phoenix to do a validation when something is changed (nothing strange here) and I just replace the content that comes back from Phoenix. But it would be nice to not have to do a trip to the server just to check wether a field is not empty when it is required or if min length is 5. So I build a small javascript library to do some basic client side validations (like checking if a field is required, if it matches a regex etc). And then I only need to fall back to the server for validation if a field contains a validation that is impossible client-side (like checking if an email is not already in the database). The javascript library checks for any attribute that starts with “validation-” so all I need to do is add an HTML-attribute in the phoenix code. Right now I do this manually but I want a way to automatically do a lookup on which validations are done in a changeset for a field so it can be added automatically (so I don’t need to remember to change both in changeset and in any forms everything a validation is added, changed or removed).
Enough background, can I, using elixir code or macros get a list of the schema types and which functions are run in validation. So with a schema and changeset like this:
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "listings" do
field :title, :string
field :price, :integer
timestamps(type: :utc_datetime)
end
@doc false
def changeset(listing, attrs) do
listing
|> cast(attrs, [:title, :price])
|> validate_required([:title, :price])
|> validate_length(:title, min: 15)
end
I wanna be able to call Marketplace.Listings.Listing.get_validations() and get something like this:
%{name: :validate_required, fields: [:title, :price], params: %{}},
%{name: :validate_length, fields: [:title], params: %{min: 5}}
]
And Marketplace.Listings.Listing.get_types()
[
{:title, :string},
{:price, :integer}
]
I feel like it should be possible with macros (but way over my head) since it is all known at compile time.
Any idea on how I can do this?