yesodweb / yesodweb/persistent

Missing mapping from text to field name

Open
#637 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Haskell
Stars
486
Forks
306
PR merge metrics
No merged PRs in 30d

Description

Hi,

I'm playing with servant and persistent and I've found this issue. My api has something like that:

type ListApi a = 
    OrderBy :> FilterBy :> FilterWildcard :> Limit :> Offset :> Get '[JSON] [(Int, a)]
type OrderBy = 
    QueryParam "order-by" Text

Here, OrderBy would be Text representing column name (or haskell datatype name). Now I would like to use selectList. To do that I need to convert incoming Text to EntityField. Using this data as example:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Area json
    deleted Bool
    name Text
    visible Bool
    active Bool
    index Int
    image Text Maybe
    description Text Maybe
    deriving Show Eq
Client json
    deleted Bool
    name Text
    street Text
    city Text
    state Text
    country Text
    code Text
    image Text Maybe
    description Text Maybe
    deriving Show Eq
|]

I am unable to write this function:

toEntityField "deleted" = Just AreaDeleted
toEntityField "name" = Just AreaName
toEntityField "visible" = Just AreaVisible
...
toEntityField _ = Nothing

I can do it like this:

toSortingOption "deleted" = [Asc AreaDeleted]
toSortingOption "name" = [Asc AreaName]
toSortingOption "visible" = [Asc AreaVisible]
toSortingOption "active" = [Asc AreaActive]
toSortingOption "index" = [Asc AreaIndex]
toSortingOption _ = []

and maybe use typeclass to make it work for all types:

class HasSortingField a where
  toSortingOption :: Text -> [SelectOpt a]

so then:

instance HasSortingField Client where
toSortingOption "deleted" = [Asc ClientDeleted]
toSortingOption "name" = [Asc ClientName]
toSortingOption "street" = [Asc ClientStreet]
toSortingOption "city" = [Asc ClientCity]
toSortingOption "state" = [Asc ClientState]
toSortingOption "country" = [Asc ClientCountry]
toSortingOption "code" = [Asc ClientCode]
toSortingOption _ = []

Then I could use it to convert incoming string into SelectOpt that selectList needs. This will work, but is far from ideal solution. This just doesn't scale. Is there a way to generate a mapping from names to fields using TH? Or maybe my approach is wrong? I want to sort by given column name, very basic thing. Probably with filtering (FilterBy :> FilterWildcard part of my api) I would have the same problem.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing persistent's selectList API, the generated EntityField constructors, and the Template Haskell settings shown in the issue. Determine whether a generic Text-to-EntityField mapping can support sorting and filtering for generated entities, and consider the mapping complete when callers no longer need to define per-entity field cases manually.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.