初学者了解GraphQL-第三部分

114 阅读7分钟

初学者了解GraphQL-第三部分

《了解GraphQL for Beginners》的第二部分中,我们创建了可以获取数据的查询。在第三部分,我们学习什么是突变,并创建突变查询来修改数据。在我们开始之前,让我们回顾一下我们在这个系列中迄今为止所学到的东西:

  • GraphQL是一种用于API的数据操作和查询语言
  • 不再有过度和不足的数据取用
  • 根字段根据选择的对象字段定义你的响应字段的结构。它们是GraphQL服务器的入口点(类似于端点)
  • 对象字段是一个对象的属性

学习成果

  • 创建一个GraphQL突变,以修改数据库中的数据。
  • 使用GraphQL突变来创建一个新的ActiveRecord。
  • 使用GraphQL突变修改数据。
  • 使用GraphQL突变来销毁现有的ActiveRecord。

在你开始之前

在本教程中,我们将使用与第二部分相同的资源库。作为提醒,该资源库已经设置了GraphQL所需的模型和宝石。

下面的模型是

食物

属性类型
idBigint
名称字符串
原产地符号
形象形象
创建时间时间戳
更新时间时间戳

营养

属性类型
id大数
food_id大数
服务量绳子
卡路里脂肪
总脂肪脂肪
反式脂肪饱和脂肪
饱和脂肪字符串
胆固醇字符串
字符串
字符串
总碳水化合物字符串
膳食纤维膳食纤维
糖类膳食纤维
蛋白质蛋白质
维生素_a字符串
维生素_c弦乐
钙质字符串
创建时间时间戳
更新时间时间戳

什么是突变?

突变是在数据库中创建、修改或删除对象的查询,类似于REST中的PUT、POST或DELETE请求。突变请求被发送到与查询请求相同的端点。突变查询有以下结构:

mutation {
  foodCreate(input: {
    name: "Apple Pie",
    placeOfOrigin: "US",
    image: "apple-pie.png"
  }) {
    id
    name
    placeOfOrigin
    image
  }
}
  • 查询以突变开始
  • 任何需要的参数都在输入
  • 突变字段名包含它要执行的动作,即foodCreate

我们在命名我们的突变查询时,先是一个对象,然后是动作。这对按字母顺序排列突变很有用,如下图所示:

先按对象排序按动作先排序
food_create.rbcreate_food.rb
food_delete.rbcreate_nutrition.rb
fiid_update.rbdelete_food.rb
营养_创建.rbdelete_nutrition.rb
nutrition_delete.rbupdate_food.rb
nutrition_update.rbupdate_nutrition.rb
左图:用一个对象先命名一个突变,然后再命名动作。右边。命名一个突变时,先是动作,然后是对象。

我们并不倾向于使用哪种命名方式,但是,我们使用图片左边的命名方式。你可以在mutations 目录下找到所有的突变,在types 目录下找到mutation_type.rb

创建你的第一个突变查询

我们创建一个foodCreate 突变来创建新的食物项目。要创建一个突变查询,在你的终端输入以下内容。rails g graphql:mutation foodCreate

rails generator ,做以下事情:

  1. 检查像base_mutation.rbmutation_type.rb 这样的新突变文件是否存在。如果不存在,就创建它们。
  2. 添加根字段,food_createmutation_type.rb
  3. 创建一个名为food_create.rb 的类。

让我们到mutation_type.rb类中,删除名为test_field 的字段和方法。

field :test_field, String, null: false,
  description: "An example field added by the generator"
def test_field
  "Hello World"
end

请注意,我们不需要在这里写一个方法,像在 query_type.rb.的突变。Mutations::foodCreate在该突变类中执行了一个名为resolve 的方法。我们很快就会知道resolve 这个方法是什么。然后我们进入food_create.rb,你的类看起来像这样。

module Mutations
  class FoodCreate < BaseMutation
    # TODO: define return fields
    # field :post, Types::PostType, null: false

    # TODO: define arguments
    # argument :name, String, required: true

    # TODO: define resolve method
    # def resolve(name:)
    #   { post: ... }
    # end
  end
end

我们要做的第一件事是添加输入参数。删除所有的注释,然后添加以下内容。

module Mutations
  class FoodCreate < BaseMutation
    argument :name, String, required: true
    argument :place_of_origin, String, required: true
    argument :image, String, required: true
  end
end

GraphQL默认使用camel大小写(placeOfOrigin)。为了与Shopify的风格指南保持一致,我们将使用蛇形大小写(place_of_origin)来代替。该字段的蛇形大小写会被GraphQL自动转换为驼峰大小写

接下来,我们需要添加一个解析方法。解析方法为其字段获取数据(food_create frommutation_type.rb )并返回一个响应。GraphQL服务器在其模式中每个字段只有一个解析方法。

module Mutations
  class FoodCreate < BaseMutation
    argument :name, String, required: true
    argument :place_of_origin, String, required: true
    argument :image, String, required: true
  
    def resolve(**args)
    end
  end
end

你可能想知道** 是什么。这是一个叫做double splat的运算符,它向解析方法传递一个哈希值。这允许我们传递尽可能多的参数。为了获得最佳实践,如果有三个以上的参数,请使用双拼接来传递参数。为了简单起见,我们对三个参数使用双拼。

然后,我们添加类型Types::FoodCreate ,以表示我们的响应字段,并在解析方法中,创建一个新的ActiveRecord。

module Mutations
  class FoodCreate < BaseMutation
    argument :name, String, required: true
    argument :place_of_origin, String, required: true
    argument :image, String, required: true

    type Types::FoodType

    def resolve(**args)
      Food.create!(args)
    end
  end
end

现在,让我们在GraphiQL上测试一下吧!转到http://localhost:3000/graphiql,测试我们新的突变查询!

编写以下查询。

mutation {
  foodCreate(input: {
    name: "Apple Pie",
    placeOfOrigin: "US",
    image: "apple-pie.png"
  }) {
    id
    name
    placeOfOrigin
    image
  }
}

当你执行该查询时,你会得到以下响应。

{
  "data": {
    "foodCreate": {
      "id": "4",
      "name": "Apple Pie",
      "placeOfOrigin": "US",
      "image": "apple-pie.png"
    }
  }
}

自己尝试一下 #1

创建一个名为nutritionCreate 的突变,创建一个新的Nutrition ActiveRecord。由于Nutrition类有很多属性,从这个gist中复制输入参数:https://gist.github.com/ShopifyEng/bc31c9fc0cc13b9d7be04368113b49d4

如果你想看解决方案,请查看nutrition_create.rb以及它的查询和响应

创建突变以更新现有的食物项目

使用rails g graphql:mutation foodUpdate 创建一个名为foodUpdate的新突变。在food_update类里面,我们需要添加更新的参数。ID ,这将是参数的一部分。

module Mutations
  class FoodUpdate < BaseMutation
    argument :id, ID, required: true
    argument :name, String, required: false
    argument :place_of_origin, String, required: false
    argument :image, String, required: false
  end
end

这里唯一需要的参数是 ID.我们需要用一个 **ID**来寻找一个现有的产品。这使得resolve方法能够找到食品项目并更新它。

接下来,我们写出解析方法和响应回馈:

module Mutations
  class FoodUpdate < BaseMutation
    argument :id, ID, required: true
    argument :name, String, required: false
    argument :place_of_origin, String, required: false
    argument :image, String, required: false

    type Types::FoodType

    def resolve(**args)
      food = Food.find(args[:id])
      food.update!(args)
      
      return food
    end
  end
end

让我们测试一下这个新的突变查询。我们把我们的新食物项目从苹果派改名为南瓜派。

mutation {
  foodUpdate(input: {
    id: 4,
    name: "Pumpkin Pie"
  }) {
    id
    name
  }
}
{
  "data": {
    "foodUpdate": {
      "id": "4",
      "name": "Pumpkin Pie"
    }
  }
}

自己尝试一下 #2

创建一个名为nutritionUpdate的突变,以更新一个现有的Nutrition ActiveRecord。

由于Nutrition类有很多属性,从这个gist中复制输入参数:https://gist.github.com/ShopifyEng/406065ab6c6ce68da6f3a2918ffbeaab。

如果你想看解决方案,请查看nutrition_update.rb和查询以及其查询和响应

创建突变以删除现有的食物项目

使用rails g graphql:mutation foodDelete ,创建一个名为foodDelete的新突变。food_delete.rb 中唯一需要的参数是ID:

module Mutations
  class FoodDelete < BaseMutation
    argument :id, ID, required: true
  end
end

接下来,我们需要添加返回类型和解析方法。为了简单起见,我们只使用Types::FoodType 作为响应:

module Mutations
  class FoodDelete < BaseMutation
    argument :id, ID, required: true

    type Types::FoodType

    def resolve(id:)
      food = Food.find(id)
      food.destroy!

      return food
    end
  end
end

让我们在GraphiQL中测试这个突变:

mutation {
  foodDelete(input: {
    id: 4
  }) {
    id
  }
}
{
  "data": {
    "foodDelete": {
      "id": "4"
    }
  }
}

自己尝试 #3

创建一个名为nutritionDelete的突变,删除一个现有的Nutrition ActiveRecord。与foodDelete类似,我们使用Types::NutritionType 作为响应。

如果你想看看这个解决方案,请查看nutrition_delete.rb以及它的查询和响应

我们已经到了本教程的结尾,我希望你喜欢创建突变来修改、创建或删除数据。

让我们回顾一下我们学到的东西

  1. 突变是在数据库中创建、修改或删除对象的查询。
  2. 为了生成一个突变,我们使用rails g graphql:mutation nameAction
  3. 一个解析方法为其字段(来自mutation_type.rb的food_create)获取数据,并返回一个响应。
  4. GraphQL服务器在其模式中每个字段只有一个解析方法。

GraphQL是一种强大的数据操作和查询语言,为API提供了很多灵活性。有时,在你的应用程序中实施GraphQL似乎非常令人生畏。我希望了解GraphQL的初学者系列能帮助你在个人项目中实施GraphQL,或说服你的工作采用GraphQL生态系统。

如果你想看第三部分的完成代码,请查看名为part-3-solution的分支。