Skip to content

Instantly share code, notes, and snippets.

@john-kelly
Last active October 24, 2016 06:00
Show Gist options
  • Save john-kelly/8ac5aa5d5e38bd148b70e10b0c44408c to your computer and use it in GitHub Desktop.
Save john-kelly/8ac5aa5d5e38bd148b70e10b0c44408c to your computer and use it in GitHub Desktop.
import PostgRest exposing (..)
type Relation schema
= Relation String schema
-- subQuery based on query6 api
{-| -}
subQuery : (schema1 -> Relation schema2) -> (a -> b) -> Query schema1 c -> Query schema2 (a -> b)
subQuery getRelation recordCtor (Query name schema params decoder) =
case getRelation schema of
Relation subName subSchema ->
Query subName
subSchema
{ select = [], filter = [], order = [], limit = Nothing }
(Decode.succeed recordCtor)
{-| -}
include : (Query schema1 (a -> b) -> Query schema2 a) -> Query schema1 (a -> b) -> Query schema1 b
include fn ((Query queryName queryShape queryParams queryDecoder) as query) =
case fn query of
Query subName subShape subParams subDecoder ->
Query queryName
queryShape
{ queryParams | select = Nested subName subParams :: queryParams.select }
(apply queryDecoder (subName := subDecoder))
hasMany : (() -> Resource schema) -> Relation schema
hasA : (() -> Resource schema) -> Relation schema
trainer =
resource "trainer"
{ id = int "id"
, name = string "name"
, pokemon = hasMany (\() -> pokemon)
}
pokemon =
resource "pokemon"
{ id = int "id"
, name = string "name"
, base_experience = int "base_experience"
, weight = int "weight"
, height = int "height"
, trainer = hasA (\() -> trainer)
}
type alias Pokemon =
{ id : Int
, name : String
}
type alias Trainer =
{ id : Int
, name : String
, pokemon : List Pokemon
}
query1 =
query trainer Trainer
|> select .id
|> select .name
|> include
(subQuery .pokemon Pokemon
|> select .id
|> select .name
|> filter [ .id |> lte 151 ]
)
|> filter [ .name |> eq "Ash" ]
query2 =
query trainer Trainer
|> select .id
|> select .name
|> include .pokemon
Pokemon
(\q ->
q
|> select .id
|> select .name
|> filter [ .id |> lte 151 ]
)
|> filter [ .name |> eq "Ash" ]
query3 =
let
sub q =
q
|> select .id
|> select .name
|> filter [ .id |> lte 151 ]
in
query trainer Trainer
|> select .id
|> select .name
|> include .pokemon Pokemon sub
|> filter [ .name |> eq "Ash" ]
query4 =
query trainer Trainer
|> select .id
|> select .name
|> include .pokemon
Pokemon
(select .id
>> select .name
>> filter [ .id |> lte 151 ]
)
|> filter [ .name |> eq "Ash" ]
query5 =
let
sub =
select .id
>> select .name
>> filter [ .id |> lte 151 ]
in
query trainer Trainer
|> select .id
|> select .name
|> include .pokemon Pokemon sub
|> filter [ .name |> eq "Ash" ]
query6 =
query trainer Trainer
|> select .id
|> select .name
|> include
(subQuery .pokemon Pokemon
>> select .id
>> select .name
>> filter [ .id |> lte 151 ]
)
|> filter [ .name |> eq "Ash" ]
@john-kelly
Copy link
Author

john-kelly commented Oct 24, 2016

ive come to the sad realization that this is not possible:

session =
    resource "sessions"
        { id = int "id"
        , speaker_id = int "speaker_id"
        , start_time = string "start_time"
        , end_time = string "end_time"
        , location = string "location"
        , session_type = int "session_type"
        , speaker = hasOne (\_ -> speaker)
        }


speaker =
    resource "speakers"
        { id = int "id"
        , name = string "name"
        , sessions = hasMany (\_ -> session)
        }

which means none of these api changes are possible.

would love someone to prove me wrong... but it looks like we are stuck with the current api...

someone please prove me wrong.

https://github.com/elm-lang/elm-compiler/blob/master/hints/recursive-alias.md

@john-kelly
Copy link
Author

Even after wrapping schema in a Union Type (like suggested in the docs), I was unable to achieve the desired behavior.

Would love to chat with someone about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment