Setting up mutations in absinthe

Using Ecto v2.2.6, Phoenix 1.3

I have Absinthe installed on my Phoenix instance and am able to run queries on it with no trouble, but I cannot get mutations to work.

I have absinthe installed thusly in mix.exs:

...
      {:absinthe, "~> 1.3.0-rc.0"},
      {:absinthe_plug, "~> 1.3.0-rc.0"},
      {:absinthe_ecto, git: "https://github.com/absinthe-graphql/absinthe_ecto.git"},
...

Then I created a simple object to test. (Ran migration, added route, did not modify schema)

mix phx.gen.json Content Thing things name:string

Tested Repo.insert! from iex. Works fine.

I added the Thing to types.ex:

defmodule MyApp.Schema.Types do
  use Absinthe.Schema.Notation
  use Absinthe.Ecto, repo: MyApp.Repo

  object :thing do
    field :id, :id
    field :name, :string
  end
end

Now the schema. I put Thing into a query field and I can see it just fine. The mutation then goes in:

  mutation do
    field :create_thing, :thing do
      arg :name, non_null(:string)
      resolve fn(%{name: name}, _context) ->
        IO.puts "TESTING"
        thing = MyApp.Repo.insert!(%MyApp.Content.Thing{ name: name })
        {:ok, thing}
      end
    end
  end

Then I type into graphiql:

mutation  {
  createThing(name: "test") {
    id
  }
}

…and the iex console says:

[info] GET /graphiql
[debug] ABSINTHE schema=nil variables=%{}
---
mutation  {
  createThing(name: "test") {
    id
  }
}
---
[info] Sent 405 in 325µs

…and my graphiql window tells me SyntaxError: Unexpected token C in JSON at position 0

Any ideas on how to troubleshoot this?

Try to return {:ok, %{thing: thing}} in your resolver function.

Also, I am usually hiding any Repo reference in my resolvers functions by calling context functions…

eg:

MyApp.MyContext.create_thing(params)

1 Like

shouldn’t that be (http://absinthe-graphql.org/tutorial/mutations/) :

mutation createThing  {
  thing(name: "test") {
    id
  }
}
1 Like

I forgot to tell I am using an intermediary result object.
That is my example, with category…

Here is my mutation

    @desc "Create category mutation"
    field :create_category, :category_result do
      arg :input, non_null(:category_input)
      resolve &CategoryResolver.create_category/3
    end

Here is my result object

  object :category_result do
    field :category, :category
    field :errors, list_of(:input_error)
  end

Here is my resolver

  def create_category(_, %{input: params}, _) do
    with {:ok, category} <- Blogging.create_category(params) do
      {:ok, %{category: category}}
    end
  end

I implemented the changeset error middleware from the Absinthe book…

I did not include the middleware, but I highly recommand previous mentionned book.

And here is my mutation

mutation($input: CategoryInput!) {
  createCategory(input: $input) {
    errors {
      key
      message
    }
    category {
      id
      internalId
      name
    }
  }
}

With input value

{"input": {"name": "koko"}}

and the result

{
  "data": {
    "createCategory": {
      "errors": null,
      "category": {
        "name": "koko",
        "internalId": 9,
        "id": "Q2F0ZWdvcnk6OQ=="
      }
    }
  }
}

@outlog Doesn’t seem to work when I do that either.

mutation createThing  {
  thing(name: "test") {
    id
  }
}

I’m wondering if there is something wrong with my local setup. Has anyone tried running this absinthe-example on github? I’m seeing the same problem when I clone and run it.

1 Like

Something odd is going on because GraphiQL shouldn’t be sending a GET request for documents, they basically all use POST. In fact mutations are not permitted unless doing a POST.

@outlog nah that isn’t right actually, the document name and the field name are different ideas.

2 Likes

What response do you see in your network tab of your browser?

1 Like

Maybe You are just missing the input in your mutation.

He isn’t using variables, so that shouldn’t make any difference. The response sent from the server is HTTP 405, which is an explicit status return from Absinthe.Plug when mutations are done over a GET request. I don’t know why they are, but that’s the issue that we’re dealing with.

2 Likes

@benwilson512 Yep, graphiql was set to GET.
Well that was embarrassing.

1 Like