Skip to content

Question about data intermediate representations #40

@jim108dev

Description

@jim108dev

I have coded a findByCredentials query with selda. Email, password goes in, User record comes out. The User record has restricted newtypes inside of it (LongString, ShortString).

The same information User(bio,...) is now represented 4 times in the code (see below) + database table definition in sql. Can you help me getting the number down?

Thanks.

findByCredentials :: PG.Pool -> Credentials -> Aff (Either InputError User)
findByCredentials pool { email, password } =
  PG.withConnection pool case _ of
    Left pgError -> throwError $ error $ ("PostgreSQL connection error: " <> show pgError)
    Right conn -> do
      runSelda conn (app email password) >>= validate

validate :: forall a. Either PGError (Array a) -> Aff (Either InputError a)
validate result = do
  case result of
    Left e -> case e of
      IntegrityError detail -> case detail.constraint of
        "email_unique" -> pure $ Left EMAIL_EXISTS
        "username_unique" -> pure $ Left USERNAME_EXISTS
        otherwise -> throwError $ error $ show e
      otherwise -> throwError $ error $ show e
    Right rows -> case head rows of
      Nothing -> pure $ Left NOT_FOUND
      Just row -> pure $ Right row

user 
  Table
    ( bio :: Maybe String -- 1. representation
    , email :: String
    , id :: Auto Int
    , image :: Maybe String
    , password :: String
    , username :: String
    )
user =
  Source "user"
    $ case _ of
        Nothing"\"user\""
        Just alias → "\"user\"" <> " " <> alias

type InterUser 
  = { bio :: Maybe String -- 2. representation
    , email :: String
    , id :: Int
    , image :: Maybe String
    , password :: String
    , username :: String
    }

mkUser :: InterUser -> User 
mkUser i =
  unsafePartial
    { bio: LongString.unsafeFromString <$> i.bio -- 3. representation
    , email: ShortString.unsafeFromString (i.email)
    , id: i.id
    , image: LongString.unsafeFromString <$> i.image
    , password: ShortString.unsafeFromString i.password
    , username: ShortString.unsafeFromString i.username
    }

selectUser 
   s.
  Email ->
  Password ->
  FullQuery s
    { bio :: Col s (Maybe String)  -- 4. representation
    , email  Col s String
    , id  Col s Int
    , image :: Col s (Maybe String)
    , password :: Col s String
    , username :: Col s String
    }
selectUser email password =
  selectFrom user \r → do
    restrict $ r.email .== lit (ShortString.toString email) && r.password .== lit (ShortString.toString password)
    pure r

queryUser 
   m.
  MonadSeldaPG m =>
  Email -> Password -> m (Array InterUser)
queryUser email password = query (selectUser email password)

app   m. MonadSeldaPG m => Email -> Password -> m (Array User)
app email password = do
  logQuery $ selectUser email password
  rows <- queryUser email password
  pure $ mkUser <$> rows

logQuery   s i m. GetCols i  MonadEffect m  FullQuery s { | i }  m Unit
logQuery q = do
  let
    { strQuery, params } = showPG $ showQuery q
  log strQuery
  log $ unsafeStringify params
  log ""

Metadata

Metadata

Assignees

No one assigned

    Labels

    add to guideUse case worth including in the guide

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions