3

我一直试图定义在我看来是一个非常基本的突变。我是 Scala、GraphQL、Akka HTTP 的新手,而且不是母语人士,所以如果下面的任何内容是胡说八道,请原谅我!很抱歉这篇冗长的文章,我确实试图用最少的例子来保持简短,但我觉得完整的上下文很重要。

语境

我有以下代码定义了一个Transaction案例类、一个用于所有事务的假数据库以及一个用于查询和创建事务的模式:

case class Transaction(id: Int, description: String, amount: BigDecimal)

object TransactionDB {
  var transactions: List[Transaction] = Nil
}

class TransactionDB {
  def transaction(id: Int): Option[Transaction] =
    TransactionDB.transactions.find(_.id == id)
  def createTransaction(transaction: Transaction) = {
    TransactionDB.transactions = transaction :: TransactionDB.transactions
    transaction
  }
}

import sangria.macros.derive._
import sangria.marshalling.sprayJson._
import sangria.schema._
import spray.json._
import DefaultJsonProtocol._

object TransactionSchema {
  val Id = Argument("id", IntType)
  val TransactionType = deriveObjectType[Unit, Transaction]()
  val QueryType = ObjectType("Query", fields[TransactionDB, Unit](
    Field("transaction", OptionType(TransactionType),
      arguments = Id :: Nil,
      resolve = c ⇒ c.ctx.transaction(c.arg(Id))
    )
  ))

  implicit val transactionFormat = jsonFormat3(Transaction)
  val TransactionInputType = deriveInputObjectType[Transaction](
    InputObjectTypeName("TransactionInput")
  )

  val TransactionArg = Argument("transaction", TransactionInputType)
  val MutationType = ObjectType("Mutation", fields[TransactionDB, Unit](
    Field("createTransaction", TransactionType,
      arguments = TransactionArg :: Nil,
      resolve = c ⇒ c.ctx.createTransaction(c.arg(TransactionArg))
    )
  ))

  val schema = Schema(QueryType, Some(MutationType))
}

生成的 GraphQL 架构如下:

type Mutation {
  createTransaction(transaction: TransactionInput!): Transaction!
}

type Query {
  transaction(id: Int!): Transaction
}

type Transaction {
  id: Int!
  description: String!
  amount: BigDecimal!
}

input TransactionInput {
  id: Int!
  description: String!
  amount: BigDecimal!
}

然后我可以创建一个事务并使用以下查询对其进行查询:

mutation {
  createTransaction(transaction: {
    id: 1
    description: "Electricity bill"
    amount: 100
  }) {
    id
  }
}

query {
  transaction(id: 1) {
    id
    description
    amount
  }
}

问题

但是,id不应该是突变的一部分。理想情况下,我会得到:

input TransactionInput {
  description: String!
  amount: BigDecimal!
}

type Mutation {
  createTransaction(input: TransactionInput): Transaction
  updateTransaction(id: Int!, input: TransactionInput): Transaction # For later
}

graphql-js文档中,这是通过以下方式完成的:

createTransaction({description, amount}) {
  const id = generateId();
  transactionRepo[id] = new Transaction(id, description, amount);
  return transaction[id];
},
updateTransaction(id, {description, amount}) { // Assuming id exists
  transactionRepo[id] = new Transaction(id, description, amount);
  return transactionRepo[id];
},

在 Scala / Sangria 中找到解决方案是我遇到的问题。

尝试的解决方案

尝试1:我在想这样的事情:

def createTransaction(description: String, amount: BigDecimal) = {
  val r = scala.util.Random // Or leave this to the DB layer
  val transaction = Transaction(r.nextInt(10000), description, amount)
  TransactionDB.transactions = transaction :: TransactionDB.transactions
  transaction
}

但这不起作用,因为createTransaction给定的 aTransactionArg映射到 a Transaction

尝试 2:我也尝试切换到,jsonFormat2因为已删除id,但这会type mismatch在编译时触发 a,因为Transaction它有 3 个属性。

尝试 3:我尝试更新派生InputObjectType以排除id使用:

val TransactionInputType = deriveInputObjectType[Transaction](
  InputObjectTypeName("TransactionInput"),
  ExcludeInputFields("id")
)

这可以编译,但是当尝试运行上面给出的突变时,结果如下:

  • Argument 'transaction' has invalid value: Object is missing required member 'id'id从现场省略时createTransaction(transaction: {...})
  • Argument 'transaction' expected type 'TransactionInput!' but got: {id: 42, description: \"Electricity bill\", amount: 100}. Reason: Unknown field 'id' is not defined in the input type 'TransactionInput'.添加回来时。

我错过了什么?对我来说这似乎很简单,graphql-js但我找不到如何在 Scala 中使用 Sangria 做到这一点。我多次阅读文档并在 Google 上广泛查看,因为这似乎是一个简单的问题,但没有找到任何类似的东西。谢谢!

4

1 回答 1

4

似乎两者都createTransaction返回updateTransaction一个Transaction定义为:

type Transaction {
  id: Int!
  description: String!
  amount: BigDecimal!
}

所需的id: Int!状态id(这就是!意思)所以我首先将其重新定义为:(id: Int无感叹号)。

于 2017-02-15T09:33:41.800 回答