From 63c795e5c0bd7f59e4e6a4373cc44ec040dd8f38 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Fri, 5 Apr 2024 07:34:06 +0300 Subject: [PATCH] Regenerate content --- book/generated-xml/deploying-your-webapp.xml | 4 +- book/generated-xml/persistent.xml | 89 +++++++++++++------- book/generated-xml/routing-and-handlers.xml | 17 ++++ 3 files changed, 79 insertions(+), 31 deletions(-) diff --git a/book/generated-xml/deploying-your-webapp.xml b/book/generated-xml/deploying-your-webapp.xml index 44326676..44bfb60b 100644 --- a/book/generated-xml/deploying-your-webapp.xml +++ b/book/generated-xml/deploying-your-webapp.xml @@ -34,7 +34,7 @@ Edit the config/keter.yaml file in your scaffolded applicatio -Set up some kind of server for hosting yours apps. I recommend trying Ubuntu on Amazon EC2. +Set up some kind of server for hosting your apps. I recommend trying Ubuntu on Amazon EC2. @@ -245,7 +245,7 @@ behind it instead. Keter configuration is trivial, since it is designed to work with Yesod applications. But if you want to instead use Nginx, how do you set it up? In general, Nginx will listen on port 80 and your Yesod/Warp app will listen on -some unprivileged port (lets say 4321). You will then need to provide a +some unprivileged port (let’s say 4321). You will then need to provide a nginx.conf file, such as: daemon off; # Don't run nginx in the background, good for monitoring apps events { diff --git a/book/generated-xml/persistent.xml b/book/generated-xml/persistent.xml index b7a7d683..80566fe3 100644 --- a/book/generated-xml/persistent.xml +++ b/book/generated-xml/persistent.xml @@ -59,7 +59,10 @@ Persistent on its own.
Synopsis The required dependencies for the below are: persistent, persistent-sqlite and persistent-template. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -333,7 +336,10 @@ filter, the types of the filtering value match the field. There’s another associated newtype for the database primary key of this entity. We can use the generated Person type like any other Haskell type, and then pass it off to other Persistent functions. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -342,11 +348,6 @@ pass it off to other Persistent functions. {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE DerivingStrategies #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE DataKinds #-} import Control.Monad.IO.Class (liftIO) import Database.Persist @@ -358,7 +359,7 @@ import Control.Monad.Reader import Control.Monad.Logger import Conduit -share [mkPersist sqlSettings, mkEntityDefList "entityDefs"] [persistLowerCase| +share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Person name String age Int Maybe @@ -445,7 +446,10 @@ an error message about a missing table. For SQL databases, one of the major pains can be managing schema changes. Instead of leaving this to the user, Persistent steps in to help, but you have to ask it to help. Let’s see what this looks like: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -454,11 +458,6 @@ to ask it to help. Let’s see what this looks like:This works when dealing with just a few entities, but can quickly get tiresome once we are dealing with a dozen entities. Instead of repeating yourself, Persistent provides a helper function, mkMigrate: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -597,7 +599,10 @@ unique. While each field name must begin with a lowercase letter, the uniqueness constraints must begin with an uppercase letter, since it will be represented in Haskell as a data constructor. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -719,8 +724,7 @@ rowsep="1" colsep="1" A Source containing all the IDs and values from the database. This allows you to write streaming code. NOTE: A Source is a stream of data, and is part of the conduit package. I recommend reading the -School -of Haskell conduit tutorial to get started. +Official Conduit tutorial to get started. selectList @@ -994,7 +998,10 @@ two words on a line. Suppose we want to have a Person entity with an (optional) age and the timestamp of when he/she was added to the system. For entities already in the database, we want to just use the current date-time for that timestamp. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1031,7 +1038,10 @@ nullable. understood by the database. In this case, it uses the database’s built-in CURRENT_TIME function. Suppose that we now want to add a field for a person’s favorite programming language: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1064,7 +1074,10 @@ database schema and automatic migrations. properly interpret it. Finally, Persistent can use double quotes for containing white space, so if we want to set someone’s default home country to be El Salvador: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1111,7 +1124,10 @@ up-to-date list is maintained Persistent allows references between your data types in a manner that is consistent with supporting non-SQL databases. We do this by embedding an ID in the related entity. So if a person has many cars: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1150,7 +1166,10 @@ many-to-many relationships, we need a join entity, which has a one-to-many relationship with each of the original tables. It is also a good idea to use uniqueness constraints on these. For example, to model a situation where we want to track which people have shopped in which stores: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1244,7 +1263,7 @@ Post We know that BlogId is just a type synonym for Key Blog, but how will Key Blog be defined? We can’t use an Int64, since that won’t work for MongoDB. And we can’t use ByteString, since that won’t work for SQL databases. -To allow for this, once mpsGeneric is set to True, out resulting datatypes have a type parameter to indicate the database backend they use, so that keys can be properly encoded. This looks like: +To allow for this, once mpsGeneric is set to True, our resulting datatypes have a type parameter to indicate the database backend they use, so that keys can be properly encoded. This looks like: data BlogGeneric backend = Blog { blogTitle :: Text } data PostGeneric backend = Post { postTitle :: Text @@ -1281,7 +1300,10 @@ import Database.Persist.TH data Employment = Employed | Unemployed | Retired deriving (Show, Read, Eq) derivePersistField "Employment" -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1330,7 +1352,10 @@ interface exclusively.) Actually, you can express a LIKE operator directly in the normal syntax due to a feature added in Persistent 0.6, which allows backend-specific operators. But this is still a good example, so let’s roll with it. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1377,7 +1402,10 @@ here to point out how it works under the surface. The yesod-persistent package provides the meeting point between Persistent and Yesod. It provides the YesodPersist typeclass, which standardizes access to the database via the runDB method. Let’s see this in action. -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -1484,7 +1512,10 @@ Persistent knowledge should transfer over easily.
Something besides SQLite To keep the examples in this chapter simple, we’ve used the SQLite backend. Just to round things out, here’s our original synopsis rewritten to work with PostgreSQL: -{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} diff --git a/book/generated-xml/routing-and-handlers.xml b/book/generated-xml/routing-and-handlers.xml index dcdd3c45..0f7e4a43 100644 --- a/book/generated-xml/routing-and-handlers.xml +++ b/book/generated-xml/routing-and-handlers.xml @@ -188,6 +188,23 @@ syntax should be preferred as it’s clearer what the goal is./foo/bar route to Foo1R or Foo3R? And should /foo/42 route to Foo2R or Foo3R? Yesod’s rule for this is simple: first route wins.
+
+Empty <literal>#String</literal> or <literal>#Text</literal> as dynamic piece +Consider the following route declaration: +/hello HelloR GET +/hello/#String HelloNameR GET +Let’s say a user requests the path /hello/ – which handler would respond to the request? +It will be HelloR because Yesod’s dispatch mechanism removes trailing slashes and +redirects to the canonical form of the URL (see section ). +If users actually want to address the HelloNameR handler with an +empty string as argument they need to request the path /hello/- +instead. Yesod automatically converts the Minus sign to the empty string. +Likewise, the resulting URL for @{HelloNameR ""} would be /hello/-. +Also, to disambiguate a single actual -, Yesod prefixes that piece with another Minus sign when rendering the URL. +Consequently, Yesod also prefixes any string consisting only of Minus signs with one single Minus sign. +This conversion between empty string in Haskell and - in the +URL applies for #String and #Text pieces as well. +
Resource name