ash-project / ash_json_api

The JSON:API extension for the Ash Framework
https://hexdocs.pm/ash_json_api
MIT License
62 stars 42 forks source link

Allow options for key format #55

Closed ianknauer closed 1 year ago

ianknauer commented 2 years ago

Working on implementation for issue https://github.com/ash-project/ash_json_api/issues/17, allowing users to define the strategy for how to handle keys with multiple words in types, relationships and attributes.

I've implemented camelCase (userName) and dasherize (user-name) on the serializer to start with and wanted to get some feedback before i continued on.

Within a consuming app you can define this option as follows:

json_api do 
  key_transformer "camel_case"
end

In the app i'm testing this PR with i'm getting the following back from the serializer using CURL requests.

  "data": [
    {
      "attributes": {
        "email": "testing.email@gmail.com",
        "firstName": "tester",
        "insertedAt": "2022-02-09T22:49:12.901732Z",
        "lastName": "McGee",
        "updatedAt": "2022-02-09T22:49:12.904930Z"
      },
      "id": "66c98040-15aa-4254-8030-0baae05d4c78",
      "links": {},
      "meta": {},
      "relationships": {
        "donorNotes": {
          "data": [
            {
              "id": "e266f0eb-b053-4fdc-bd9c-e742f9fb9c1a",
              "type": "donorNote"
            }
          ],
          "links": {
            "self": "http://localhost:4000/donors/66c98040-15aa-4254-8030-0baae05d4c78/relationships/donor_notes"
          },
          "meta": {}
        }
      },
      "type": "donor"
    },
  }
]

Todo

Contributor checklist

zachdaniel commented 2 years ago

Hey @ianknauer, this looks like a great start! There is one main thing that I would suggest, which is instead of having the transformer be a string like "camel_case" or "dasherize", that we should instead have key_transformer :camel | :dash | YourOwnModule. And then instead of doing the switch logic to get them in the serializer, we'd do it at compile time you can do that w/ a custom type, that looks like this:

key_transformer: [
  type: {:custom, __MODULE__, :key_transformer, []},
  ....
]

def key_transformer(:dash), do: {:ok, DashModule}
def key_transformer(:camel), do: {:ok, CamelModule}
def key_transformer(other), do: {:ok, other}

since the serializer functions get called a ton we want to ideally push as much of its logic to compile time as we can.

This also allows them to do key_transformer: SomeModuleTheyWrote and have custom key transformers :)

but this is looking great 🙂 Looking forward to having this in place!

zachdaniel commented 1 year ago

Closing this for now. Feel free to reopen if work continues.