feat: Add validation constraints and tests for CustomField and CustomFieldValue

This commit is contained in:
Moritz 2025-11-13 18:37:58 +01:00
parent 8400e727a7
commit e9290b7156
4 changed files with 523 additions and 9 deletions

View file

@ -15,17 +15,18 @@ defmodule Mv.Membership.CustomField do
- `required` - If true, all members must have this custom field (future feature)
## Supported Value Types
- `:string` - Text data (unlimited length)
- `:string` - Text data (max 10,000 characters)
- `:integer` - Numeric data (64-bit integers)
- `:boolean` - True/false flags
- `:date` - Date values (no time component)
- `:email` - Validated email addresses
- `:email` - Validated email addresses (max 254 characters)
## Relationships
- `has_many :custom_field_values` - All custom field values of this type
## Constraints
- Name must be unique across all custom fields
- Name maximum length: 100 characters
- Cannot delete a custom field that has existing custom field values (RESTRICT)
## Examples
@ -60,14 +61,26 @@ defmodule Mv.Membership.CustomField do
attributes do
uuid_primary_key :id
attribute :name, :string, allow_nil?: false, public?: true
attribute :name, :string,
allow_nil?: false,
public?: true,
constraints: [
max_length: 100,
trim?: true
]
attribute :value_type, :atom,
constraints: [one_of: [:string, :integer, :boolean, :date, :email]],
allow_nil?: false,
description: "Defines the datatype `CustomFieldValue.value` is interpreted as"
attribute :description, :string, allow_nil?: true, public?: true
attribute :description, :string,
allow_nil?: true,
public?: true,
constraints: [
max_length: 500,
trim?: true
]
attribute :immutable, :boolean,
default: false,

View file

@ -30,6 +30,11 @@ defmodule Mv.Membership.CustomFieldValue do
## Constraints
- Each member can have only one custom field value per custom field (unique composite index)
- Custom field values are deleted when the associated member is deleted (CASCADE)
- String values maximum length: 10,000 characters
- Email values maximum length: 254 characters (RFC 5321)
## Future Features
- Type-matching validation (value type must match custom field's value_type) - to be implemented
"""
use Ash.Resource,
domain: Mv.Membership,
@ -56,11 +61,25 @@ defmodule Mv.Membership.CustomFieldValue do
constraints: [
storage: :type_and_value,
types: [
boolean: [type: :boolean],
date: [type: :date],
integer: [type: :integer],
string: [type: :string],
email: [type: Mv.Membership.Email]
boolean: [
type: :boolean
],
date: [
type: :date
],
integer: [
type: :integer
],
string: [
type: :string,
constraints: [
max_length: 10_000,
trim?: true
]
],
email: [
type: Mv.Membership.Email
]
]
]
end