Retrieve the value associated with the given key of an Object.
The result is empty if the key is not present or the value cannot
be converted to the desired type.
This accessor is appropriate if the key and value must be present
in an object for it to be valid. If the key and value are
optional, use .:? instead.
Set whether to use record constructors or normal constructors.
If you are getting partial-fields warnings you want to remove, set this to
False. If you want to use record syntax, set this to True.
Build a WAI Application that dispatches starting at a nested route
fragment a (rather than the whole Route site), given a
YesodRunnerEnv for the parent site and the parent route's ParentArgs.
Handles cleanPath redirects and a terminal 404 just like toWaiAppYre.
Looks up the CSRF token from the request headers or POST parameters. If the value doesn't match the token stored in the session,
this function throws a PermissionDenied error.
For details, see the "AJAX CSRF protection" section of Yesod.Core.Handler.
For details, see the "AJAX CSRF protection" section of Yesod.Core.Handler.
Make sure to set the setCookiePath to the root path of your application, otherwise you'll generate a new CSRF token for every path of your app. If your app is run from from e.g. www.example.com/app1, use app1. The vast majority of sites will just use /.
Default implementation of messageLoggerSource. Checks if the
message should be logged using the provided function, and if so,
formats using formatLogMessage. You can use defaultShouldLogIO
as the provided function.
Default formatting for log messages. When you use
the template haskell logging functions for to log with information
about the source location, that information will be appended to
the end of the log. When you use the non-TH logging functions,
like logDebugN, this function does not include source
information. This currently works by checking to see if the
package name is the string "<unknown>". This is a hack,
but it removes some of the visual clutter from non-TH logs.
Helps defend against CSRF attacks by setting the SameSite attribute on
session cookies to Lax. With the Lax setting, the cookie will be sent with same-site
requests, and with cross-site top-level navigations.
This option is liable to change in future versions of Yesod as the spec evolves.
View more information here.
Apply a Strict-Transport-Security header with the specified timeout to
all responses so that browsers will rewrite all http links to https
until the timeout expires. For security, the max-age of the STS header
should always equal or exceed the client sessions timeout. This defends
against SSL-stripping man-in-the-middle attacks. It is only effective if
a secure connection has already been made; Strict-Transport-Security
headers are ignored over HTTP.
Defends against session hijacking by setting the secure bit on session
cookies so that browsers will not transmit them over http. With this
setting on, it follows that the server will regard requests made over
http as sessionless, because the session cookie will not be included in
the request. Use this as part of a total security measure which also
includes disabling HTTP traffic to the site or issuing redirects from
HTTP urls, and composing sslOnlyMiddleware with the site's
yesodMiddleware.
Helps defend against CSRF attacks by setting the SameSite attribute on
session cookies to Strict. With the Strict setting, the cookie will only be
sent with same-site requests.
This option is liable to change in future versions of Yesod as the spec evolves.
View more information here.
Generate a random number uniformly distributed in the full range
of Int.
Note: Before 1.6.20, this generates pseudo-random number in an
unspecified range. The range size may not be a power of 2. Since
1.6.20, this uses a secure entropy source and generates in the full
range of Int.
Construct a YesodRunnerEnv for a site, initializing its logger, session
backend, and other runtime state. This is the environment threaded through
dispatch; toWaiAppPlain and friends build one for you, but it is exposed so
callers can construct and reuse a runner environment directly.
Convert the given argument into a WAI application, executable with any WAI
handler. This function will provide no middlewares; if you want commonly
used middlewares, please use toWaiApp.
Convert the given argument into a WAI application, executable with any WAI
handler. This function will provide no middlewares; if you want commonly
used middlewares, please use toWaiApp.
This function allows you to create an Application that only responds
to a subset of the site routes. This is really only useful for writing
tests, but it does allow you to write tests that only depend on a subset
of the handlers instead of all handlers.
A convenience method to run an application using the Warp webserver on the
specified port. Automatically calls toWaiApp. Provides a default set of
middlewares. This set may change at any point without a breaking version
number. Currently, it includes:
Logging
GZIP compression
Automatic HEAD method handling
Request method override with the _method query string parameter
Accept header override with the _accept query string parameter
If you need more fine-grained control of middlewares, please use toWaiApp
directly.
Runs your application using default middlewares (i.e., via toWaiApp). It
reads port information from the PORT environment variable, as used by tools
such as Keter and the FP Complete School of Haskell.
Note that the exact behavior of this function may be modified slightly over
time to work correctly with external tools, without a change to the type
signature.
Allows Unicode characters by encoding to UTF-8.
Some modurn browser parse UTF-8 characters with out encoding setting.
But, for example IE9 can't parse UTF-8 characters.
This function use
RFC 6266(RFC 5987)
Use a per-request cache to avoid performing the same action multiple times.
Values are stored by their type, the result of typeOf from Typeable.
Therefore, you should use different newtype wrappers at each cache site.
For example, yesod-auth uses an un-exported newtype, CachedMaybeAuth and exports functions that utilize it such as maybeAuth.
This means that another module can create its own newtype wrapper to cache the same type from a different action without any cache conflicts.
a per-request cache. just like cached.
cached can only cache a single value per type.
cachedBy stores multiple values per type by usage of a ByteString key
cached is ideal to cache an action that has only one value of a type, such as the session's current user
cachedBy is required if the action has parameters and can return multiple values per type.
You can turn those parameters into a ByteString cache key.
For example, caching a lookup of a Link by a token where multiple token lookups might be performed.
Checks that a valid CSRF token is present in either the request headers or POST parameters.
If the value doesn't match the token stored in the session, this function throws a PermissionDenied error.
Takes a POST parameter name to lookup a CSRF token. If the value doesn't match the token stored in the session,
this function throws a PermissionDenied error.
Returns a function that runs HandlerFor actions inside IO.
Sometimes you want to run an inner HandlerFor action outside
the control flow of an HTTP request (on the outer HandlerFor
action). For example, you may want to spawn a new thread:
getFooR :: Handler RepHtml
getFooR = do
runInnerHandler <- handlerToIO
liftIO $ forkIO $ runInnerHandler $ do
Code here runs inside HandlerFor but on a new thread.This is the inner HandlerFor.
...
Code here runs inside the request's control flow.This is the outer HandlerFor.
...
Another use case for this function is creating a stream of
server-sent events using HandlerFor actions (see
yesod-eventsource).
Most of the environment from the outer HandlerFor is preserved
on the inner HandlerFor, however:
The request body is cleared (otherwise it would be very
difficult to prevent huge memory leaks).
Changes to the response made inside the inner HandlerFor are
ignored (e.g., session variables, cookies, response headers).
This allows the inner HandlerFor to outlive the outer
HandlerFor (e.g., on the forkIO example above, a response
may be sent to the client without killing the new thread).
Get the list of supported languages supplied by the user.
Languages are determined based on the following (in descending order
of preference):
The _LANG get parameter.
The _LANG user session variable.
The _LANG cookie.
Accept-Language HTTP header.
Yesod will seek the first language from the returned list matched with languages supporting by your application. This language will be used to render i18n templates.
If a matching language is not found the default language will be used.
This is handled by parseWaiRequest (not exposed).
NOTE: Before version 1.6.19.0, this function prioritized the session
variable above all other sources.
Same as provideRep, but instead of determining the content type from the
type of the value itself, you provide the content type separately. This can
be a convenience instead of creating newtype wrappers for uncommonly used
content types.
provideRepType "application/x-special-format" "This is the content"
Redirect to the given route.
HTTP status code 303 for HTTP 1.1 clients and 302 for HTTP 1.0
This is the appropriate choice for a get-following-post
technique, which should be the usual use case.
If you want direct control of the final status code, or need a different
status code, please use redirectWith.
This is not technically a redirect; instead, it returns an HTML page with a
POST form, and some Javascript to automatically submit the form. This can be
useful when you need to post a plain link somewhere that needs to cause
changes on the server.
Note that, for ease of use, the underlying monad is a HandlerFor. This
implies that you can run any HandlerFor action. However, since a streaming
response occurs after the response headers have already been sent, some
actions make no sense here. For example: short-circuit responses, setting
headers, changing status codes, etc.
Send a raw response without conduit. This is used for cases such as
WebSockets. Requires WAI 3.0 or later, and a web server which supports raw
responses (e.g., Warp).
Send a Response. Please note: this function is rarely
necessary, and will disregard any changes to response headers and session
that you have already specified. This function short-circuits. It should be
considered only for very specific needs. If you are not sure if you need it,
you don't.
Takes a SetCookie and overrides its value with a CSRF token, then sets the cookie.
Make sure to set the setCookiePath to the root path of your application, otherwise you'll generate a new CSRF token for every path of your app. If your app is run from from e.g. www.example.com/app1, use app1. The vast majority of sites will just use /.
Check the if-none-match header and, if it matches the given value, return
a 304 not modified response. Otherwise, set the etag header to the given
value.
Note that it is the responsibility of the caller to ensure that the provided
value is a valid etag value, no sanity checking is performed by this
function.
The session is handled by the clientsession package: it sets an encrypted
and hashed cookie on the client. This ensures that all data is secure and
not tampered with.
Check the if-none-match header and, if it matches the given value, return
a 304 not modified response. Otherwise, set the etag header to the given
value.
A weak etag is only expected to be semantically identical to the prior content,
but doesn't have to be byte-for-byte identical. Therefore it can be useful for
dynamically generated content that may be difficult to perform bytewise hashing
upon.
Note that it is the responsibility of the caller to ensure that the provided
value is a valid etag value, no sanity checking is performed by this
function.
Generate a YesodSubDispatchNested instance for a nested route within a
subsite, for hand-written split-route modules (see the subsite-splitting
recipe in docs/split-route-compilation.md).
Takes the resources as [ResourceTreeString] — exactly the form the
parseRoutes quasi-quoter produces — and parses them to Type internally
via parseResourceTypes, so the caller never touches the partial
parseType/dropBracket. A malformed type fails the splice with an
attributed error instead.
Contexts and type variables in the name of the datatype are parsed.
For example, a datatype App a with typeclass constraint MyClass a can be written as "(MyClass a) => App a".
Sometimes, you will want to declare your routes in one file and define
your handlers elsewhere. For example, this is the only way to break up a
monolithic file into smaller parts. Use this function, paired with
mkYesodDispatch, to do just that.
Generate both YesodSubDispatch and YesodSubDispatchNested instances
for a parameterized subsite. This is the subsite equivalent of using
mkYesod for top-level sites.
Usage:
mkYesodSubDispatchInstance "(MyClass a) => MySub a" resourcesMySub
The generated instances quantify over the master site and constrain it
only through the subsite's own class. For a parameterized subsite this
normally means the subsite's class carries a subsite -> master functional
dependency (so master is determined) and the using module enables
UndecidableInstances (the instance contexts mention type-family
applications and non-variable arguments), along with FlexibleContexts,
FlexibleInstances, MultiParamTypeClasses and TypeFamilies. The nested
route datatype must also declare exactly as many type parameters as the
subsite has type arguments (see the arity note below).
Like mkYesodSubDispatchInstance, but takes a RouteOpts so a subsite can
control nested-route generation — most usefully setNestedRouteFallthrough
(which mkYesodSubDispatchInstance leaves at its default of False). The
flag is threaded into both the yesodSubDispatch body (so the subsite's own
top-level parent clauses fall through to later siblings on an inner miss) and
the generated YesodSubDispatchNested fragment instances.
Similar to mkYesod, except contexts and type variables are not parsed.
Instead, they are explicitly provided.
You can write (MyClass a) => App a with mkYesodWith [["MyClass","a"]] "App" ["a"] ....
Parse the request body to a data type as a JSON value. The
data type must support conversion from JSON via FromJSON.
If you want the raw JSON value, just ask for a ResultValue.
The MIME type must indicate JSON content. Requiring a JSON
content-type helps secure your site against CSRF attacks
(browsers will perform POST requests for form and text/plain
content-types without doing a CORS check, and those content-types
can easily contain valid JSON).
Note that this function will consume the request body. As such, calling it
twice will result in a parse error on the second call, since the request
body will no longer be available.
Represents TypedContent as a String, rendering at most a specified number of
bytes of the content, and annotating it with the remaining length. Returns Nothing
if the content type indicates the content is binary data.
setDescription is not idempotent; we recommend setDescriptionIdemp instead Multiple calls to setDescription will insert multiple meta tags in the page head. If you want an idempotent function, use setDescriptionIdemp - but if you do, you may need to change your layout to include pageDescription.
Add description meta tag to the head of the page
Google does not use the description tag as a ranking signal, but the
contents of this tag will likely affect your click-through rate since it
shows up in search results.
The average length of the description shown in Google's search results is
about 160 characters on desktop, and about 130 characters on mobile, at time
of writing.
setDescriptionI is not idempotent; we recommend setDescriptionIdempI instead Multiple calls to setDescriptionI will insert multiple meta tags in the page head. If you want an idempotent function, use setDescriptionIdempI - but if you do, you may need to change your layout to include pageDescription.
Add translated description meta tag to the head of the page
Google does not use the description tag as a ranking signal, but the
contents of this tag will likely affect your click-through rate since it
shows up in search results.
The average length of the description shown in Google's search results is
about 160 characters on desktop, and about 130 characters on mobile, at time
of writing.
Unlike setDescription, this version is *idempotent* - calling it multiple
times will result in only a single description meta tag in the head.
A quasi-quoter to parse a string into a list of Resources. Checks for
overlapping routes, failing if present; use parseRoutesNoCheck to skip the
checking. See documentation site for details on syntax.
Determine whether or not to generate the resourcesApp value.
Disabling this can be useful if you are creating the routes ::
[ResourceTree String] elsewhere in your module, and referring to it
here. The resourcesApp can become very large in large applications,
and duplicating it can result in signifiacntly higher compile times.
If you set this with routeName, then the code generation will
generate code for the routeName to be imported in the main dispatch
class. This allows you to generate code in separate modules.
Example:
First, you would put your route definitions into their own file.
module App.Routes.Resources where
import Yesod.Core
appResources :: [ResourceTree String]
appResources = [parseRoutes|
/ HomeR GET
/nest NestR:
/ NestIndexR GET POST
/#Int NestShowR GET POST
|]
We have defined a nested route called NestR here. A nested route is
created with the : after the route name.
Then, in a module for the route specifically, we can generate the route
datatype and instances for later hooking in to the main instance.
When True, a nested route that fails to match falls through to the
enclosing dispatch rather than throwing notFound. When False, a
non-matching nested route throws notFound.
If True, generate nested-discovery code (separate subroute datatypes and
RenderRouteNested dispatch instances) for a parameterized/ site instead
of the backwards-compatible inline output. The subroute datatypes then carry
the parent site's type variables so that the ParentSite / ParentArgs
associated types stay well-scoped.
Because the generated nested instances are parameterized over the site's
type variables, the splice emits instance heads with non-variable arguments;
a module using this typically needs FlexibleContexts, FlexibleInstances,
MultiParamTypeClasses, TypeFamilies and, for a parameterized subsite
whose master is determined by the subsite (a subsite -> master
functional dependency on the user's class), UndecidableInstances.
Monomorphic sites always use nested discovery regardless of this flag; see
discoveryMode.
A type that can be converted from JSON, with the possibility of
failure.
In many cases, you can get the compiler to generate parsing code
for you (see below). To begin, let's cover writing an instance by
hand.
There are various reasons a conversion could fail. For example, an
Object could be missing a required key, an Array could be of
the wrong size, or a value could be of an incompatible type.
The basic ways to signal a failed conversion are as follows:
fail yields a custom error message: it is the recommended way of
reporting a failure;
empty (or mzero) is uninformative:
use it when the error is meant to be caught by some (<|>);
typeMismatch can be used to report a failure when the encountered value
is not of the expected JSON type; unexpected is an appropriate alternative
when more than one type may be expected, or to keep the expected type
implicit.
-- Allow ourselves to write Text literals.
{-# LANGUAGE OverloadedStrings #-}
data Coord = Coord { x :: Double, y :: Double }
instance FromJSON Coord where
parseJSON (Object v) = Coord
<$> v .: "x"
<*> v .: "y"
-- We do not expect a non-Object value here.
-- We could use empty to fail, but typeMismatch
-- gives a much more informative error message.
parseJSON invalid =
prependFailure "parsing Coord failed, "
(typeMismatch "Object" invalid)
For this common case of only being concerned with a single
type of JSON value, the functions withObject, withScientific, etc.
are provided. Their use is to be preferred when possible, since
they are more terse. Using withObject, we can rewrite the above instance
(assuming the same language extension and data type) as:
Instead of manually writing your FromJSON instance, there are two options
to do it automatically:
Data.Aeson.TH provides Template Haskell functions which will derive an
instance at compile time. The generated instance is optimized for your type
so it will probably be more efficient than the following option.
The compiler can provide a default generic implementation for
parseJSON.
To use the second, simply add a deriving Generic clause to your
datatype and declare a FromJSON instance for your datatype without giving
a definition for parseJSON.
For example, the previous example can be simplified to just:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Coord = Coord { x :: Double, y :: Double } deriving Generic
instance FromJSON Coord
The default implementation will be equivalent to
parseJSON = genericParseJSONdefaultOptions; if you need different
options, you can customize the generic decoding by defining:
FromJSONValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONIntSetDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONVoidDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONIntegerDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
This instance includes a bounds check to prevent maliciously
large inputs to fill up the memory of the target system. You can
newtype Scientific and provide your own instance using
withScientific if you want to allow larger inputs.
FromJSONNaturalDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONAllDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONAnyDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONVersionDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONCTimeDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONInt16Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONInt32Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONInt64Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONInt8Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONBoolDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONCharDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONDoubleDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONFloatDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONIntDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONOrderingDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONWordDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONWord16Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONWord32Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONWord64Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONWord8Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONURIDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONPersistValueDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
FromJSONDayOfWeekDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONDiffTimeDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
This instance includes a bounds check to prevent maliciously
large inputs to fill up the memory of the target system. You can
newtype Scientific and provide your own instance using
withScientific if you want to allow larger inputs.
This instance includes a bounds check to prevent maliciously
large inputs to fill up the memory of the target system. You can
newtype Scientific and provide your own instance using
withScientific if you want to allow larger inputs.
The first space may instead be a T, and the second space is
optional. The Z represents UTC. The Z may be replaced with a
time zone offset of the form +0000 or -08:00, where the first
two digits are hours, the : is optional and the second two digits
(also optional) are minutes.
FromJSONUUIDDefined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
FromJSONTextareaDefined in yesod-form-1.7.11 · Yesod.Form.Fields
FromJSON ()Defined in aeson-2.3.2.0 · Data.Aeson.Types.FromJSON
This instance includes a bounds check to prevent maliciously
large inputs to fill up the memory of the target system. You can
newtype Scientific and provide your own instance using
withScientific if you want to allow larger inputs.
EqValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.Internal
DataValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.Internal
OrdValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.Internal
The ordering is total, consistent with Eq instance.
However, nothing else about the ordering is specified,
and it may change from environment to environment and version to version
of either this package or its dependencies
(hashable and
unordered-containers).
ReadValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.Internal
ShowValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.Internal
Since version 1.5.6.0 version object values are printed in lexicographic key order
Constructs a singleton KeyMap. For calling functions that
demand an Object for constructing objects. To be used in
conjunction with mconcat. Prefer to use object where possible.
Instances in general must specify toJSON and should (but don't need
to) specify toEncoding.
An example type and instance:
-- Allow ourselves to write Text literals.
{-# LANGUAGE OverloadedStrings #-}
data Coord = Coord { x :: Double, y :: Double }
instance ToJSON Coord where
toJSON (Coord x y) = object ["x" .= x, "y" .= y]
toEncoding (Coord x y) = pairs ("x" .= x <> "y" .= y)
Instead of manually writing your ToJSON instance, there are two options
to do it automatically:
Data.Aeson.TH provides Template Haskell functions which will derive an
instance at compile time. The generated instance is optimized for your type
so it will probably be more efficient than the following option.
The compiler can provide a default generic implementation for
toJSON.
To use the second, simply add a deriving Generic clause to your
datatype and declare a ToJSON instance. If you require nothing other than
defaultOptions, it is sufficient to write (and this is the only
alternative where the default toJSON implementation is sufficient):
Previous versions of this library only had the toJSON method. Adding
toEncoding had two reasons:
toEncoding is more efficient for the common case that the output of
toJSON is directly serialized to a ByteString.
Further, expressing either method in terms of the other would be
non-optimal.
The choice of defaults allows a smooth transition for existing users:
Existing instances that do not define toEncoding still
compile and have the correct semantics. This is ensured by making
the default implementation of toEncoding use toJSON. This produces
correct results, but since it performs an intermediate conversion to a
Value, it will be less efficient than directly emitting an Encoding.
(this also means that specifying nothing more than
instance ToJSON Coord would be sufficient as a generically decoding
instance, but there probably exists no good reason to not specify
toEncoding in new instances.)
The default implementation of this method creates an
intermediate Value using toJSON. This provides
source-level compatibility for people upgrading from older
versions of this library, but obviously offers no performance
advantage.
To benefit from direct encoding, you must provide an
implementation for this method. The easiest way to do so is by
having your types implement Generic using the DeriveGeneric
extension, and then have GHC generate a method body as follows.
Defines when it is acceptable to omit a field of this type from a record.
Used by (.?=) operator, and Generics and TH deriving
with omitNothingFields = True.
Instances120ToJSON, …
ToJSONKeyDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONDotNetTimeDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONValueDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONIntSetDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONVoidDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONIntegerDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONNaturalDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONAllDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONAnyDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONVersionDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONCTimeDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONInt16Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONInt32Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONInt64Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONInt8Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONBoolDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONCharDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONDoubleDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONFloatDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONIntDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONOrderingDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONWordDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONWord16Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONWord32Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONWord64Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONWord8Defined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONURIDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONPersistValueDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
ToJSONScientificDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONTextDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONTextDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
ToJSONShortTextDefined in aeson-2.3.2.0 · Data.Aeson.Types.ToJSON
Monads in which IO computations may be embedded.
Any monad built by applying a sequence of monad transformers to the
IO monad will be an instance of this class.
Instances should satisfy the following laws, which state that liftIO
is a transformer of monads:
Lift a computation from the IO monad.
This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations
(i.e. IO is the base monad for the stack).
Example
import Control.Monad.Trans.State -- from the "transformers" library
printState :: Show s => StateT s IO ()
printState = do
state <- get
liftIO $ print state
Had we omitted liftIO, we would have ended up with this error:
• Couldn't match type ‘IO’ with ‘StateT s IO’
Expected type: StateT s IO ()
Actual type: IO ()
The important part here is the mismatch between StateT s IO () and IO ().
Luckily, we know of a function that takes an IO a and returns an (m a): liftIO,
enabling us to run the program and see the expected results:
A Monad which allows for safe resource allocation. In theory, any monad
transformer stack which includes a ResourceT can be an instance of
MonadResource.
Note: runResourceT has a requirement for a MonadUnliftIO m monad,
which allows control operations to be lifted. A MonadResource does not
have this requirement. This means that transformers such as ContT can be
an instance of MonadResource. However, the ContT wrapper will need to be
unwrapped before calling runResourceT.
Opaque options type for mkMessage
This is used to pass options to the mkMessage function.
The options are not exposed directly to the user, but can be set using
the 'set*' functions, and the default can be made using defMakeMessageOpts.
the RenderMessage is used to provide translations for a message types
The master argument exists so that it is possible to provide more
than one set of translations for a message type. This is useful
if a library provides a default set of translations, but the user
of the library wants to provide a different set of translations.
The class of monad transformers.
For any monad m, the result t m should also be a monad,
and lift should be a monad transformation from m to t m,
i.e. it should satisfy the following laws:
Since 0.6.0.0 and for GHC 8.6 and later, the requirement that t m
be a Monad is enforced by the implication constraint
forall m. Monad m => Monad (t m) enabled by the
QuantifiedConstraints extension.
While MonadIO allows an IO action to be lifted into another
monad, this class captures the opposite concept: allowing you to
capture the monadic context. Note that, in order to meet the laws
given below, the intuition is that a monad must have no monadic
state, but may have monadic context. This essentially limits
MonadUnliftIO to ReaderT and IdentityT transformers on top of
IO.
Laws. For any function run provided by withRunInIO, it must meet the
monad transformer laws as reformulated for MonadUnliftIO:
run . return = return
run (m >>= f) = run m >>= run . f
Instances of MonadUnliftIO must also satisfy the following laws:
Identity law
withRunInIO (\run -> run m) = m
Inverse law
withRunInIO (\_ -> m) = liftIO m
As an example of an invalid instance, a naive implementation of
MonadUnliftIO (StateT s m) might be
Convenience function for capturing the monadic context and running an IO
action with a runner function. The runner function is used to run a monadic
action m in IO.
Instances9MonadUnliftIO, …
MonadUnliftIOIODefined in unliftio-core-0.2.1.0 · Control.Monad.IO.Unlift
Note that, since WAI 3.0, this type is structured in continuation passing
style to allow for proper safe resource handling. This was handled in the
past via other means (e.g., ResourceT). As a demonstration:
A type-safe, concise method of creating breadcrumbs for pages. For each
resource, you declare the title of the page and the parent resource (if
present).
Build a WAI Application for site, indexed by a url type that can
be rendered to a route of site (via RedirectUrl).
Note that dispatch is purely path-based: the hand-written instances below
discard the url value (urlToDispatch _ = yesodDispatch) and route on the
request's pathInfo. The url argument exists only to select the instance
and to carry the RedirectUrl constraint — it is not consulted at runtime.
This is equivalent to YesodDispatch but allows us to vary on the
url type, which lets us demand additional constraints in test
contexts.
This instance is the pattern upon which UrlToDispatch instances are
generated for subsite fragments. Given the constraints, we are able to
call toWaiAppYreNested at the route type with the correct arguments.
This allows us to create an application for a fragment of a site.
This class enables you to dispatch on a route fragment without needing
to know how to dispatch on the entire route structure. This allows you
to break up route generation into multiple files.
The implementation uses the full WAI Request to determine if the
remaining path (after the parent route) matches any child routes.
Returns Nothing if no child routes match (for fallthrough to other
routes), or Just a continuation that handles the request.
The parent depth (number of path pieces consumed by the parent route)
is statically known during Template Haskell generation and baked into
the generated instance.
YesodDispatchNested is a more flexible class than YesodDispatch,
and this instance is the proof. Given a Route site we can dispatch
on it as normal, so this code path works. This allows us to create
generalized helpers and reuse them, ensuring that nested and top-level
dispatch remain equivalent. This instance therefore always returns
Just — committing to yesodDispatch, which itself terminates in
a 404 on a miss — rather than the Nothing that the class haddock
describes for fragment instances. The only intended caller is the
terminal authority toWaiAppYreNested, where that 404 is exactly the
right answer; do not rely on this instance to signal fallthrough.
Like YesodDispatchNested, but for subsites. This class enables
class-based delegation for nested routes within subsites, allowing
module separation and symmetry with YesodDispatchNested.
When a YesodSubDispatchNested instance exists for a nested route type,
mkYesodSubDispatch will delegate to it instead of inlining the dispatch.
Use mkYesodSubDispatchInstance to generate both YesodSubDispatch and
YesodSubDispatchNested instances in one splice.
Dispatches a request for a nested route fragment within a subsite.
Similar to yesodDispatchNested, but works with YesodSubRunnerEnv
instead of YesodRunnerEnv, making it suitable for subsites.
The master type is universally quantified since it's not determined
by the nested route type.
Reconstruct a full parent route from a nested route fragment and its
ParentArgs (the dynamic pieces consumed by the ancestor parents). This is
what lets a fragment dispatched in its own module be rendered back into the
master site's Route (ParentSite a).
An absolute URL to the root of the application. Do not include
trailing slash.
Default value: guessApproot. If you know your application root
statically, it will be more efficient and more reliable to instead use
ApprootStatic or ApprootMaster. If you do not need full absolute
URLs, you can use ApprootRelative instead.
Note: Prior to yesod-core 1.5, the default value was ApprootRelative.
allows the user to specify how exceptions are cought.
by default all async exceptions are thrown and synchronous
exceptions render a 500 page.
To catch all exceptions (even async) to render a 500 page,
set this to catchSyncOrAsync. Beware
this may have negative effects with functions like timeout.
Override the rendering function for a particular URL and query string
parameters. One use case for this is to offload static hosting to a
different domain name to avoid sending cookies.
For backward compatibility default implementation is in terms of
urlRenderOverride, probably ineffective
Determines whether the current request is a write request. By default,
this assumes you are following RESTful principles, and determines this
from request method. In particular, all except the following request
methods are considered write: GET HEAD OPTIONS TRACE.
This function is used to determine if a request is authorized; see
isAuthorized.
A function used to clean up path segments. It returns Right with a
clean path or Left with a new set of pieces the user should be
redirected to. The default implementation enforces:
No double slashes
There is no trailing slash.
Note that versions of Yesod prior to 0.7 used a different set of rules
involing trailing slashes.
Builds an absolute URL by concatenating the application root with the
pieces of a path and a query string, if any.
Note that the pieces of the path have been previously cleaned up by cleanPath.
This function is used to store some static content to be served as an
external file. The most common case of this is stashing CSS and
JavaScript content in an external file; the Yesod.Widget module uses
this feature.
The return value is Nothing if no storing was performed; this is the
default implementation. A JustLeft gives the absolute URL of the
file, whereas a JustRight gives the type-safe URL. The former is
necessary when you are serving the content outside the context of a
Yesod application, such as via memcached.
Maximum allowed length of the request body, in bytes. This is similar
to maximumContentLength, but the result lives in IO. This allows
you to dynamically change the maximum file size based on some external
source like a database or an IORef.
Note that a common technique (endorsed by the scaffolding) is to create
a Logger value and place it in your foundation datatype, and have this
method return that already created value. That way, you can use that
same Logger for printing messages during app initialization.
Same as jsAttributes but allows you to run arbitrary Handler code
This is useful if you need to add a randomised nonce value to the script
tag generated by widgetFile. If this function is overridden then
jsAttributes is ignored.
Create a session backend. Returning Nothing disables
sessions. If you'd like to change the way that the session
cookies are created, take a look at
customizeSessionCookies.
Default: Uses clientsession with a 2 hour timeout.
Default: When the request body is greater than 50kb, store in a temp
file. For chunked request bodies, store in a temp file. Otherwise, store
in memory.
How to allocate an InternalState for each request.
The default implementation is almost always what you want. However, if
you know that you are never taking advantage of the MonadResource
instance in your handler functions, setting this to a dummy
implementation can provide a small optimization. Only do this if you
really know what you're doing, otherwise you can turn safe code into a
runtime error!
Anything which can be converted into Content. Most of the time, you will
want to use the ContentBuilder constructor. An easier approach will be to use
a pre-defined toContent function, such as converting your data into a lazy
bytestring and then calling toContent on that.
Please note that the built-in instances for lazy data structures (String,
lazy ByteString, lazy Text and Html) will not automatically include
the content length for the ContentBuilder constructor.
How to determine the root of the application for constructing URLs.
Note that future versions of Yesod may add new constructors without bumping
the major version number. As a result, you should not pattern match on
Approot values.
A generic widget, allowing specification of both the subsite and master
site datatypes. While this is simply a WriterT, we define a newtype for
better error messages.
Note that, despite Builder's laziness, this is entirely forced
into memory by default in order to catch imprecise exceptions
before beginning to respond. If you are confident you don't have
imprecise exceptions, you may disable this by wrapping the
ToContent data in DontFullyEvaluate.
The requested resource was not found.
Examples of when this occurs include when an incorrect URL is used, or yesod-persistent's get404 doesn't find a value.
HTTP status: 404.
Indicates some sort of invalid or missing argument, like a missing query parameter or malformed JSON body.
Examples Yesod functions that send this include requireCheckJsonBody and Yesod.Auth.GoogleEmail2.
HTTP status: 400.
Parse a route fragment from a path. Like parseRoute, but produces
the fragment a directly rather than a complete Route; the parent is
responsible for constructing the full route from the result.
Render the fragment of the route. To form a complete route, you'll
need to mappend this with the result from the parent renderRoute
or renderRouteNested call.
YesodDispatchNested is a more flexible class than YesodDispatch,
and this instance is the proof. Given a Route site we can dispatch
on it as normal, so this code path works. This allows us to create
generalized helpers and reuse them, ensuring that nested and top-level
dispatch remain equivalent. This instance therefore always returns
Just — committing to yesodDispatch, which itself terminates in
a 404 on a miss — rather than the Nothing that the class haddock
describes for fragment instances. The only intended caller is the
terminal authority toWaiAppYreNested, where that 404 is exactly the
right answer; do not rely on this instance to signal fallthrough.
This datatype wraps up the ParentArgs for a route fragment with the
route fragment itself. A route fragment with its parent arguments can
be rendered and dispatched on.
This instance is the pattern upon which UrlToDispatch instances are
generated for subsite fragments. Given the constraints, we are able to
call toWaiAppYreNested at the route type with the correct arguments.
This allows us to create an application for a fragment of a site.
Contains options for customizing code generation for the router in
mkYesodData, including what type class instances will be derived for
the route datatype, whether to parameterize subroutes,
and whether or not to create the resources :: [ResourceTree String] value.
Use the setting functions on defaultOpts to set specific fields.
The type arguments of a route datatype, paired with the source Name each
was derived from. A monomorphic site like App has NoTyArgs; a
parameterized one like MySub subsite has SomeTyArgs.
Carrying the (non-)emptiness in the type — rather than as a bare list with a
separate null check — keeps "are there type args?" and "what are they?"
a single fact, so the populated branch hands you the NonEmpty directly.
Creates a group of radio buttons to answer the question given in the message. Radio buttons are used to allow differentiating between an empty response (Nothing) and a no response (Just False). Consider using the simpler checkBoxField if you don't need to make this distinction.
If this field is optional, the first radio button is labeled "<None>", the second "Yes" and the third "No".
If this field is required, the first radio button is labeled "Yes" and the second "No".
Creates an input with type="checkbox".
While the default boolField implements a radio button so you
can differentiate between an empty response (Nothing) and a no
response (Just False), this simpler checkbox field returns an empty
response as Just False.
Creates an input with type="email". Yesod will validate the email's correctness according to RFC5322 and canonicalize it by removing comments and whitespace (see Text.Email.Validate).
Creates an input with type="hidden"; you can use this to store information in a form that users shouldn't see (for example, Yesod stores CSRF tokens in a hidden field).
Creates an input with type="email" with the multiple attribute; browsers might implement this as taking a comma separated list of emails. Each email address is validated as described in emailField.
Selects a list of Entitys with the given Filter and SelectOpts. The (a -> msg) function is then used to derive the display value for an OptionList. Example usage:
Country
name Text
deriving Eq -- Must derive Eq
data CountryForm = CountryForm
{ country :: Entity Country
}
countryNameForm :: AForm Handler CountryForm
countryNameForm = CountryForm
<$> areq (selectField countries) "Which country do you live in?" Nothing
where
countries = optionsPersist [] [Asc CountryName] countryName
A helper function for constucting selectFields with optional option groups. You may want to use this when you define your custom selectFields or radioFields.
Creates an input with type="text", parsing the time from an [H]H:MM[:SS] format, with an optional AM or PM (if not given, AM is assumed for compatibility with the 24 hour clock system).
This function exists for backwards compatibility with the old implementation of timeField, which used to use type="text". Consider using timeField or timeFieldTypeTime for improved UX and validation from the browser.
Add the time package and import the Data.Time.LocalTime module to use this function.
Allows the user to place the option radio widget somewhere in
the template.
For example: If you want a table of radio options to select.
radioField is an example on how to use this function.
Same as areq but with your own message to be rendered in case the value
is not provided.
This is useful when you have several required fields on the page and you
want to differentiate between which fields were left blank. Otherwise the
user sees "Value is required" multiple times, which is ambiguous.
Since a Field cannot be a Functor, it is not obvious how to "reuse" a Field
on a newtype or otherwise equivalent type. This function allows you to convert
a Field m a to a Field m b assuming you provide a bidirectional
conversion between the two, through the first two functions.
A simple example:
import Data.Monoid
sumField :: (Functor m, Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m (Sum Int)
sumField = convertField Sum getSum intField
Another example, not using a newtype, but instead creating a Lazy Text field:
import qualified Data.Text.Lazy as TL
TextField :: (Functor m, Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m TL.Text
lazyTextField = convertField TL.fromStrict TL.toStrict textField
Similar to runFormPost, except it always ignores the currently available
environment. This is necessary in cases like a wizard UI, where a single
page will both receive and incoming form and produce a new, blank form. For
general usage, you can stick with runFormPost.
Creates a hidden field on the form that identifies it. This
identification is then used to distinguish between missing
and wrong form data when a single handler contains more than
one form.
For instance, if you have the following code on your handler:
Note that it's your responsibility to ensure that the
identification strings are unique (using the same one twice on a
single handler will not generate any errors). This allows you
to create a variable number of forms and still have them work
even if their number or order change between the HTML
generation and the form submission.
The raw parameter values the named field was run against in this
request, whether from a direct submission or a Post/Redirect/Get
replay (runFormPRG). Empty if no form containing the field has run
with a submission in this request (e.g. generateFormPost, or an
identifyForm-wrapped form that was not the one submitted).
This lets the view of a field rendering several inputs under one name
restore all of the user's raw input after a failed submission: the
Either Text a argument a view receives can only carry the first
submitted value. Only fields run through mreq/mopt (and the
applicative/widget helpers built on them) record their values here.
Converts a form field into monadic form. This field is optional, i.e.
if filled in, it returns 'Just a', if left empty, it returns Nothing.
Arguments are the same as for mreq (apart from type of default value).
Same as mreq but with your own message to be rendered in case the value
is not provided.
This is useful when you have several required fields on the page and you
want to differentiate between which fields were left blank. Otherwise the
user sees "Value is required" multiple times, which is ambiguous.
Render a form using Bootstrap v2-friendly shamlet syntax.
If you're using Bootstrap v3, then you should use the
functions from module Yesod.Form.Bootstrap3.
Render a form into a series of tr tags. Note that, in order to allow
you to add extra rows to the table, this function does not wrap up
the resulting HTML in a table tag; you must do that yourself.
Run a form for the Post/Redirect/Get pattern, so that invalid input
and its validation errors survive a redirect.
Use this in both the GET and POST handlers of a route, exactly as you
would runFormPost:
On a POST request this behaves exactly like runFormPost (including
CSRF protection). Additionally, on FormFailure the submitted
parameters are stashed in the user session so that your handler can
simply redirect back to the GET route instead of re-rendering. On
FormSuccess any previously stashed parameters for this route are
cleared. On FormMissing (another identifyForm-wrapped form on the
page was the one submitted) the stash is left untouched.
On a GET request, if stashed parameters exist for the current path,
they are removed from the session and the form is run against them:
the fields re-render with the user's input and validation errors, just
as a non-redirecting handler would have rendered them. A fresh CSRF
token is rendered into the form (the stashed token is discarded, and
no token check is performed on a replay). If nothing is stashed, this
behaves like generateFormPost (the result is FormMissing).
getRegisterR :: Handler Markup
getRegisterR = do
((_res, widget), enctype) <- runFormPRG personForm
defaultLayout
[whamlet|
<form method=post action=@{RegisterR} enctype=#{enctype}>
^{widget}
|]
postRegisterR :: Handler Markup
postRegisterR = do
((res, _widget), _enctype) <- runFormPRG personForm
case res of
FormSuccess person -> do
-- insert into the database, etc.
setMessage "Registered!"
redirect RegisterR
_ -> redirect RegisterR
Notes and caveats:
The stash is keyed by request path, so the GET and POST handlers must
share a route (the common Yesod pattern). Form pages on different
routes do not interfere with each other; two tabs on the same path
share one stash (the last failed submission wins).
Multiple forms on one page work when wrapped with identifyForm: on
replay, only the form that was actually submitted re-renders with
values and errors; the others return FormMissing and render blank.
(The stash is popped once per request and shared between calls via
the per-request cache, so every form in the handler sees it.)
Uploaded files are not stashed; file fields re-render empty after the
redirect.
The stashed parameters live in the user session. With the default
client-session backend the whole session must fit in a cookie
(roughly 4KB), so this is unsuitable for very large forms. If the
stash fails to decode, it is discarded and a blank form is generated.
If the application has no session backend, stashing is a no-op and
this degrades to runFormPost/generateFormPost semantics (input
will not survive the redirect).
If your POST handler re-renders on failure instead of redirecting, do
not use this function: the stash would be consumed by an unrelated
later GET of the same path.
On a replay the form may even produce FormSuccess (e.g. a checkM
validation whose outcome depends on external state); the result is
returned as-is. GET handlers normally use only the widget.
A HEAD request reads the stash without consuming it, so that
middleware such as autoHead does not eat the replay meant for the
subsequent GET.
This function is used to both initially render a form and to later extract
results from it. Note that, due to CSRF protection and a few other issues,
forms submitted via GET and POST are slightly different. As such, be sure to
call the relevant function based on how the form will be submitted, not
the current request method.
For example, a common case is displaying a form on a GET request and having
the form submit to a POST page. In such a case, both the GET and POST
handlers should use runFormPost.
Converts a form field into monadic form WForm. This field is optional,
i.e. if filled in, it returns 'Just a', if left empty, it returns
Nothing. Arguments are the same as for wreq (apart from type of default
value).
Same as wreq but with your own message to be rendered in case the value
is not provided.
This is useful when you have several required fields on the page and you
want to differentiate between which fields were left blank. Otherwise the
user sees "Value is required" multiple times, which is ambiguous.
A structure holding a list of options. Typically you can use a convenience function like mkOptionList or optionsPairs instead of creating this directly.
A newtype wrapper around a Text whose ToMarkup instance converts newlines to HTML <br> tags.
(When text is entered into a <textarea>, newline characters are used to separate lines.
If this text is then placed verbatim into HTML, the lines won't be separated, thus the need for replacing with <br> tags).
If you don't need this functionality, simply use unTextarea to access the raw text.
updateAge :: MonadIO m => ReaderT SqlBackend m ()
updateAge = updateWhere [UserName ==. "SPJ" ] [UserAge =. 45]
Similar to updateWhere which is shown in the above example you can use other functions present in the module Database.Persist.Class. Note that the first parameter of updateWhere is [Filter val] and second parameter is [Update val]. By comparing this with the type of ==. and =., you can see that they match up in the above usage.
The above query when applied on dataset-1, will produce this:
Convenience function for getting a free PersistField instance
from a type with JSON instances. The JSON parser used will accept JSON
values other that object and arrays. So, if your instance serializes the
data to a JSON string, this will still work.
This is a specialization of tabulateEntityA, which allows you to
construct an Entity by providing an Applicative action for each
field instead of a regular function.
The type of record can usually be infered from the types of the provided filters
and select options. In the previous two examples, though, you'll notice that the
select options are polymorphic, applying to any record type. In order to help
type inference in such situations, or simply as an enhancement to readability,
you might find type application useful, illustrated below.
With Asc and Desc, we can provide the field we want to sort on. We can
provide multiple sort orders - later ones are used to sort records that are
equal on the first field.
Get all records matching the given criterion in the specified order.
Returns also the identifiers.
WARNING: This function returns a ConduitM, which suggests that it streams
the results. It does not stream results on most backends. If you need
streaming, see persistent-pagination for a means of chunking results based
on indexed ranges.
Check whether there are any conflicts for unique keys with this entity and
existing entities in the database.
Returns Nothing if the entity would stay unique, and could thus safely be updated.
on a conflict returns the conflicting key
This is similar to checkUnique, except it's useful for updating - when the
particular entity already exists, it would normally conflict with itself.
This variant ignores those conflicts
A modification of getBy, which takes the PersistEntity itself instead
of a Unique record. Returns a record matching one of the unique keys. This
function makes the most sense on entities with a single Unique
constructor.
Insert a value, checking for conflicts with any unique constraints. If a
duplicate exists in the database, it is returned as Left. Otherwise, the
new 'Key is returned as Right.
onlySimonConst :: MonadIO m => ReaderT SqlBackend m (Unique User)
onlySimonConst = onlyUnique $ User "Simon" 999
mSimonConst <- onlySimonConst
mSimonConst would be Simon's uniqueness constraint. Note that
onlyUnique doesn't work if there're more than two constraints. It will
fail with a type error instead.
Attempt to replace the record of the given key with the given new record.
First query the unique fields to make sure the replacement maintains
uniqueness constraints.
Return Nothing if the replacement was made.
If uniqueness is violated, return a Just with the Unique violation
Retrieve the list of FieldDef that makes up the fields of the entity.
This does not return the fields for an Id column or an implicit id. It
will return the key columns if you used the Primary syntax for defining the
primary key.
This does not return fields that are marked SafeToRemove or MigrationOnly
- so it only returns fields that are represented in the Haskell type. If you
need those fields, use getEntityFieldsDatabase.
This returns all of the FieldDef defined for the EntityDef, including
those fields that are marked as MigrationOnly (and therefore only present
in the database) or SafeToRemove (and a migration will drop the column if
it exists in the database).
For all the fields that are present on the Haskell-type, see
getEntityFields.
Note that as of this writing the span covers the entire file or quasiquote
where the item is defined due to parsing limitations. This may be changed in
a future release to be more accurate.
Retrieve the list of UniqueDef from an EntityDef. As of version 2.14,
this will also include the primary key on the entity, if one is defined. If
you do not want the primary key, see getEntityUniquesNoPrimaryKey.
Retrieve the list of UniqueDef from an EntityDef. This does not include
a Primary key, if one is defined. A future version of persistent will
include a Primary key among the Unique constructors for the Entity.
Automatically creates a valid PersistField instance for any datatype
that has valid ToJSON and FromJSON instances. For a datatype T it
generates instances similar to these:
instance PersistField T where
toPersistValue = PersistByteString . L.toStrict . encode
fromPersistValue = (left T.pack) . eitherDecodeStrict' <=< fromPersistValue
instance PersistFieldSql T where
sqlType _ = SqlString
Splice in a list of all EntityDef in scope. This is useful when running
mkPersist to ensure that all entity definitions are available for setting
foreign keys, and for performing migrations with all entities available.
mkPersist has the type MkPersistSettings -> [EntityDef] -> DecsQ. So, to
account for entities defined elsewhere, you'll mappend $(discoverEntities).
Likewise, to run migrations with all entity instances in scope, you'd write:
migrateAll = migrateModels $(discoverEntities)
Note that there is some odd behavior with Template Haskell and splicing
groups. If you call discoverEntities in the same module that defines
PersistEntity instances, you need to ensure they are in different top-level
binding groups. You can write $(pure []) at the top level to do this.
-- Foo and Bar both export an instance of PersistEntity
import Foo
import Bar
-- Since Foo and Bar are both imported, discoverEntities can find them here.
mkPersistWith sqlSettings $(discoverEntities) [persistLowerCase|
User
name Text
age Int
|]
-- onlyFooBar is defined in the same 'top level group' as the above generated
-- instance for User, so it isn't present in this list.
onlyFooBar :: [EntityDef]
onlyFooBar = $(discoverEntities)
-- We can manually create a new binding group with this, which splices an
-- empty list of declarations in.
$(pure [])
-- fooBarUser is able to see the User instance.
fooBarUser :: [EntityDef]
fooBarUser = $(discoverEntities)
The function mkMigrate currently implements exactly this behavior now. If
you're splitting up the entity definitions into separate files, then it is
better to use the entity definition list and the concatenate all the models
together into a big list to call with migrateModels.
module Foo where
share [mkPersist s, mkEntityDefList "fooModels"] ...
module Bar where
share [mkPersist s, mkEntityDefList "barModels"] ...
module Migration where
import Foo
import Bar
migrateAll = migrateModels (fooModels <> barModels)
Creates a declaration for the [EntityDef] from the persistent
schema. This is necessary because the Persistent QuasiQuoter is unable
to know the correct type of ID fields, and assumes that they are all
Int64.
Provide this in the list you give to share, much like mkMigrate.
Creates a single function to perform all migrations for the entities
defined here. One thing to be aware of is dependencies: if you have entities
with foreign references, make sure to place those definitions after the
entities they reference.
In persistent-2.13.0.0, this was changed to *ignore* the input entity def
list, and instead defer to mkEntityDefList to get the correct entities.
This avoids problems where the QuasiQuoter is unable to know what the right
reference types are. This sets mkPersist to be the "single source of truth"
for entity definitions.
This function should be used if you are only defining a single block of
Persistent models for the entire application. If you intend on defining
multiple blocks in different fiels, see mkPersistWith which allows you
to provide existing entity definitions so foreign key references work.
Like mkPersist, but allows you to provide a [EntityDef]
representing the predefined entities. This function will include those
EntityDef when looking for foreign key references.
You should use this if you intend on defining Persistent models in
multiple files.
Suppose we define a table Foo which has no dependencies.
Same as persistFileWith, but uses several external files instead of
one. Splitting your Persistent definitions into multiple modules can
potentially dramatically speed up compile times.
The recommended file extension is .persistentmodels.
Examples
Split your Persistent definitions into multiple files (models1, models2),
then create a new module for each new file and run mkPersist there:
Tip: To get the same import behavior as if you were declaring all your models in
one file, import your new files as Name into another file, then export module Name.
This approach may be used in the future to reduce memory usage during compilation,
but so far we've only seen mild reductions.
Most functions require a full [EntityDef], which can be provided
using $(discoverEntities) for all entites in scope, or defining
mkEntityDefList to define a list of entities from the given block.
Returns a NonEmpty list of FieldDef that correspond with the key
columns for an EntityDef including those fields that are marked as
MigrationOnly (and therefore only present in the database) or
SafeToRemove (and a migration will drop the column if it exists in the
database).
Parse raw field attributes into structured form. Any unrecognized
attributes will be preserved, identically as they are encountered,
as FieldAttrOther values.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
Represents a value containing all the configuration options for a specific
backend. This abstraction makes it easier to write code that can easily swap
backends.
Datatype that represents an entity, with both its Key and
its Haskell record representation.
When using a SQL-based backend (such as SQLite or
PostgreSQL), an Entity may take any number of columns
depending on how many fields it has. In order to reconstruct
your entity on the Haskell side, persistent needs all of
your entity columns and in the right order. Note that you
don't need to worry about this when using persistent's API
since everything is handled correctly behind the scenes.
However, if you want to issue a raw SQL command that returns
an Entity, then you have to be careful with the column
order. While you could use SELECT Entity.* WHERE ... and
that would work most of the time, there are times when the
order of the columns on your database is different from the
order that persistent expects (for example, if you add a new
field in the middle of you entity definition and then use the
migration code -- persistent will expect the column to be in
the middle, but your DBMS will put it as the last column).
So, instead of using a query like the one above, you may use
rawSql (from the
Database.Persist.Sql module) with its /entity
selection placeholder/ (a double question mark ??). Using
rawSql the query above must be written as SELECT ?? WHERE
... Then rawSql will replace ?? with the list of all
columns that we need from your entity in the right order. If
your query returns two entities (i.e. (Entity backend a,
Entity backend b)), then you must you use SELECT ??, ??
WHERE ..., and so on.
An EntityField is parameterised by the Haskell record it belongs to
and the additional type of that field.
As of persistent-2.11.0.0, it's possible to use the OverloadedLabels
language extension to refer to EntityField values polymorphically. See
the documentation on SymbolToField for more information.
Instances1IsLabel
SymbolToFieldsymrectyp => IsLabelsym (EntityFieldrectyp)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
This instance delegates to SymbolToField to provide
OverloadedLabels support to the EntityField type.
Filters which are available for select, updateWhere and
deleteWhere. Each filter constructor specifies the field being
filtered on, the type of comparison applied (equals, not equals, etc)
and the argument for the comparison.
Persistent users use combinators to create these.
Note that it's important to be careful about the PersistFilter that
you are using, if you use this directly. For example, using the InPersistFilter requires that you have an array- or list-shaped
EntityField. It is possible to construct values using this that will
create malformed runtime values.
Persistent serialized Haskell records to the database.
A Database Entity (A row in SQL, a document in MongoDB, etc)
corresponds to a Key plus a Haskell record.
For every Haskell record type stored in the database there is a
corresponding PersistEntity instance. An instance of PersistEntity
contains meta-data for the record. PersistEntity also helps abstract
over different record types. That way the same query interface can return
a PersistEntity, with each query returning different types of Haskell
records.
Some advanced type system capabilities are used to make this process
type-safe. Persistent users usually don't need to understand the class
associated data and functions.
An EntityField is parameterised by the Haskell record it belongs to
and the additional type of that field.
As of persistent-2.11.0.0, it's possible to use the OverloadedLabels
language extension to refer to EntityField values polymorphically. See
the documentation on SymbolToField for more information.
This function allows you to build an Entity a by specifying an
action that returns a value for the field in the callback function.
Let's look at an example.
parseFromEnvironmentVariables :: IO (Entity User)
parseFromEnvironmentVariables =
tabulateEntityA $ \userField ->
case userField of
UserName ->
getEnv USER_NAME
UserAge -> do
ageVar <- getEnv USER_AGE
case readMaybe ageVar of
Just age ->
pure age
Nothing ->
error $ "Failed to parse Age from: " <> ageVar
UserAddressId -> do
addressVar <- getEnv USER_ADDRESS_ID
pure $ AddressKey addressVar
Like tabulateEntityA, but works with any Apply f. This works
because all entities have at least one field, and so we can tabulate
things into semigroup-like shapes instead.
Extract a Key record from a record value. Currently, this is
only defined for entities using the Primary syntax for
natural/composite keys. In a future version of persistent which
incorporates the ID directly into the entity, this will always be Just.
A type class which is used to witness that a type is safe to insert into
the database without providing a primary key.
The TemplateHaskell function mkPersist will generate instances of this
class for any entity that it works on. If the entity has a default primary
key, then it provides a regular instance. If the entity has a Primary
natural key, then this works fine. But if the entity has an Id column with
no default=, then this does a TypeError and forces the user to use
insertKey.
Instances2SafeToInsert
TypeError (EntityErrorMessagea) => SafeToInsert (Entitya)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
TypeError (FunctionErrorMessageab) => SafeToInsert (a -> b)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
This type class is used with the OverloadedLabels extension to
provide a more convenient means of using the EntityField type.
EntityField definitions are prefixed with the type name to avoid
ambiguity, but this ambiguity can result in verbose code.
If you have a table User with a name Text field, then the
corresponding EntityField is UserName. With this, we can write
#name :: EntityField User Text.
What's more fun is that the type is more general: it's actually
#name
:: (SymbolToField "name" rec typ)
=> EntityField rec typ
Which means it is *polymorphic* over the actual record. This allows you
to write code that can be generic over the tables, provided they have
the right fields.
Prior to persistent-2.11.0, we provided an instance of
PersistField for the Natural type. This was in error, because
Natural represents an infinite value, and databases don't have
reasonable types for this.
The instance for Natural used the Int64 underlying type, which will
cause underflow and overflow errors. This type has the exact same code
in the instances, and will work seamlessly.
A more appropriate type for this is the Word series of types from
Data.Word. These have a bounded size, are guaranteed to be
non-negative, and are quite efficient for the database to store.
This type uses the SqlInt64 version, which will exhibit overflow and
underflow behavior. Additionally, it permits negative values in the
database, which isn't ideal.
In this example, we create a PersistField instance for a newtype following the "Smart Constructor" pattern.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.Text as T
import qualified Data.Char as C
-- | An American Social Security Number
newtype SSN = SSN Text
deriving (Eq, Show, PersistFieldSql)
mkSSN :: Text -> EitherText SSN
mkSSN t = if (T.length t == 9) && (T.all C.isDigit t)
then Right $ SSN t
else Left $ "Invalid SSN: " <> t
instance PersistField SSN where
toPersistValue (SSN t) = PersistText t
fromPersistValue (PersistText t) = mkSSN t
-- Handle cases where the database does not give us PersistText
fromPersistValue x = Left $ "File.hs: When trying to deserialize an SSN: expected PersistText, received: " <> T.pack (show x)
Tips:
This file contain dozens of PersistField instances you can look at for examples.
TypeError ((((('Text"The instance of PersistField for the Natural type was removed." ':$$: 'Text"Please see the documentation for OverflowNatural if you want to ") ':$$: 'Text"continue using the old behavior or want to see documentation on ") ':$$: 'Text"why the instance was removed.") ':$$: 'Text"") ':$$: 'Text"This error instance will be removed in a future release.") => PersistFieldNaturalDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldHtmlDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldByteStringDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt16Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt32Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt64Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt8Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldRationalDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldBoolDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldDoubleDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldIntDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWordDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord16Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord32Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord64Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord8Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
Get all records matching the given criterion in the specified order.
Returns also the identifiers.
NOTE: This function returns an Acquire and a ConduitM, which implies
that it streams from the database. It does not. Please use selectList
to simplify the code. If you want streaming behavior, consider
persistent-pagination which efficiently chunks a query into ranges, or
investigate a backend-specific streaming solution.
This class witnesses that two backend are compatible, and that you can
convert from the sub backend into the sup backend. This is similar
to the HasPersistBackend and IsPersistBackend classes, but where you
don't want to fix the type associated with the PersistEntityBackend of
a record.
This works for SqlReadBackend because of the instance BackendCompatibleSqlBackendSqlReadBackend, without needing to go through the BaseBackend type family.
Likewise, functions that are currently hardcoded to use SqlBackend can be generalized:
Class which allows the plucking of a BaseBackend backend from some larger type.
For example,
instance HasPersistBackend (SqlReadBackend, Int) where
type BaseBackend (SqlReadBackend, Int) = SqlBackend
persistBackend = unSqlReadBackend . fst
Class which witnesses that backend is essentially the same as BaseBackend backend.
That is, they're isomorphic and backend is just some wrapper over BaseBackend backend.
Replace the record in the database with the given
key. Note that the result is undefined if such record does
not exist, so you must use insertKey or repsert in
these cases.
ToBackendKey converts a PersistEntityKey into a BackendKey
This can be used by each backend to convert between a Key and a plain
Haskell type. For Sql, that is done with toSqlKey and fromSqlKey.
By default, a PersistEntity uses the default BackendKey for its Key
and is an instance of ToBackendKey
A Key that instead uses a custom type will not be an instance of
ToBackendKey.
This class is used to ensure that functions requring at least one
unique key are not called with records that have 0 unique keys. The
quasiquoter automatically writes working instances for appropriate
entities, and generates TypeError instances for records that have
0 unique keys.
StypetypeMultipleUniqueKeysErrorty = ((('Text"The entity " ':<>: 'ShowTypety) ':<>: 'Text" has multiple unique keys.") ':$$: ('Text"The function you are trying to call requires only a single " ':<>: 'Text"unique key.")) ':$$: (('Text"There is probably a variant of the function with 'By' " ':<>: 'Text"appended that will allow you to select a unique key ") ':<>: 'Text"for the operation.")
This is an error message. It is used when an entity has multiple
unique keys, and the function expects a single unique key.
StypetypeNoUniqueKeysErrorty = (('Text"The entity " ':<>: 'ShowTypety) ':<>: 'Text" does not have any unique keys.") ':$$: ('Text"The function you are trying to call requires a unique key " ':<>: 'Text"to be defined on the entity.")
This class is used to ensure that upsert is only called on records
that have a single Unique key. The quasiquoter automatically generates
working instances for appropriate records, and generates TypeError
instances for records that have 0 or multiple unique keys.
Queries against Unique keys (other than the id Key).
Please read the general Persistent documentation to learn how to create
Unique keys.
Using this with an Entity without a Unique key leads to undefined
behavior. A few of these functions require a singleUnique, so using
an Entity with multiple Uniques is also undefined. In these cases
persistent's goal is to throw an exception as soon as possible, but
persistent is still transitioning to that.
SQL backends automatically create uniqueness constraints, but for MongoDB
you must manually place a unique index on a field to have a uniqueness
constraint.
Some functions in this module (insertUnique, insertBy, and
replaceUnique) first query the unique indexes to check for
conflicts. You could instead optimistically attempt to perform the
operation (e.g. replace instead of replaceUnique). However,
there is some fragility to trying to catch the correct exception and
determing the column of failure;
an exception will automatically abort the current SQL transaction.
Update based on a uniqueness constraint or insert:
insert the new record if it does not exist;
If the record exists (matched via it's uniqueness constraint), then update the existing record with the parameters which is passed on as list to the function.
Next, what if the schema has two uniqueness constraints?
Let's check it out using schema-2:
mSpjEnt <- upsertSpj [UserAge +=. 15]
This fails with a compile-time type error alerting us to the fact
that this record has multiple unique keys, and suggests that we look for
upsertBy to select the unique key we want.
upsertBySpjName :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertBySpjName record updates = upsertBy (UniqueUserName "SPJ") record updates
mSpjEnt <- upsertBySpjName (Person "X" 999) [PersonAge += .15]
upsertBySimonAge :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertBySimonAge record updates = upsertBy (UniqueUserName "SPJ") record updates
mPhilipEnt <- upsertBySimonAge (User "X" 999) [UserName =. "Philip"]
+----+-----------------+-----+
| id | name | age |
+----+-----------------+-----+
| 1 | SPJ | 40 |
+----+-----------------+-----+
| 2 | Simon -> Philip | 41 |
+----+-----------------+-----+
upsertByUnknownName :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertByUnknownName record updates = upsertBy (UniqueUserName "Unknown") record updates
mXEnt <- upsertByUnknownName (User "X" 999) [UserAge +=. 15]
A specification for how the implied ID columns are created.
By default, persistent will give each table a default column named id
(customizable by PersistSettings), and the column type will be whatever
you'd expect from BackendKey yourBackendType. For The SqlBackend type,
this is an auto incrementing integer primary key.
You might want to give a different example. A common use case in postgresql
is to use the UUID type, and automatically generate them using a SQL
function.
Previously, you'd need to add a custom Id annotation for each model.
User
Id UUID default="uuid_generate_v1mc()"
name Text
Dog
Id UUID default="uuid_generate_v1mc()"
name Text
user UserId
Now, you can simply create an ImplicitIdDef that corresponds to this
declaration.
newtype UUID = UUID ByteString
instance PersistField UUID where
toPersistValue (UUID bs) =
PersistLiteral_Escaped bs
fromPersistValue pv =
case pv of
PersistLiteral_ Escaped bs ->
Right (UUID bs)
_ ->
Left "nope"
instance PersistFieldSql UUID where
sqlType _ = SqlOtherUUID
With this instance at the ready, we can now create our implicit definition:
The DbSpecific constructor corresponds to the legacy
PersistDbSpecific constructor. We need to keep this around because
old databases may have serialized JSON representations that
reference this. We don't want to break the ability of a database to
load rows.
Instances4Eq, Ord, Read, Show
EqLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
OrdLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
ReadLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
ShowLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
This constructor is used to specify some raw literal value for the
backend. The LiteralType value specifies how the value should be
escaped. This can be used to make special, custom types avaialable
in the back end.
Deprecated. Deprecated since 2.11 because of inconsistent escaping behavior across backends. The Postgres backend escapes these values, while the MySQL backend does not. If you are using this, please switch to PersistLiteral_ and provide a relevant LiteralType for your conversion.
This pattern synonym used to be a data constructor for the
PersistValue type. It was changed to be a pattern so that JSON-encoded
database values could be parsed into their corresponding values. You
should not use this, and instead prefer to pattern match on
PersistLiteral_ directly.
If you use this, it will overlap a patern match on the 'PersistLiteral_,
PersistLiteral, and PersistLiteralEscaped patterns. If you need to
disambiguate between these constructors, pattern match on
PersistLiteral_ directly.
This pattern synonym used to be a data constructor on PersistValue,
but was changed into a catch-all pattern synonym to allow backwards
compatiblity with database types. See the documentation on
PersistDbSpecific for more details.
This pattern synonym used to be a data constructor on PersistValue,
but was changed into a catch-all pattern synonym to allow backwards
compatiblity with database types. See the documentation on
PersistDbSpecific for more details.
Settings that can be passed to the mkPersist (mps) function to control what code is generated.
This is (just) the data type definition, so you will most likely want to use and adapt concrete values
like sqlSettings.
Deprecated. The mpsGeneric function adds a considerable amount of overhead and complexity to the library without bringing significant benefit. We would like to remove it. If you require this feature, please comment on the linked GitHub issue, and we'll either keep it around, or we can figure out a nicer way to solve your problem.Github: https://github.com/yesodweb/persistent/issues/1204
Create generic types that can be used with multiple backends. Good for
reusable code, but makes error messages harder to understand. Default:
False.
A Checkmark should be used as a field type whenever a
uniqueness constraint should guarantee that a certain kind of
record may appear at most once, but other kinds of records may
appear any number of times.
NOTE: You need to mark any Checkmark fields as nullable
(see the following example).
For example, suppose there's a Location entity that
represents where a user has lived:
Location
user UserId
name Text
current Checkmark nullable
UniqueLocation user current
The UniqueLocation constraint allows any number of
InactiveLocations to be current. However, there may be
at most one currentLocation per user (i.e., either zero
or one per user).
This data type works because of the way that SQL treats
NULLable fields within uniqueness constraints. The SQL
standard says that NULL values should be considered
different, so we represent Inactive as SQL NULL, thus
allowing any number of Inactive records. On the other hand,
we represent Active as TRUE, so the uniqueness constraint
will disallow more than one Active record.
Note: There may be DBMSs that do not respect the SQL
standard's treatment of NULL values on uniqueness
constraints, please check if this data type works before
relying on it.
The SQL BOOLEAN type is used because it's the smallest data
type available. Note that we never use FALSE, just TRUE
and NULL. Provides the same behavior Maybe () would if
() was a valid PersistField.
An EntityDef represents the information that persistent knows
about an Entity. It uses this information to generate the Haskell
datatype, the SQL migrations, and other relevant conversions.
Instances5Eq, Ord, Read, Show, Lift
EqEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
OrdEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
ReadEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
ShowEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
LiftEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
This indicates that the column is nullable, but should not have
a Maybe type. For this to work out, you need to ensure that the
PersistField instance for the type in question can support
a PersistNull value.
data What = NoWhat | Hello Text
instance PersistField What where
fromPersistValue PersistNull =
pure NoWhat
fromPersistValue pv =
Hello $ fromPersistValue pv
instance PersistFieldSql What where
sqlType _ = SqlString
User
what What nullable
This tag means that the column will not be present on the Haskell code,
but will not be removed from the database. Useful to deprecate fields in
phases.
You should set the column to be nullable in the database. Otherwise,
inserts won't have values.
A SafeToRemove attribute is not present on the Haskell datatype, and
the backend migrations should attempt to drop the column without
triggering any unsafe migration warnings.
Useful after you've used MigrationOnly to remove a column from the
database in phases.
This attribute indicates that we should not create a foreign key
reference from a column. By default, persistent will try and create a
foreign key reference for a column if it can determine that the type of
the column is a Key entity or an EntityId and the Entity's name
was present in mkPersist.
This is useful if you want to use the explicit foreign key syntax.
Post
title Text
Comment
postId PostId noreference
Foreign Post fk_comment_post postId
This is set to specify precisely the database table the column refers
to.
Post
title Text
Comment
postId PostId references="post"
You should not need this - persistent should be capable of correctly
determining the target table's name. If you do need this, please file an
issue describing why.
This datatype describes how a foreign reference field cascades deletes
or updates.
This type is used in both parsing the model definitions and performing
migrations. A Nothing in either of the field values means that the
user has not specified a CascadeAction. An unspecified CascadeAction
is defaulted to Restrict when doing migrations.
A FieldDef represents the inormation that persistent knows about
a field of a datatype. This includes information used to parse the field
out of the database and what the field corresponds to.
The name of the field. Note that this does not corresponds to the
record labels generated for the particular entity - record labels
are generated with the type name prefixed to the field, so
a FieldDef that contains a FieldNameHS "name" for a type
User will have a record field userName.
Defines how operations on the field cascade on to the referenced
tables. This doesn't have any meaning if the fieldReference is set
to NoReference or SelfReference. The cascade option here should
be the same as the one obtained in the fieldReference.
A SQL data type. Naming attempts to reflect the underlying Haskell
datatypes, eg SqlString instead of SqlVarchar. Different SQL databases may
have different translations for these types.
The reason why a field is nullable is very important. A
field that is nullable because of a Maybe tag will have its
type changed from A to Maybe A. OTOH, a field that is
nullable because of a nullable tag will remain with the same
type.
This function differs from runDB in that it returns a database
runner function, as opposed to simply running a single action. This will
usually mean that a connection is taken from a pool and then reused for
each invocation. This can be useful for creating streaming responses;
see runDBSource.
It additionally returns a cleanup function to free the connection. If
your code finishes successfully, you must call this cleanup to
indicate changes should be committed. Otherwise, for SQL backends at
least, a rollback will be used instead.