Repodb.Changeset
repodb · API reference
type change =
| StringChange of string
| IntChange of int
| FloatChange of float
| BoolChange of bool
| NullChangePhoenix/Ecto-style changesets for casting, validation, and constraints.
A changeset tracks proposed changes to a record, validation errors, and the intended action. Use it at boundaries where untrusted input becomes trusted domain data: HTTP forms, JSON payloads, CLI arguments, imports, and tests.
Basic flow:
let create_user params =
User.empty
|> Changeset.for_insert
|> Changeset.cast params ~fields:[ User.email; User.name ]
|> Changeset.validate_required [ User.email; User.name ]
|> Changeset.validate_format User.email ~pattern:"^[^@]+@[^@]+$"
|> Changeset.unique_constraint User.email ~name:"users_email_key"cast only accepts named fields and ignores unknown parameters. Validation functions add structured Error.validation_error values without raising. Use apply_action or Repo.validate_changeset to turn a valid changeset into data or a validation error result.
Constraint helpers such as unique_constraint, foreign_key_constraint, and check_constraint document expected database errors. Repos can use that metadata to convert backend constraint failures into user-facing validation errors instead of opaque SQL errors.
Changes currently store scalar form values as strings plus a few primitive variants. For rich domain parsing, parse values before calling put_change or write a model-specific changeset function that converts the boundary representation into a typed record.
module StringMap : sig ... endmodule StringSet : sig ... endtype 'a t = {
data : 'a;
changes : change StringMap.t;
errors : Error.validation_error list;
valid : bool;
action : action option;
constraints : constraint_def list;
}and action =
| Insert
| Update
| Deleteand constraint_def = {
constraint_name : string;
constraint_field : string;
constraint_type : constraint_type;
}and constraint_type =
| UniqueConstraint
| ForeignKeyConstraint of {
table : string;
column : string;
}
| CheckConstraint of stringval create : 'a -> 'a tval change : 'a -> 'a tval for_insert : 'a -> 'a tval for_update : 'a -> 'a tval cast :
(StringSet.elt * string) list ->
fields:('a, 'b) Field.t list ->
'c t ->
'c tval cast_assoc :
(StringSet.elt * change) list ->
fields:('a, 'b) Field.t list ->
'c t ->
'c tval put_change : ('a, 'b) Field.t -> string -> 'c t -> 'c tval delete_change : ('a, 'b) Field.t -> 'c t -> 'c tval get_change : 'a t -> ('b, 'c) Field.t -> string optionval get_field : 'a t -> ('a, 'b) Field.t -> 'bval add_error :
field:string ->
message:string ->
validation:string ->
'a t ->
'a tval validate_required : ('a, 'b) Field.t list -> 'c t -> 'c tval validate_format : ('a, 'b) Field.t -> pattern:string -> 'c t -> 'c tval validate_length :
('a, 'b) Field.t ->
?min:int ->
?max:int ->
?is:int ->
'c t ->
'c tval validate_inclusion : ('a, 'b) Field.t -> values:string list -> 'c t -> 'c tval validate_exclusion : ('a, 'b) Field.t -> values:string list -> 'c t -> 'c tval validate_number :
('a, 'b) Field.t ->
?greater_than:int ->
?less_than:int ->
?greater_than_or_equal:int ->
?less_than_or_equal:int ->
'c t ->
'c tval validate_acceptance : ('a, 'b) Field.t -> 'c t -> 'c tval validate_confirmation :
('a, 'b) Field.t ->
confirmation_field:('c, 'd) Field.t ->
'e t ->
'e tval validate_change :
('a, 'b) Field.t ->
(string -> (unit, string) result) ->
'c t ->
'c tval validate : 'a -> ('a -> 'b) -> 'bval unique_constraint : ('a, 'b) Field.t -> 'c t -> 'c tval foreign_key_constraint :
('a, 'b) Field.t ->
references:(string * string) ->
'c t ->
'c tval check_constraint :
name:string ->
('a, 'b) Field.t ->
expression:string ->
'c t ->
'c tval is_valid : 'a t -> boolval errors : 'a t -> Error.validation_error listval data : 'a t -> 'aval changes : 'a t -> (StringMap.key * change) listval changes_map : 'a t -> change StringMap.tval action : 'a t -> action optionval get_error : 'a t -> ('b, 'c) Field.t -> Error.validation_error optionval has_error : 'a t -> ('b, 'c) Field.t -> boolval traverse_errors : 'a t -> (string -> string -> unit) -> unitval error_messages : 'a t -> string listval apply_action : 'a t -> ('a, Error.validation_error list) resulttype 'a assoc_changeset = {
assoc_name : string;
assoc_changesets : 'a t list;
on_replace : [ `Raise | `Mark_as_invalid | `Delete | `Update ];
}val cast_assoc_one :
assoc_name:string ->
params:(string * 'a) list ->
cast_fn:('a -> 'b t) ->
'c t ->
'c tval cast_assoc_many :
assoc_name:string ->
params_list:'a list ->
cast_fn:('a -> 'b t) ->
'c t ->
'c tval put_assoc : assoc_name:StringMap.key -> json_string:string -> 'a t -> 'a tval cast_embed :
embed_name:string ->
params:(string * 'a) list ->
parse:('a -> ('b, string) result) ->
'c t ->
'c tval put_embed : embed_name:StringMap.key -> json_string:string -> 'a t -> 'a tval merge_errors : 'a t -> 'b t -> prefix:string -> 'a t