GithubHelp home page GithubHelp logo

elm-postgrest's People

Contributors

danstn avatar john-kelly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elm-postgrest's Issues

5.0.0 release

The current plan is to release the next version of the library in sync with the 0.19 release of Elm.

With that being said, there are still a few things I'd like to finish before an official release:

  1. embed alias updates: (#57)
  2. documentation: (#12)
  3. misc api name changes + updates (no issues for that right now)

Additionally, there are a few issue we may want to consider/think about before the next release. At the very least we should examine if they are candidates for non major bump updates:

  1. upsert (#58)
  2. custom error type (#59)
  3. composite attributes (#42)

At the time of writing, my focus is on documentation.

`is` operator type

{-| Is comparison
-}
is : Maybe Bool -> (schema -> Field (Maybe Bool)) -> schema -> Filter
is =
    singleValueFilterFn Is

from vs query vs (equiv)

fetchSchools =
    PG.query Schema.school School
        |> PG.select .name
        |> PG.select .streetAddress
        |> PG.select .city
        |> PG.select .stateAbbrev
        |> PG.readMany "http://localhost:3000"
            { filter = []
            , order = []
            , limit = Nothing
            , offset = 0
            }

vs

fetchSchools =
    PG.from Schema.school School
        |> PG.select .name
        |> PG.select .streetAddress
        |> PG.select .city
        |> PG.select .stateAbbrev
        |> PG.readMany "http://localhost:3000"
            { filter = []
            , order = []
            , limit = Nothing
            , offset = 0
            }

filter vs filters

i'm leaning on the side of filter

it's hard to remember which record name is correct filter vs filters -- order vs orders

Naming filter and order operators

Note to self that I think operator names should be looked at again. My gut is telling me that camel casing everything (I'm looking at you ilike) makes more sense.

Non-trivial resource field codecs support

Is it currently possible to provide different codecs for decoding and encoding?

The use-case is as follows:

Resource foo has a field email that could be null, so we'd like our Foo model to represent email as Maybe String. The resource and query definition look like this:

fooResource = 
  resourse "foo"
    { ...
    , email = field "email" <| Decode.maybe Decode.string
    , ...
    }

fooQuery = 
  query fooResource Foo
    |> ...
    |> select .email
    |> ...

fooRequest : List String -> Cmd (List Foo)
fooRequest emails =
  fooQuery
    |> filter [ .email |> in' emails ]
    |> ...

The problem is that if I try to apply a filter to the query (|> filter [ .email |> in' [<list of strings>]) the types don't line up, because the resource uses a Maybe String codec.

Is there a way to say which codec to use when making requests?

There is a high chance that I'm missing something fundamental though.

Selecting where order does not matter?

Okay, so in terms of implementing Json without depending on order

[9:52]
Let's start by defining a simple mode:

[9:52]

 { name : String
 , age : Int
 }

[9:53]
Nothing fancy really. Now let's describe how we'd like our decoders to look:

[9:53]

decodeModel value =
 Ok { name = "", age = 0 } 
   |> decodeField "age" Json.int setAge value
   |> decodeField "name" Json.string setName value

[9:53]
Notice how I've gotten rid of the confusing Decoder abstraction for now

[9:53]
Also notice that name and age are out of place

[9:54]
Also notice that I define setAge and setName, lens style

[9:55]
they're mostly boilerplate but for clarity, this is what they look like:

setName model name = { model | name = name }

setAge model age = { model | age = age }

[9:55]
finally, we use it like this:

  E.object [ ("name", E.string "noah"), ("age", E.int 10) ]
    |> decodeModel
    |> toString
    |> Html.text

[9:56]
decodeModel will return a result of Ok { name = "noah", age = 10 }

[9:56]
decodeField is a scary looking thing which is actually pretty simple:

[9:56]

 String
 -> Json.Decoder a 
 -> (Model -> a -> Model) 
 -> Json.Value 
 -> Result String Model 
 -> Result String Model 
decodeField fieldName decoder setter value model = 
 case model of 
   Err s -> model
   Ok v -> 
     Json.decodeValue (Json.field fieldName decoder) value
       |> Result.map (setter v)

[9:56]
(there are various ways of cleaning this up some more, but this is how you do out-of-order decoding in elm)

[9:59]
It could be further simplified if elm provided a couple of things. Namely, things that were taken out of the type system that didn't need to be (e.g adding fields to a record - then we wouldn't need to provide a default)

[9:59]
This approach is infinitely more workable.

[10:00]
You can make refactoring changes to your model without worrying about the order

[10:00]
If you have the right tooling, then generating setters/getters is trivial

[10:00]
Anyway, the other point: notice how I flatten the types as soon as possible.

[10:01]
People get so confused when they see Decoder a and don't know how to make their own

fredcy [10:01 AM]
Fascinating. But my brain hurts. I hope someday you'll write this up. (I know that's not your thing though).

eeue56 [10:02 AM]
Which bit is making your brain hurt? Maybe I can explain that a bit better

fredcy [10:04 AM]
The role of the first line of decodeModel puzzles me. Just haven't seen record values built up from a default as that appears to be.

rtfeldman [10:12 AM]

AndMap (not a big fan of the name either) is exactly the right tool for the job
of course, the json-pipeline library aliases andMap, but to understand how that decoder works, you need to know how andMap works

this is not a great pitch for andMap the function itself as opposed to the concept behind it ๐Ÿ˜‰

eeue56 [10:15 AM]
@fredcy, it's exactly what decode does in elm-decode-pipeline

glenjamin [10:15 AM]
@eeue56 when thinking about it, I found the Generator one harder to refactor (only tried in my head) because of the need to chain the RNG state around - did I miss something?

eeue56 [10:15 AM]
You can think of it as "raising" or "lifting" a value into a type. Basically, just taking a Model and turning into Result x Model

[10:16]
which can then be piped down to the other functions, so they can keep a clean sig

[10:16]
@glenjamin you can pass the state onwards in the same way through a tuple if you want

[10:16]
I just didn't for the decode example since it doesn't need it

glenjamin [10:17 AM]
ah right, same general approach then - you get something like bind and return, but name them based on the concrete case?

eeue56 [10:19 AM]
you'd need a return for that example yeah

(META) API Design

I currently believe that all api choices should be as close to sql as possible. PostgREST really is a thin layer over sql and i think that it would be important to reveal this fact in the elm client api. There is definitely a possibility that a more general realization of this library would change api naming, however, this library is not that. Despite this realization, it is important to note that priorities are as follows:

  1. Type safety and Preventing Invalid States (queries)
  2. API close to SQL

Relevant Issues:
#51
#50
#48
#47
#53

init and update example on dev branch

I like what I see in the dev branch, but I am struggling to construct a prototype.
I am not able to interpret from reading the source and from the compiler errors what the dev branch needs in init and update. In the source, you mention that an examples/Main.elm might be the first stop, but I do not find that. Might you find time to draft an example to get us started?

map...map8 limits

I just ran into my first case of needing to retrieve ten fields in a query. Right now it looks like I have to make two queries, but it would be helpful to find a more general way instead. It's not unusual for rows in a database to have more than eight columns.

change filtering and ordering api

reason being -- include is currently forced to be Maybe... because of the possibility of filtering the query

something like this.

sessionCmd =
    let
        speakerQuery =
            PG.query Resources.speaker Speaker
                |> PG.select .id
                |> PG.select .name
                |> PG.select .bio
    in
        PG.query Resources.session Session
            |> PG.select .id
            |> PG.select .location
            |> PG.select .start_time
            |> PG.include .speaker speakerQuery
            |> PG.list "http://postgrest.herokuapp.com/"
                [ .location |> PG.not PG.ilike "%russia%" ]
                [ PG.asc .start_time ]
                PG.noLimit
            |> Http.send Fetch

vs



sessionCmd =
    let
        speakerQuery =
            PG.query Resources.speaker Speaker
                |> PG.select .id
                |> PG.select .name
                |> PG.select .bio
    in
        PG.query Resources.session Session
            |> PG.select .id
            |> PG.select .location
            |> PG.select .start_time
            |> PG.include .speaker speakerQuery
            |> PG.list "http://postgrest.herokuapp.com/"
                { filter = [ .location |> PG.not PG.ilike "%russia%" ]
                , order = [ PG.asc .start_time ]
                , limit = PG.noLimit
                }
            |> Http.send Fetch

Hardcoded name

although using the same name as elm-decode-pipeline is nice for reusing common naming conventions...

similar functions (in our lib) use a verb convention instead of the adj convention. for example: select, set, insert... so maybe hardcode instead of hardcoded

just bringing this up for discussion.

hardcode values

when the value does not come from the api.

similar to http://package.elm-lang.org/packages/NoRedInk/elm-decode-pipeline/3.0.0/Json-Decode-Pipeline#hardcoded

{-| -}
hardcoded : a -> Query uniq schema (a -> b) -> Query uniq schema b
hardcoded val (Query queryName schema params queryDecoder) =
    Query queryName
        schema
        params
        (apply queryDecoder (Decode.succeed val))

-- example

majorQuery =
    PG.query Resources.major Major
        |> PG.select .id
        |> PG.select .assist_id
        |> PG.select .title
        |> PG.select .description
        |> PG.select .school_id
        |> PG.hardcoded True

type alias Major =
    { id : Int
    , assist_id : String
    , title : String
    , description : Maybe String
    , school_id : Int
    , collapsed : Bool
    }

BelongsTo vs HasOne

based on my shallow exploration, it appears that these are different. i do not know how or why, so this may be worth looking into.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.