Skip to content

add basic design for allowing to set letterCase #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

jannishuebl
Copy link
Contributor

@jannishuebl jannishuebl commented Jan 31, 2018

This is my suggestion to fix #66 .

What are your opinions?

First to underscore and then to camelcase seems strange to me, but it seems like the semantic of the inflected package is correct that way, since activesupport also has this semantics.

@jannishuebl jannishuebl changed the title WIP: add basic design for allowing to set letterCase add basic design for allowing to set letterCase Jan 31, 2018
@richmolj
Copy link
Contributor

@jannishuebl haven't been able to take a deep look yet but seems like it's coming along nicely. I like letterCase and I'm fine with underscore/camelize - though we should probably extract that same logic into a separate hyphenate function.

@richmolj
Copy link
Contributor

richmolj commented Feb 1, 2018

After thinking about it a bit more, what do you think about refactoring to something like

// model.ts

serializeKey(key: string) : string {
  if (this.letterCase == 'underscore') {
    // etc
  }
}

deserializeKey(key: string) : string {
  if (this.letterCase == 'underscore') {
    // etc
  }
}

Then in the relevant portions of the code we call serializeKey/deserializeKey. This way we can support easy configuration with letterCase, but users can also override these functions and do whatever type of serialization/deserialization they want. Should also clean up the code a bit.

@jannishuebl
Copy link
Contributor Author

@richmolj I like that too! I'll give it a try.

@jannishuebl
Copy link
Contributor Author

@richmolj would you prefer a static methods for that purpose?

@richmolj
Copy link
Contributor

richmolj commented Feb 1, 2018

Yeah static makes sense

Copy link
Contributor

@richmolj richmolj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jannishuebl thanks so much for this work - we're very close to merging along with a 1.0 release. Had some minor comments and then we are good to go!

src/model.ts Outdated
@@ -466,7 +468,7 @@ export class JSORMBase {
let attributeName = key

if (this.klass.camelizeKeys) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're allowing backwards-incompatible changes in 1.0, I'd like to remove this and support letterCase === "camelized" the same way you already have letterCase === "dasherized"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion they both have a different semantic:

letterCase allows to set the format of the api.
camelizeKeys tells jsorm if it should camelize the keys that come from the api or if it should keep the format as it is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this really comes down for naming. Effectively we now have deserializeKey and serializeKey methods - anything dealing with casing should be within these two methods.

So one option would be to move if (this.camelizeKeys) into the serializeKey method's logic. But it doesn't really make sense to have one thing called letterCase and another thing called camelizeKeys.

What about something like static keyFormat = { from: 'dasherized', to: 'camelized' }?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes putting it to an object with from and to makes totally sense. I think keyFomat is to general what's about keyCase?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keyCase sounds good to me 👍 Please make sure Typescript is only allowing from/to strings we have whitelisted. @wadetandy suggests 'dash' | 'camel' | 'snake'

@@ -241,7 +241,11 @@ class Deserializer {
let relationName = key

if (instance.klass.camelizeKeys) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same note on camelizeKeys

@@ -44,7 +43,7 @@ export class ValidationErrors {
let attribute = meta.attribute

if (this.model.klass.camelizeKeys) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camelizeKeys

@@ -44,7 +44,7 @@ describe("Model Class static attributes typings", () => {
const endpoint: string = RootClass.endpoint
const jwt: string | undefined = RootClass.jwt
const jwtLocalStorage: string | false = RootClass.jwtLocalStorage
const camelizeKeys: boolean = RootClass.camelizeKeys
const keyCase: KeyCase = RootClass.keyCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I donot know about this test. It should fail in my opinion but does not. also if I change another attributes type to something diffrent.

Since this is my first time writing typescript I appreciate some help here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I'm following your question. This test is essentially serving as a smoke test that the type of a particular static property is what you'd expect. If you look at the comment at the top, the test won't actually ever fail, it will just be a type error in your editor or at compilation time. The current state of yarn run test doesn't actually throw type errors, so it's more of a user assistance test than anything.

src/model.ts Outdated
@@ -39,14 +39,19 @@ import { cloneDeep } from "./util/clonedeep"
import { nonenumerable } from "./util/decorators"
import { IncludeScopeHash } from "./util/include-directive"

export interface KeyCase {
from: "dash" | "camel" | "snake"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may want to extract these strings to a separate type for easier reuse: type KeyCaseValue = "dash" | "camel" | "snake"

src/model.ts Outdated
@@ -128,7 +133,7 @@ export class JSORMBase {
static endpoint: string
static isBaseClass: boolean
static jwt?: string
static camelizeKeys: boolean = true
static keyCase: KeyCase = { from: "snake", to: "camel" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from and to are confusing names for me when the possible arguments are the case themselves. Transitive names of these imply that the arguments are functions, when instead they are 'which case I am in when on a particular side of the server and client interaction'. For this reason I'd suggest renaming to client and either server or api.

@wadetandy
Copy link
Contributor

Thanks for making that change. This all looks 🔥 great 🔥

Thanks for the contribution!

@wadetandy wadetandy merged commit 5af9d3a into jsonapi-suite:1.x-dev Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants