Skip to content
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

Conversion between snake and camel case inconsistencies #601

Open
kevmojay opened this issue Aug 27, 2018 · 14 comments
Open

Conversion between snake and camel case inconsistencies #601

kevmojay opened this issue Aug 27, 2018 · 14 comments

Comments

@kevmojay
Copy link

I ran into an issue where the following field
field(:v_i_n, :string)
would produce the graphql field "vIN"

When requesting vIN, it would produce an error "errors":[{"message":"Cannot query field \"vIN\" on type \"Metadata\". Did you mean \"vIN\"?","locations":[{"line":30,"column":0}]}]}

This is because absinthe uses Macro.camelize and Macro.underscore. These aren't necessarily reverse operations.

iex(19)> "v_i_n" |> Macro.camelize |> Macro.underscore
"vin"
iex(20)> "foo_bar" |> Macro.camelize |> Macro.underscore
"foo_bar"

I was considering creating a PR to create a more consistent conversion but figured it would be too much of a breaking change.

I was curious if there were any potential options of how this should be solved, if at all.

@ku1ik
Copy link

ku1ik commented Aug 30, 2018

I just ran into similar problem. We have field :adress_line_1 in input object schema, and when addressLine1 is included we get Unknown field error.

iex(1)> "address_line_1" |> Macro.camelize |> Macro.underscore
"address_line1"

Sending value for this field under addressLine_1 works, but this is not what GQL schema shows in GraphiQL (it underlines it as error).

@alejandrodnm
Copy link

I was going crazy I have a percent_change_7d field, the unittests were passing because they are in snake_case, but graphiql complained with

 "Cannot query field \"percentChange7d\" on type \"Quote\". Did you mean \"percentChange24h\", \"percentChange1h\", or \"percentChange7d\"?",

The weird part is that Graphiql autocompletes the correct name.

screen shot 2018-09-03 at 00 39 00

Changing it to percentChange_7d like @sickill suggested makes the query work.

@ku1ik
Copy link

ku1ik commented Sep 4, 2018

I think that quite safe way of fixing that is to keep %{Macro.camelize(field_1_name) => field_1_name, ...} map on the schema, and use it for lookup instead of relying on Macro.underscore. If that sounds like acceptable solution I'd be happy to send PR.

@benwilson512
Copy link
Contributor

benwilson512 commented Sep 4, 2018 via email

@alanpeabody
Copy link

Hi @benwilson512 I wanted to bring this one back up and see if there is anything I can do to help. With a little direction I am happy to open a PR.

I pulled down 1.5.0-alpha.2 but it appears to suffer from the same problem.

This is a pretty big blocker for me when working with api clients that generate queries automatically from introspection.

I would prefer to help fix it in absinthe rather then come up with new field names with out numbers or something.

@benwilson512
Copy link
Contributor

@alanpeabody is this a blocker there? Adapters should provide everything you need there. There are some consistency issues when trying to use the built in adapter with specific field names (involving numbers for example) but even those are handleable with adjusters.

@alanpeabody
Copy link

alanpeabody commented Feb 22, 2019

Thanks for directing me to look at and Adapter. I have solved for now with a custom adapter delegating most processing to the LanguageConventions Adapter:

  @impl true
  def to_internal_name(external_name, role) do
    external_name
    |> String.replace(~r/([a-zA-Z])(\d+)/, "\\1_\\2")
    |> LanguageConventions.to_internal_name(role)
  end

However, to me, this isn't an ideal solution for something that seems like it should work out of the box.

For reference my schema is something like:

  object :ticker do
    # ...
    field :price_change_24h, :currency_price
    field :price_change_24h_pct, :float
    field :high_price_24h, :currency_price
    field :low_price_24h, :currency_price
    field :volume_24h, :currency_amount
    # ...
  end

And a query generated interactively with GraphiQL using the introspective API is:

query {
  getTicker() {
    highPrice24h { amount }
    lowPrice24h { amount }
    priceChange24h { amount }
    priceChange24hPct
    volume24h { amount }
  }
}

However, those two combined generate this error:

{
      "message": "Cannot query field \"highPrice24h\" on type \"Ticker\". Did you mean \"priceChange24hPct\", \"priceChange24h\", \"lowPrice24h\", or \"highPrice24h\"?"
}

The fact that the query is passing in what is the correct field, the error says "this field is incorrect" and then lists the exact field you input isn't a great experience for people trying to develop against and API using the provided documentation.

Using a custom adapter works for me, but I do think the correct fix would be in Absinthe itself, and I am happy to help with it.

tcitworld added a commit to framasoft/mobilizon that referenced this issue Apr 1, 2019
Got caught with absinthe-graphql/absinthe#601
at some point, that's why fields are renamed

Fix tests

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
@iautom8things
Copy link

iautom8things commented May 3, 2019

Glad I found this. I'm just getting started with GraphQL and Absinthe. I'm working with a platform that I do not have control over the naming of tables/columns and there's prolific use of underscores, and most notably double underscores.

I thought I was going crazy when I was getting the error Cannot query field "foo" ... Did you mean "foo"?.

I'll try to take a look at Adapters like was suggested. There was a mention that v1.5 would make some changes that address this. Are those still in the works?

Thank you.

@benwilson512
Copy link
Contributor

@iautom8things keep in mind that nothing requires that you use the same graphql field names as your database column names. In fact you can even rename them at the ecto layer to be more ergonomic.

@jfrolich
Copy link
Contributor

Would be great if it can be resolved in 1.5! Using a custom adapter now, but not the best solution.

@jfrolich
Copy link
Contributor

It might be better to have a slightly different underscore function by default, that puts an underscore before digits by default (looks like a lot of people are running into this).
I could pull-request this.

@nishant-ghodke
Copy link

I had the same issue. Columns names in MySQL table, and properties in Ecto model and GraphQL schema were in camelCase.

I fixed the issue by updating the case of all properties and columns to snake_case.

Absinthe makes the model properties accessible in camelCase but expects the same to be declared in snake_case.

Absinthe version: 1.4.16

@thebigredgeek
Copy link

thebigredgeek commented Oct 31, 2020

This is still an issue in 1.5

@dotdotdotpaul
Copy link

Still a problem in 2022. Even worse, I defined an input field with the name :fooBar (actual name hidden for proprietary reasons), and when I ran a test giving it that key, the error it generated was this:

In field \\\"fooBar\\\": Unknown field. Did you mean \\\"fooBar\\\"?

Yeah, I almost had to go buy a new laptop after I got that gem on my screen.

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

No branches or pull requests