IHP Api Reference
Safe HaskellNone

IHP.ValidationSupport.ValidateIsUnique

Synopsis

Documentation

validateIsUnique :: forall field model savedModel fieldValue modelId savedModelId. (savedModel ~ NormalizeModel model, ?modelContext :: ModelContext, FromRow savedModel, KnownSymbol field, HasField field model fieldValue, HasField field savedModel fieldValue, KnownSymbol (GetTableName savedModel), ToField fieldValue, EqOrIsOperator fieldValue, HasField "meta" model MetaBag, SetField "meta" model MetaBag, HasField "id" savedModel savedModelId, HasField "id" model modelId, savedModelId ~ modelId, Eq modelId, GetModelByTableName (GetTableName savedModel) ~ savedModel, Table savedModel) => Proxy field -> model -> IO model Source #

Validates that e.g. an email (or another field) is unique across all users before inserting.

This validator reads the given field name (e.g. email) from the record, and runs a database query to check that there is no other record using the same field value (e.g. email value).

Example: Validate that an email is unique

action CreateUserAction = do
    let user = newRecord @User
    user
        |> fill @'["email"]
        |> validateIsUnique #email
        >>= ifValid \case
            Left user -> render NewView { .. }
            Right user -> do
                createRecord user
                redirectTo UsersAction

validateIsUniqueCaseInsensitive :: forall field model savedModel fieldValue modelId savedModelId. (savedModel ~ NormalizeModel model, ?modelContext :: ModelContext, FromRow savedModel, KnownSymbol field, HasField field model fieldValue, HasField field savedModel fieldValue, KnownSymbol (GetTableName savedModel), ToField fieldValue, EqOrIsOperator fieldValue, HasField "meta" model MetaBag, SetField "meta" model MetaBag, HasField "id" savedModel savedModelId, HasField "id" model modelId, savedModelId ~ modelId, Eq modelId, GetModelByTableName (GetTableName savedModel) ~ savedModel, Table savedModel) => Proxy field -> model -> IO model Source #

Case insensitive version of validateIsUnique.

Uses a comparison like LOWER(field) = LOWER(value) internally, so it's best to have an index for LOWER(field) in your Schema.sql

>>> CREATE UNIQUE INDEX users_email_index ON users ((LOWER(email)));

Example: Validate that an email is unique, ignoring case

action CreateUserAction = do
    let user = newRecord @User
    user
        |> fill @'["email"]
        |> validateIsUniqueCaseInsensitive #email
        >>= ifValid \case
            Left user -> render NewView { .. }
            Right user -> do
                createRecord user
                redirectTo UsersAction

withCustomErrorMessageIO :: forall field model savedModel fieldValue modelId savedModelId. (savedModel ~ NormalizeModel model, ?modelContext :: ModelContext, FromRow savedModel, KnownSymbol field, HasField field model fieldValue, HasField field savedModel fieldValue, KnownSymbol (GetTableName savedModel), ToField fieldValue, EqOrIsOperator fieldValue, HasField "meta" model MetaBag, SetField "meta" model MetaBag, HasField "id" savedModel savedModelId, HasField "id" model modelId, savedModelId ~ modelId, Eq modelId, GetModelByTableName (GetTableName savedModel) ~ savedModel) => Text -> (Proxy field -> model -> IO model) -> Proxy field -> model -> IO model Source #

Overrides the error message of a given IO validator function.

Example: Validate that an email is unique with a custom error message

action CreateUserAction = do
    let user = newRecord @User
    user
        |> fill @'["email"]
        |> withCustomErrorMessageIO "Email Has Already Been Used" validateIsUnique #email
        >>= ifValid \case
            Left user -> render NewView { .. }
            Right user -> do
                createRecord user
                redirectTo UsersAction