以下是有关graphql-ruby的笔记(仅涉及查询部分)

因为工作需要使用graphql,所以我将公开我学习过程中记录的笔记。
这篇文章将使用一个叫做graphql-ruby的 gem,在发出数据获取请求并获取自己定义的数据类型的基础知识的部分进行记录。
本文相当于一个Hello World级别的简单介绍。

前提 tí)

    • ruby 2.5.1p57

 

    • rails 5.1.6.1

 

    • 上記の環境でrails newで動作確認用のrailsプロジェクトは作成済の状態

 

    ちなみにGraphQLについての知識はこの記事を書く前の時点でGraphQLという便利なインターフェースがあるらしい程度の知識

安装

安装

将以下内容添加到Gemfile中,并执行bundle install。

gem 'graphql'

生成GraphQL相关的基本文件

rails g graphql:install

接下来,Gemfile中会添加以下的gem,所以执行bundle install命令。

graphiql-rails

我們試試在這個狀態下進行運作確認。

请访问 http://localhost:3000//graphiql,将以下查询输入到最左侧的位置,并点击执行按钮。

{
  testField
}

如果得到了以下类似的结果,就表示成功。

{
  "data": {
    "testField": "Hello World!"
  }
}

关于模式(スキーマ)

对于上述查询,它在以下位置作出反应。据说这部分被称为模式。
在这里,每个查询项目(似乎被称为字段)的行为被指定。
例如,在下面自动生成的模式中,如果查询中指定了testField,将调用test_field方法,并将方法的返回值作为查询的结果返回。

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    # TODO: remove me
    field :test_field, String, null: false,
      description: "An example field added by the generator"

    def test_field
      "Hello World!"
    end
  end
end

明白了解到,query_type.rb定义了指定查询字段应返回什么。由于这次查询包含了test_field,所以将执行该类内的test_field,并返回”Hello World!”。

確認一下稍微改造一下。

添加一个字段到模式中,然后进行操作测试。

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    # TODO: remove me
    field :test_field, String, null: false,
      description: "An example field added by the generator"

    field :test_field2, String, null: false,                  # 追加
      description: "An example field added by the generator"  # 追加

    def test_field
      "Hello World!"
    end

    def test_field2     # 追加
      "test2"
    end
  end
end

请在 http://localhost:3000//graphiql 上发送以下查询。

{
  testField,
  testField2
}

如期返回了字段testField2的值”test2″。

{
  "data": {
    "testField": "Hello World!",
    "testField2": "test2"
  }
}

生成 GraphQL 对象

下一步尝试定义对象。
理解为一种所谓的类型的东西。

rails g graphql:object Post title:String rating:Int

执行此命令会生成以下文件

module Types
  class PostType < Types::BaseObject
    field :title, String, null: true
    field :rating, Integer, null: true
  end
end

在指定类型的查询中,修改模式以返回值。

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    field :post, PostType, null: true do  # ここでPostTypeを指定
      description "Find a post by ID"
    end

    def post    # ここでpostが指定された時に返却する値を設定
      {
        "title" => "test_title",
        "rating" => 3,
      }
    end
  end
end

投递下列查询。

{
  post {
    title
    rating
  }
}

当投掷时,会返回以下内容。

{
  "data": {
    "post": {
      "title": "test_title",
      "rating": 3
    }
  }
}

使得可以为类型指定参数。

我认为根据指定的id获取与id相关的值是常见的情况,所以将其改造为可以指定id。

首先,为了能够接收到id,请在类型中添加id。

module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false        # 追加
    field :title, String, null: true
    field :rating, Integer, null: true
  end
end

下一步是对模式进行修改,以便能够接收id。

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    field :post, PostType, null: true do
      description "Find a post by ID"
      argument :id, ID, required: true      # 追加
    end

    def post(id:)     # idを引数で受け取れるようにする
      {
        "id" => id,                     # idをそのまま返却
        "title" => "test_title_#{id}",  # 動作確認用にIDをtitleに含める
        "rating" => 3,
      }
    end
  end
end

用中文表达以下类似的模式

{
  post(id: 11) {
    id
    title
    rating
  }
}

然后将返回以下值。

{
  "data": {
    "post": {
      "id": "11",
      "title": "test_title_11",
      "rating": 3
    }
  }
}

这次在模式中返回的几乎是固定值的哈希,但实际上应该是根据这里的id调用某个获取过程的感觉。

如果发送一个没有指定ID的查询…

由于在架构中设置了’required: true’,所以会进行验证并产生错误。
为了确认,发送以下查询。

{
  post {
    id
    title
    rating
  }
}

返回值。果然,出现了错误。

{
  "errors": [
    {
      "message": "Field 'post' is missing required arguments: id",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "fields": [
        "query",
        "post"
      ]
    }
  ]
}

请参考

广告
将在 10 秒后关闭
bannerAds