lykahb / groundhog

This library maps datatypes to a relational model, in a way similar to what ORM libraries do in OOP. See the tutorial https://www.schoolofhaskell.com/user/lykahb/groundhog for introduction
http://hackage.haskell.org/package/groundhog
176 stars 39 forks source link

`Maybe a` where `a` is an embedded type #75

Closed pjones closed 5 years ago

pjones commented 7 years ago

I have an Email type that is configured through mkPersist as an embedded type. For some of the types in this application I would like to have a record field of Maybe Email, but that won"t compile:

    • Could not deduce (Database.Groundhog.Core.NeverNull Email)
        arising from a use of ‘Database.Groundhog.Core.dbType’
      from the context: Database.Groundhog.Core.DbDescriptor db
        bound by the type signature for:
                   entityDef :: Database.Groundhog.Core.DbDescriptor db =>
                                proxy db -> Student -> Database.Groundhog.Core.EntityDef
        at lib/Merkel/Types/Database/Student.hs:(101,1)-(112,2)
    • In the expression:
        Database.Groundhog.Core.dbType p_a1aSQ (undefined :: Maybe Email)
      In the expression:
        ("student_email", 
         Database.Groundhog.Core.dbType p_a1aSQ (undefined :: Maybe Email))
      In the third argument of ‘Database.Groundhog.Core.ConstructorDef’, namely
        ‘[("student_created_at", 
           Database.Groundhog.Core.dbType p_a1aSQ (undefined :: UTCTime)),
          ("student_name", 
           Database.Groundhog.Core.dbType p_a1aSQ (undefined :: Text)),
          ("student_email", 
           Database.Groundhog.Core.dbType p_a1aSQ (undefined :: Maybe Email)),
          ("student_account", 
           Database.Groundhog.Core.dbType
             p_a1aSQ (undefined :: Maybe (DefaultKey Account)))]’

Is there something in my YAML that needs to change to allow this?

lykahb commented 7 years ago

It would help to see the Email type and how you describe it in YAML.

pjones commented 7 years ago

Sorry about that. Here you go:

data Email = Email
  { emailAddress :: Text

  } deriving Show

mkPersist merkelCodegenConfig [groundhog|
embedded: Email
fields:
  - name: emailAddress
    dbName: email
|]

Where:

merkelCodegenConfig :: CodegenConfig
merkelCodegenConfig = defaultCodegenConfig
                      { namingStyle = lowerCaseSuffixNamingStyle
                      }
lykahb commented 5 years ago

Sorry for ignoring the issue for so long. In this case the Groundhog templating logic doesn't have enough data to tell if an embedded type is mapped into one column. A field of type Text clearly is, but a tuple or another embedded cannot be easily distinguished in compile-time, as the code cannot call dbType. Mapping to the single column is necessary for making the NeverNull and PrimitivePersistField instances.

In this case the best solution would be to define an instance manually:

instance NeverNull Email