yesodweb / yesodweb/persistent
Split up `PersistEntity`
Nobody has claimed this yet.
- Dominant language
- Haskell
- Stars
- 486
- Forks
- 306
- PR merge metrics
- No merged PRs in 30d
Description
Related to #1037 and #1239
Right now, PersistEntity has a ton of responsibilities. Here's the class definition (minus comments)
class
( PersistField (Key record), ToJSON (Key record), FromJSON (Key record)
, Show (Key record), Read (Key record), Eq (Key record), Ord (Key record)
)
=>
PersistEntity record
where
type PersistEntityBackend record
data Key record
keyToValues :: Key record -> [PersistValue]
keyFromValues :: [PersistValue] -> Either Text (Key record)
persistIdField :: EntityField record (Key record)
entityDef :: proxy record -> EntityDef
data EntityField record :: Type -> Type
persistFieldDef :: EntityField record typ -> FieldDef
toPersistFields :: record -> [SomePersistField]
fromPersistValues :: [PersistValue] -> Either Text record
data Unique record
persistUniqueKeys :: record -> [Unique record]
persistUniqueToFieldNames :: Unique record -> NonEmpty (FieldNameHS, FieldNameDB)
persistUniqueToValues :: Unique record -> [PersistValue]
fieldLens :: EntityField record field
-> (forall f. Functor f => (field -> f field) -> Entity record -> f (Entity record))
keyFromRecordM :: Maybe (record -> Key record)
keyFromRecordM = Nothing
So, a PersistEntity record implies:
- There's a specific
PersistEntityBackend recordthat the type must be used with (probably can be deleted with #1250 ) - There's a primary
Keyfor the record.- That key can be converted into a
[PersistValue], and parsed from a[PersistValue] - There's a specific
EntityFieldthat directly corresponds to that primary key (this is false for composite keys)
- That key can be converted into a
- You can get an
entityDef Proxy :: EntityDeffor a given type. - There is an
EntityFieldinstance for the type. - You can convert the type into a
[SomePersistField]and parse one out of a[PersistValue]. - The record has uniqueness keys. #1239
- Uniqueness keys can be converted into a
[PersistValue](but not parsed - there's no[PersistValue] -> Either Text (Unique record)?) - Uniqueness keys have a
NonEmpty (FieldNameHS, FieldNameDB)associated - like aFieldDeforEntityDef - Primary keys and Unique keys are not interchangeable.
- Uniqueness keys can be converted into a
This is too much.
Here's a sketch of how I'd like to refactor this. First, I want to have classes for things that can be rendered into a database with multiple columns, as well as a class for parsing them out.
class ToPersistValues a where
toPersistValues :: a -> [PersistValue]
class FromPersistValues a where
-- note that we may want this to be something like Either Text ([PersistValue], a)
-- if the idea is that we parse multiple columns, then it makes sense to have left overs
fromPersistValues :: [PersistValue] -> Either Text a
We can pretty easily have an instance of PersistField a => ToPersistValues (Only a). And we can make tuples for parsing out lots of stuff.
In #1133 I talk about using prairie, which pulls out EntityField, persistFieldLens, and other things from PersistEntity. That may not be feasible until we get the separation of types for inserting/reading from the database. I'm not sure if that's necessary.
Then that leaves our Key and Unique stuff. #1239 I think I'll put most of my thoughts in there about how to resolve it.
So, I think, for a path forward:
- Implement the
To/FromPersistValuesclasses and make them superclasses ofPersistEntity. - Figure out the uniqueness keys design
a. Do we want to make that a superclass? It doesn't make sense for all things... it is perfectly possible in SQL to have a table without a primary key.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the PersistEntity class definition and the designs discussed in issues #1037, #1239, #1250, and #1133. Evaluate the proposed ToPersistValues and FromPersistValues classes first, then resolve how Key and Unique responsibilities should be separated. Done means the refactoring direction and uniqueness-key design are agreed and documented well enough to implement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell
- Domain
- database
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100