{"id":47630,"date":"2023-05-12T06:17:49","date_gmt":"2024-01-15T20:01:30","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/"},"modified":"2024-04-30T03:45:45","modified_gmt":"2024-04-29T19:45:45","slug":"%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/","title":{"rendered":"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011"},"content":{"rendered":"<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/0-0.png\" alt=\"\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8 2018-07-02 0.16.29.png\" \/><\/div>\n<h2>\u9996\u5148<\/h2>\n<h3>\u7684 Chinese paraphrase for &#8220;\u76ee\u7684&#8221; could be &#8220;\u76ee\u6807&#8221; (m\u00f9 , which means &#8220;objective&#8221; or &#8220;goal&#8221; in English.<\/h3>\n<p>\u672c\u6587\u7684\u76ee\u7684\u662f\u603b\u7ed3\u9002\u7528\u4e8e\u521d\u5b66\u8005\u6216\u5373\u5c06\u5f00\u59cb\u5b66\u4e60GraphQL\u7684\u4eba\u6240\u9700\u8981\u4e86\u89e3\u7684\u4fe1\u606f\uff0c\u5e76\u63d0\u4f9b\u76f8\u5e94\u7d22\u5f15\u3002<\/p>\n<p>\u6211\u60f3\u8981\u5438\u5f15\u7684\u8bfb\u8005\u662f\u90a3\u4e9b\u60f3\u8981\u5f00\u59cb\u5b66\u4e60GraphQL\u6216\u8005\u521a\u521a\u5f00\u59cb\u5b66\u4e60\u7684\u4eba\u3002<\/p>\n<p>\u9700\u8981\u89e3\u91ca\u7684\u4e00\u4e2a\u80cc\u666f\u662f\uff0c\u4e3a\u4e86\u589e\u52a0\u57fa\u4e8eGraphQL\u7684API\u7684\u6570\u91cf\uff0c\u540c\u65f6\u8bf4\u660e\u5176\u5f15\u5165\/\u5b66\u4e60\u6210\u672c\u5e76\u4e0d\u7b97\u9ad8\u3002<\/p>\n<p>\u53e6\u5916\uff0c\u6211\u5728\u4e2a\u4eba\u4f7f\u7528\u7684Markdown\u7b14\u8bb0\u670d\u52a1Issus\uff08\u30a4\u30b7\u30e5\u30fc\u30ba\uff09\u4e2d\u6574\u7406\u4e86\u4f7f\u7528Graphql\u6240\u5f97\u5230\u7684\u4fe1\u606f\u3002<\/p>\n<h3>\u7b80\u8981\u6982\u8ff0<\/h3>\n<p>\u4eceGraphQL\u7684\u6982\u5ff5\u3001\u7279\u70b9\u548c\u4f18\u52bf\u8fd9\u4e2a\u89d2\u5ea6\u6765\u8ba8\u8bba\uff0c<br \/>\n\u8c08\u8bba\u8bf7\u6c42\/\u54cd\u5e94\u6d41\u7a0b\u3001\u67e5\u8be2\u3001\u67b6\u6784\u3001\u89e3\u6790\u3001\u7c7b\u578b\u3001\u6d4b\u8bd5\u3001\u6587\u4ef6\u5904\u7406\u548c\u9519\u8bef\u5904\u7406\u7b49\u5177\u4f53\u5b9e\u73b0\u7ec6\u8282\u3002<\/p>\n<p>\u6211\u4f1a\u7b80\u5355\u4ecb\u7ecd\u4e00\u4e0b\u3002<\/p>\n<p>\u5982\u679c\u60a8\u6709\u4efb\u4f55\u9700\u8981\u4fee\u6b63\u7684\u5185\u5bb9\uff0c\u6216\u8005\u6709\u66f4\u597d\u7684\u4fe1\u606f\uff0c\u656c\u8bf7\u63d0\u51fa\u7f16\u8f91\u8bf7\u6c42\u3002<\/p>\n<p>\u6ce8\u610f\uff01<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">graphql-ruby(\u304b\u3064Rails)\u3092\u30d9\u30fc\u30b9\u306b\u8a71\u3059\u305f\u3081\u4ed6Graphql\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u306f\u5f53\u3066\u306f\u307e\u3089\u306a\u3044\u8a71\u3082\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u9014\u4e2d\u56f3\u306b\u8d77\u3053\u3059\u306e\u3092\u8ae6\u3081\u3066\u624b\u66f8\u304d\u3057\u305f\u30e1\u30e2\u304c\u3042\u308a\u307e\u3059<\/ul>\n<\/li>\n<\/ul>\n<p>\u9577\u3044\u305e!!!<\/p>\n<h2>GraphQL\u6709\u4ec0\u4e48\u7528\u9014\uff1f<\/h2>\n<p>\u8fd9\u65b9\u9762\uff0c\u3053\u3093\u3074\u3085\u603b\u7ed3\u5f97\u5f88\u6e05\u695a\u6613\u61c2\u3002<br \/>\nGraphQL\u4e0d\u662fREST\u7684\u66ff\u4ee3\u54c1\uff5c\u3053\u3093\u3074\u3085\uff5cnote<\/p>\n<p>\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u62e9\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">API\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u675f\u306d\u3066\u52b9\u7387\u5316 = \u5404\u6240\u3067\u5fc5\u8981\u5341\u5206\u306a\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u8981\u6c42\u3067\u304d\u308b<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u30b9\u30ad\u30fc\u30de\u30d5\u30a1\u30fc\u30b9\u30c8\u958b\u767a<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u30de\u30a4\u30af\u30ed\u30b5\u30fc\u30d3\u30b9\u306eAPI\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4<\/ul>\n<\/li>\n<\/ul>\n<p>\u88cf\u5074\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8907\u6570\u6301\u3066\u305f\u308a\u3001\u4ed6\u306eRESTapi\u3092call\u3057\u305f\u308a<\/p>\n<p>\u9664\u6b64\u4e4b\u5916\uff0c<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">request parameters \/ response\u306b\u578b\u3092\u3064\u3051\u3089\u308c\u308b<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">RESTfulAPI\u306e\u9762\u5012\u306a\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u8a2d\u8a08\u304c\u4e0d\u8981\u306b\u306a\u308b<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u30b5\u30fc\u30d0\u30fc\u306e\u958b\u767a\u3092\u5f85\u305f\u306a\u304f\u3066\u3044\u3044<\/ul>\n<p>\u6211\u8ba4\u4e3a\u4e5f\u6709\u7c7b\u4f3c\u7684\u597d\u5904\u3002<\/p>\n<p>\u53e6\u5916\uff0c\u5728\u89c6\u9891\u4e2d\uff0c\u4f7f\u7528\u5168\u6808\u6559\u7a0b\u5b66\u4e60GraphQL\u57fa\u7840\u975e\u5e38\u6613\u61c2\uff0c\u5c06\u6982\u5ff5\u6e05\u6670\u5730\u603b\u7ed3\u4e86\u8d77\u6765\u3002<\/p>\n<blockquote><p>GraphQL\u7684\u6838\u5fc3\u5728\u4e8e\u652f\u6301\u58f0\u660e\u5f0f\u6570\u636e\u83b7\u53d6\uff0c\u5ba2\u6237\u7aef\u53ef\u4ee5\u660e\u786e\u6307\u5b9a\u9700\u8981\u4eceAPI\u4e2d\u83b7\u53d6\u54ea\u4e9b\u6570\u636e\u3002\u4e0e\u8fd4\u56de\u56fa\u5b9a\u6570\u636e\u7ed3\u6784\u7684\u591a\u4e2a\u7ec8\u7aef\u4e0d\u540c\uff0cGraphQL\u670d\u52a1\u5668\u4ec5\u66b4\u9732\u4e00\u4e2a\u7ec8\u7aef\uff0c\u5e76\u51c6\u786e\u5730\u56de\u5e94\u5ba2\u6237\u7aef\u6240\u8bf7\u6c42\u7684\u6570\u636e\u3002<\/p><\/blockquote>\n<p>\u6839\u636e\u8fd9\u91cc\u6240\u8ff0\uff0c\u6211\u4eec\u5f3a\u70c8\u503e\u5411\u4e8e\u5728\u6bcf\u4e2a\u4eba\u81ea\u5df1\u5b9a\u4e49\u6240\u9700\u7684\u54cd\u5e94\u5e76\u4f7f\u7528\u5355\u4e2aAPI\u8c03\u7528\u6765\u63a5\u6536\u76f8\u5e94\u7684\u54cd\u5e94\u3002\u80cc\u666f\u662f\u7531\u4e8e\u79fb\u52a8\u5e94\u7528\u7684\u5174\u8d77\u5bfc\u81f4API\u7684\u591a\u6837\u5316\uff0c\u4ee5\u53ca\u6240\u9700\u7684\u54cd\u5e94\u9891\u7e41\u53d8\u5316\uff0c\u5bfc\u81f4\u6bcf\u6b21\u90fd\u9700\u8981\u670d\u52a1\u5668\u8fdb\u884c\u76f8\u5e94\u7684\u9002\u914d\uff0c\u8fd9\u4f7f\u5f97\u5f00\u53d1\u901f\u5ea6\u65e0\u6cd5\u88ab\u4fdd\u6301\u3002<\/p>\n<p>GraphQL\u9002\u7528\u4e8e\u54ea\u4e9b\u65b9\u9762\u5462\uff1f\u53ef\u4ee5\u53c2\u8003k0kubun\u7684\u535a\u5ba2\u4e2d\u5173\u4e8e\u5b83\u4e0eRESTful API\u7684\u51b7\u9759\u6bd4\u8f83\u3002<\/p>\n<h2>\u8bbe\u7f6e\uff01<\/h2>\n<p>\u8bf7\u5b9e\u9645\u5f00\u53d1\u7684\u4eba\u8df3\u8fc7\u6b64\u6b65\u9aa4\u3002<\/p>\n<p>\u8fd9\u662f\u5728Rails\u9879\u76ee\u4e2d\u5f15\u5165\u7684\u524d\u63d0\u3002<br \/>\n\uff08\u4f1a\u6d89\u53ca\u5230routes\u7b49\u5185\u5bb9\uff0c\u4f46\u5982\u679c\u662fsinatra\u7b49\u60c5\u51b5\uff0c\u8bf7\u9002\u5f53\u5730\u8fdb\u884c\u66ff\u6362\uff09<\/p>\n<h3>\u4f7f\u7528gem\u5b89\u88c5<\/h3>\n<p>\u9996\u5148\uff0c\u6211\u4eec\u5c06\u5f15\u5165GraphQL\u4ee5\u53ca\u53ef\u4ee5\u63d0\u4f9b\u6d4b\u8bd5\u5ba2\u6237\u7aef\u754c\u9762\u7684graphiql-rails\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"n\">gem<\/span> <span class=\"s1\">'graphql'<\/span>\r\n<span class=\"n\">group<\/span> <span class=\"ss\">:development<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">gem<\/span> <span class=\"s1\">'graphiql-rails'<\/span> <span class=\"c1\"># graphql\u306e\u30c6\u30b9\u30c8\u753b\u9762\u3067\u3059\u3002\u5f8c\u8ff0<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>bundle <span class=\"nb\">install\r\n<\/span>rails generate graphql:install\r\n<\/code><\/pre>\n<h3>\u5728routes\u4e2d\u6dfb\u52a0<\/h3>\n<p>\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u5c06\u51c6\u5907\u7528\u4e8e\u6267\u884cGraphQL\u7684\u8def\u5f84\u548c\u6d4b\u8bd5\u5ba2\u6237\u7aef\u7684\u8def\u5f84\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">if<\/span> <span class=\"no\">Rails<\/span><span class=\"p\">.<\/span><span class=\"nf\">env<\/span><span class=\"p\">.<\/span><span class=\"nf\">development?<\/span>\r\n  <span class=\"n\">mount<\/span> <span class=\"no\">GraphiQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Rails<\/span><span class=\"o\">::<\/span><span class=\"no\">Engine<\/span><span class=\"p\">,<\/span> <span class=\"ss\">at: <\/span><span class=\"s2\">\"\/graphiql\"<\/span><span class=\"p\">,<\/span> <span class=\"ss\">graphql_path: <\/span><span class=\"s2\">\"\/api\/v1\/graphql\"<\/span>\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"c1\"># \u9069\u5b9c\u597d\u304d\u306apath\u306b\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044. \u4eca\u56de\u306e\u30b1\u30fc\u30b9\u3067\u306f \/api\/v1\/graphql\u3092\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306b\u3057\u3066\u3044\u307e\u3059<\/span>\r\n<span class=\"n\">namespace<\/span> <span class=\"ss\">:api<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"ss\">format: <\/span><span class=\"s1\">'json'<\/span> <span class=\"p\">}<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">namespace<\/span> <span class=\"ss\">:v1<\/span> <span class=\"k\">do<\/span>\r\n    <span class=\"n\">post<\/span> <span class=\"s2\">\"\/graphql\"<\/span><span class=\"p\">,<\/span> <span class=\"ss\">to: <\/span><span class=\"s2\">\"graphql#execute\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u73b0\u5728\uff0c\u5b8c\u6210\u4e86<\/p>\n<p>POST \/api\/v1\/graphql\u3067graphql\u3092\u5b9f\u884c\u3067\u304d\u308b\u3088\u3046\u306b\u3001<\/p>\n<p>GET \/graphiql \u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u3068\u3001grapqhl\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b<\/p>\n<p>\u53d8\u4e86\u3002<\/p>\n<p>\u6d4b\u8bd5\u5ba2\u6237\u7684\u60c5\u51b5\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/38-0.png\" alt=\"test_client.png\" \/><\/div>\n<p>\u6211\u4f1a\u7ee7\u7eed\u4f7f\u7528\u8fd9\u4e2a\u67e5\u8be2\u6765\u901a\u8fc7id\u83b7\u53d6\u4e00\u4e2aEvent\u3002\u610f\u601d\u662f\u83b7\u53d6Event.find(id)\uff0c\u5e76\u83b7\u53d6\u5176id\u548csubject\u3002<\/p>\n<h2>GraphQL\u5982\u4f55\u5de5\u4f5c\uff1f<\/h2>\n<p>\u5982\u679c\u4f60\u5df2\u7ecf\u4f7f\u7528GraphQL\u8fdb\u884c\u4e86\u5b9e\u73b0\uff0c\u4f60\u53ef\u4ee5\u8df3\u8fc7\u8fd9\u90e8\u5206\u7684\u57fa\u672c\u590d\u4e60\u3002<\/p>\n<h3>\u901a\u4fe1\u7f16\u7801<\/h3>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/43-0.png\" alt=\"flow.png\" \/><\/div>\n<p>\u4ee5\u4e0b\u4e3a\u5927\u81f4\u6d41\u7a0b<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u5728\u5ba2\u6237\u7aef\u4e0a\u6784\u5efa\u67e5\u8be2\uff08\u548c\u53d8\u91cf\uff09\uff0c\u7136\u540e\u901a\u8fc7POST\u8bf7\u6c42\u5c06\u5176\u53d1\u9001\u5230\u552f\u4e00\u7684\u7ec8\u70b9\u3002<\/ol>\n<\/li>\n<\/ol>\n<p>\u5728\u5ba2\u6237\u7aef\u4e0a\u6784\u5efa\u67e5\u8be2\u548c\u53d8\u91cf\u662f\u4e3b\u8981\u7684\u5de5\u4f5c\uff0c\u5373\u4f7f\u662f\u7528\u4e8e\u6570\u636e\u83b7\u53d6\u7684\u8bf7\u6c42\u4e5f\u4f1a\u4f7f\u7528POST\u3002<\/p>\n<p>\u670d\u52a1\u5668\u7aef\u63a5\u6536\u5230\u8be5\u8bf7\u6c42\u540e\uff0c\u89e3\u6790\u67e5\u8be2\uff08\u548c\u53d8\u91cf\uff09\u5e76\u751f\u6210\u54cd\u5e94\u3002<\/p>\n<p>\u9884\u5148\u5b9a\u4e49\u4e86\u7528\u4e8e\u8fd4\u56de\u54ea\u4e2a\u5b57\u6bb5\u4ee5\u53ca\u8fd4\u56de\u4ec0\u4e48\u6837\u7684\u503c\u7684\u6a21\u5f0f\u4f5c\u4e3a\u67b6\u6784\u3002<\/p>\n<p>\u5b9e\u73b0\u8fd9\u4e2a\u67b6\u6784\u662f\u670d\u52a1\u5668\u7aef\u7684\u4e3b\u8981\u5de5\u4f5c\u3002<\/p>\n<p>\u662f\u7684\u3002<\/p>\n<p>\u5728Rails\u4e2d\uff0c\u53ef\u4ee5\u6839\u636e\u4ee5\u4e0b\u65b9\u5f0f\u67e5\u770b\u5b9e\u9645\u65e5\u5fd7\u548c\u54cd\u5e94\u3002<\/p>\n<pre class=\"post-pre\"><code>Started POST \"\/api\/v1\/graphql\" for ::1 at 2018-07-01 09:22:51 +0900\r\nProcessing by Api::V1::GraphqlController#execute as JSON\r\n  Parameters: \r\n    {\r\n      \"query\"=&gt;\"query Event($id:ID = \\\"\\\") {\\n  event {\\n    id\\n    subject\\n  }\\n}\", # \u7279\u6b8a\u306aGraphql\u69cb\u6587\u3092string\u3067\u9001\u4fe1\r\n      \"variables\"=&gt;{\"id\"=&gt;5},   # rocket hash\u306b\u306a\u3063\u3066\u308b\r\n      \"operationName\"=&gt;\"Event\", # operationName\u306fquery\u306e\u76f4\u5f8c\u306b\u4ed8\u3051\u3066\u3044\u308b\u6587\u5b57\u5217\u3067\u3001\u30b5\u30fc\u30d0\u30fc\u5074\u3067\u30ed\u30ae\u30f3\u30b0\u306b\u7528\u3044\u308b\u3002\u7701\u7565\u53ef\u80fd\u3060\u304c\u3042\u3063\u305f\u307b\u3046\u304c\u3044\u3044\r\n      \u201cgraphql\"=&gt;{\r\n        \"query\"=&gt;\"query Event($id:ID = \\\"\\\") {\\n  event {\\n    id\\n    subject\\n  }\\n}\", \r\n        \"variables\"=&gt;{\"id\"=&gt;5}, \r\n        \u201coperationName\"=&gt;\"Event\"\r\n      }\r\n    }\r\n<\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/49-0.png\" alt=\"response.png\" \/><\/div>\n<p>\u73b0\u5728\u6211\u4eec\u6765\u770b\u770b\u4ece\u5ba2\u6237\u7aef\u7684\u89d2\u5ea6\u6765\u770b\uff0c\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u7684\u5904\u7406\u8fc7\u7a0b\u3002<\/p>\n<h3>\u5ba2\u6237\u7f16\u8f91<\/h3>\n<p>\u5ba2\u6237\u7aef\u7684\u5de5\u4f5c\u662f<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u6784\u5efa\u67e5\u8be2\u5e76\u5411\u7ec8\u7aef\u53d1\u9001\u8bf7\u6c42\uff0c<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u68c0\u67e5\u54cd\u5e94\u5185\u5bb9\uff0c\u82e5\u5b58\u5728\u9519\u8bef\u5219\u8fdb\u884c\u9519\u8bef\u5904\u7406\uff0c<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\u57fa\u4e8e\u63a5\u6536\u5230\u7684\u54cd\u5e94\u6570\u636e\u8fdb\u884c\u7ed8\u56fe\u6216\u5176\u4ed6\u64cd\u4f5c\uff08\u6b64\u5904\u7701\u7565\uff09\u3002<\/ol>\n<p>\u9996\u5148\uff0c\u8ba9\u6211\u4eec\u4ece\u7b2c\u4e00\u4e2a\u5f00\u59cb\u770b\u3002<\/p>\n<h4>\u7ec4\u88c5\u67e5\u8be2\u5e76\u5411\u7ec8\u7aef\u53d1\u9001\u8bf7\u6c42\u3002<\/h4>\n<p>\u53d1\u9001\u7ed9GraphQL\u7684\u53c2\u6570\u6709\u4e24\u4e2a\u3002\u4e00\u4e2a\u662f\u67e5\u8be2 (query)\uff0c\u53e6\u4e00\u4e2a\u662f\u8868\u793a\u8981\u5d4c\u5165\u67e5\u8be2\u7684\u503c\u7684\u53d8\u91cf (variables)\u3002<\/p>\n<p>\u67e5\u8be2\u662f\u4ee5JSON\u5f62\u5f0f\u5448\u73b0\u7684\uff0c\u4f46\u662f\u5b83\u6709\u81ea\u5df1\u72ec\u7279\u7684\u8bed\u6cd5\uff0c\u9700\u8981\u5927\u81f4\u8bb0\u4f4f\u5b83\u7684\u7ed3\u6784\u3002<\/p>\n<p>\u6839\u636e\u4ee5\u4e0b\u7684\u67e5\u8be2\u548c\u53d8\u91cf\u6765\u67e5\u770b\u6784\u6210\u8981\u7d20\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">query<\/span> <span class=\"n\">Event<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$id<\/span><span class=\"p\">:<\/span><span class=\"nb\">ID<\/span> <span class=\"p\">=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">event<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">id<\/span>\r\n    <span class=\"n\">subject<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span> <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">5<\/span> <span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/61-0.jpeg\" alt=\"image_from_ios-1.jpg\" \/><\/div>\n<p>\u8fd9\u6837\u7ec4\u88c5\u7684\u67e5\u8be2\u548c\u53d8\u91cf\u5c06\u59cb\u7ec8\u4ee5POST\u65b9\u6cd5\u4f5c\u4e3a\u8bf7\u6c42\u53d1\u9001\u5230\u552f\u4e00\u7684\u7ec8\u7aef\u70b9\u3002<\/p>\n<p>\u8fd9\u4e5f\u662f GraphQL \u7684\u7279\u70b9\uff0c\u901a\u8fc7\u5b83\uff0c\u5ba2\u6237\u7aef\u53ef\u4ee5\u5728\u6bcf\u4e2a\u77ac\u95f4\u901a\u8fc7\u4e00\u6b21 API \u8c03\u7528\u83b7\u53d6\u6240\u9700\u7684\u54cd\u5e94\uff0c\u800c\u65e0\u9700\u8003\u8651\u7ec8\u7aef\u70b9\u8bbe\u8ba1\u7b49\u95ee\u9898\u3002<\/p>\n<h4>\u6839\u636e\u54cd\u5e94\u5185\u5bb9\u8fdb\u884c\u68c0\u67e5\uff0c\u5982\u679c\u6709\u9519\u8bef\u5219\u8fdb\u884c\u9519\u8bef\u5904\u7406\u3002<\/h4>\n<p>\u5373\u4f7fGraphql\u8bf7\u6c42\u5b58\u5728\u9519\u8bef\uff0c\u5b83\u4e5f\u4f1a\u59cb\u7ec8\u4ee5\u72b6\u6001\u7801200\u8fdb\u884c\u8fd4\u56de\u3002<br \/>\n\uff08\u56e0\u4e3aGraphql\u53ef\u4ee5\u540c\u65f6\u53d1\u9001\u591a\u4e2a\u67e5\u8be2\uff0c\u56e0\u6b64\u65e0\u6cd5\u5c06\u5176\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5931\u8d25\u7684\u60c5\u51b5\u8868\u793a\u4e3a\u72b6\u6001\u7801\u3002\uff09<\/p>\n<p>\u53ea\u9700\u4e00\u79cd\u9009\u62e9\uff1a<br \/>\n\u4f5c\u4e3a\u66ff\u4ee3\uff0c\u5982\u679c\u53d1\u751f\u9519\u8bef\uff0c\u9700\u8981\u5728\u54cd\u5e94\u4e2d\u5305\u542b\u9519\u8bef\u5185\u5bb9\uff08errors\uff09\uff0c\u6839\u636e\u5176\u6709\u65e0\u8fdb\u884c\u9519\u8bef\u5904\u7406\u3002<\/p>\n<p>\u4f7f\u7528JS\u7684\u4f2a\u4ee3\u7801\u6765\u8ffd\u8e2a\u5904\u7406\u8fc7\u7a0b\uff0c\u5927\u81f4\u5448\u73b0\u5982\u4e0b\u56fe\u50cf\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">API<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">api<\/span><span class=\"dl\">'<\/span> <span class=\"c1\">\/\/ \u4f55\u3089\u304b\u306ehttp\u30ea\u30af\u30a8\u30b9\u30c8\u30e9\u30a4\u30d6\u30e9\u30ea<\/span>\r\n\r\n<span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">API<\/span><span class=\"p\">.<\/span><span class=\"nx\">post<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">\/api\/v1\/graphql<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">query<\/span><span class=\"p\">:<\/span> <span class=\"nx\">query<\/span><span class=\"p\">,<\/span> <span class=\"na\">variables<\/span><span class=\"p\">:<\/span> <span class=\"nx\">variables<\/span> <span class=\"p\">})<\/span>\r\n\r\n<span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">errors<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"c1\">\/\/ do error handling<\/span>\r\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nx\">log<\/span><span class=\"p\">(<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">errors<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"kd\">const<\/span> <span class=\"nx\">event<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">event<\/span>\r\n<span class=\"c1\">\/\/ do something with response<\/span>\r\n<\/code><\/pre>\n<p>\u7136\u800c\uff0c\u5b9e\u9645\u4e0a\uff0c\u6839\u636e\u6bcf\u4e2a\u5ba2\u6237\u7aef\u7684\u9700\u6c42\uff0c\u4f7f\u7528\u76f8\u5e94\u7684GraphQL\u5ba2\u6237\u7aef\u5e93\u8f83\u4e3a\u5e38\u89c1\u3002<br \/>\n\u5ba2\u6237\u7aef\u5e93\u652f\u6301\u6784\u5efa\u81ea\u5b9a\u4e49\u67e5\u8be2\u8bed\u53e5\u548cjson\u53d8\u91cf\uff0c\u5e76\u6839\u636e\u54cd\u5e94\u6765\u5904\u7406\u9519\u8bef\u3002<\/p>\n<p>\u5ba2\u6237\u7aef\u5e93\u6709\u4e00\u4e9b\u4e3b\u6d41\u7684\u9009\u62e9\uff0c\u4f8b\u5982Facebook\u5f00\u53d1\u7684Relay\uff08\u5728JavaScript\u4e2d\uff09\u548c\u65e5\u6e10\u6d41\u884c\u7684Apollo\u3002\u5b98\u65b9\u4e5f\u63a8\u8350\u4e86\u4e00\u4e9b\u9002\u7528\u4e8eJavaScript\u7684\u5ba2\u6237\u7aef\u5e93\u3002\u540c\u65f6\uff0c\u8fd8\u6709\u9002\u7528\u4e8eiOS\u548cAndroid\u7684\u5ba2\u6237\u7aef\u5e93\u53ef\u4f9b\u9009\u62e9\u3002<\/p>\n<p>\u6211\u5c06\u5c55\u793a\u5728JavaScript\u4e2d\u7684\u4f2a\u4ee3\u7801\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install <\/span>apollo-boost graphql-tag graphql <span class=\"nt\">--save<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"k\">import<\/span> <span class=\"nx\">ApolloClient<\/span> <span class=\"o\">=<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">apollo-boost<\/span><span class=\"dl\">'<\/span> <span class=\"c1\">\/\/ \u4fbf\u5229\u306a\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3092\u52a0\u3048\u305fapollo client<\/span>\r\n<span class=\"kd\">const<\/span> <span class=\"nx\">client<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nx\">ApolloClient<\/span><span class=\"p\">({<\/span>\r\n    <span class=\"na\">url<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">api\/v1\/graphql<\/span><span class=\"dl\">'<\/span>\r\n<span class=\"p\">})<\/span>\r\n\r\n<span class=\"k\">import<\/span> <span class=\"nx\">gql<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">graphql-tag<\/span><span class=\"dl\">'<\/span>\r\n\r\n<span class=\"nx\">client<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">({<\/span>\r\n    <span class=\"na\">query<\/span><span class=\"p\">:<\/span> <span class=\"nx\">gql<\/span><span class=\"s2\">`\r\n        query Event($id:ID!) {\r\n            event(id: $id) {\r\n                id\r\n                subject\r\n            }\r\n        }\r\n    `<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"na\">variables<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"mi\">1<\/span>\r\n    <span class=\"p\">}<\/span>\r\n<span class=\"p\">})<\/span>\r\n    <span class=\"p\">.<\/span><span class=\"nx\">then<\/span><span class=\"p\">((<\/span><span class=\"nx\">response<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"kd\">const<\/span> <span class=\"nx\">event<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">event<\/span>\r\n        <span class=\"c1\">\/\/ do something...<\/span>\r\n\r\n    <span class=\"c1\">\/\/ response\u306berrors\u304c\u3042\u308c\u3070throw\u3057\u3066\u304f\u308c\u308b<\/span>\r\n    <span class=\"p\">}).<\/span><span class=\"k\">catch<\/span><span class=\"p\">((<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"c1\">\/\/ do something<\/span>\r\n    <span class=\"p\">})<\/span>\r\n<\/code><\/pre>\n<p>\u6b64\u5916\uff0c\u9488\u5bf9js\uff0c\u6bcf\u4e2a\u6846\u67b6\u90fd\u6709\u76f8\u5e94\u7684\u5e93\uff0c\u5efa\u8bae\u5c06\u5b83\u4eec\u7ed3\u5408\u8d77\u6765\u4f7f\u7528\u3002<\/p>\n<p>\u4f8b\u5982\uff0c\u5982\u679c\u60a8\u4f7f\u7528Vue.js\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528https:\/\/github.com\/Akryum\/vue-apollo\u3002<br \/>\n\u7531\u4e8e\u5ba2\u6237\u7aef\u7684\u5177\u4f53\u5b9e\u73b0\u56e0\u5ba2\u6237\u7aef\u800c\u5f02\uff0c\u56e0\u6b64\u6211\u5c06\u5728\u53e6\u4e00\u7bc7\u6587\u7ae0\u4e2d\u63d0\u4f9b\u5173\u4e8eVue.js\u7684\u5185\u5bb9\u3002<\/p>\n<h4>\u603b\u7ed3<\/h4>\n<p>\u4ee5\u4e0b\u662f\u5ba2\u6237\u7aef\u7684\u5de5\u4f5c\u5185\u5bb9<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u6839\u636e\u67e5\u8be2\u6784\u5efa\u8bf7\u6c42\u5e76\u53d1\u9001\u5230\u7ec8\u7aef<\/ol>\n<\/li>\n<\/ol>\n<p>\u6784\u5efa\u67e5\u8be2\u548c\u53d8\u91cf\uff0c<br \/>\n\u53d1\u9001\u5230\u5355\u4e00\u7ec8\u7aef\u8fdb\u884cPOST\u8bf7\u6c42\u3002<\/p>\n<p>\u901a\u8fc7\u68c0\u67e5\u54cd\u5e94\u5185\u5bb9\uff0c\u8fdb\u884c\u9519\u8bef\u5904\u7406<\/p>\n<p>\u59cb\u7ec8\u8fd4\u56de200\u3002\u5982\u679c\u6709\u9519\u8bef\uff0c\u54cd\u5e94\u4e2d\u4f1a\u6709errors\u5b57\u6bb5\uff0c\u901a\u8fc7\u68c0\u67e5\u662f\u5426\u5b58\u5728\u8be5\u5b57\u6bb5\u6765\u8fdb\u884c\u5904\u7406\u3002<br \/>\n\u5982\u679c\u4f7f\u7528\u5ba2\u6237\u7aef\u5e93\uff0c\u53ef\u4ee5\u8d1f\u8d23\u6784\u5efa\u67e5\u8be2\u548c\u53d8\u91cf\uff0c\u5e76\u8fdb\u884c\u9519\u8bef\u5904\u7406\u3002<\/p>\n<p>\u7136\u540e\u6839\u636e\u63a5\u6536\u5230\u7684\u54cd\u5e94\u6570\u636e\u8fdb\u884c\u6e32\u67d3\u6216\u5176\u4ed6\u64cd\u4f5c\u3002<\/p>\n<h3>\u670d\u52a1\u5668\u7f16\u7a0b<\/h3>\n<p>\u670d\u52a1\u5668\u7684\u5de5\u4f5c\u662f<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u53d7\u3051\u53d6\u3063\u305fquery, variables\u3092\u89e3\u91c8\u3057<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">response\u3092\u8fd4\u3059<\/ul>\n<p>\u662f\u7684\u3002<\/p>\n<p>\u56de\u5e94\u90e8\u5206\u5f88\u7b80\u5355\u3002\u4f60\u51e0\u4e4e\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u901a\u8fc7 &#8220;rails generate graphql:install&#8221; \u81ea\u52a8\u751f\u6210\u7684graphql_controller\u6765\u5904\u7406\u3002<\/p>\n<pre class=\"post-pre\"><code>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">Api::V1::GraphqlController<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">Api<\/span><span class=\"o\">::<\/span><span class=\"no\">V1<\/span><span class=\"o\">::<\/span><span class=\"no\">BaseController<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># \u7701\u7565<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># POST \/api\/v1\/graphql<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">execute<\/span>\r\n    <span class=\"c1\"># ensure_hash\u306e\u5b9f\u88c5\u306f\u3053\u306e\u771f\u4e0b\u306b\u81ea\u52d5\u751f\u6210\u3055\u308c\u3066\u3044\u307e\u3059\u304c\u624b\u3092\u5165\u308c\u308b\u3053\u3068\u306f\u5c11\u306a\u3044\u306e\u3067\u7701\u7565<\/span>\r\n    <span class=\"n\">variables<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ensure_hash<\/span><span class=\"p\">(<\/span><span class=\"n\">params<\/span><span class=\"p\">[<\/span><span class=\"ss\">:variables<\/span><span class=\"p\">])<\/span>\r\n    <span class=\"n\">query<\/span>     <span class=\"o\">=<\/span> <span class=\"n\">params<\/span><span class=\"p\">[<\/span><span class=\"ss\">:query<\/span><span class=\"p\">]<\/span>\r\n\r\n    <span class=\"c1\"># OperationName\u306f\u30ed\u30ae\u30f3\u30b0\u3067\u4f7f\u3046<\/span>\r\n    <span class=\"n\">operation_name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">params<\/span><span class=\"p\">[<\/span><span class=\"ss\">:operationName<\/span><span class=\"p\">]<\/span>\r\n\r\n    <span class=\"c1\"># \u5f8c\u8ff0. \u306a\u304f\u3066\u3082\u3044\u3044<\/span>\r\n    <span class=\"n\">context<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span> <span class=\"ss\">current_user: <\/span><span class=\"n\">current_user<\/span> <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"c1\"># MySchema\u306f\u3001\u5f8c\u8ff0\u3059\u308bGraphql\u306e\u5b9f\u4f53\u3068\u306a\u308bclass\u3067\u3059\u3002<\/span>\r\n    <span class=\"c1\"># execute\u3059\u308b\u3068query, variables\u3092\u3082\u3068\u306bresponse\u3068\u306a\u308bhash\u3092\u8fd4\u3057\u307e\u3059<\/span>\r\n    <span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"no\">MySchema<\/span><span class=\"p\">.<\/span><span class=\"nf\">execute<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">query<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">variables: <\/span><span class=\"n\">variables<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">context: <\/span><span class=\"n\">context<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">operation_name: <\/span><span class=\"n\">operation_name<\/span>\r\n    <span class=\"p\">)<\/span>\r\n\r\n    <span class=\"n\">render<\/span> <span class=\"ss\">json: <\/span><span class=\"n\">result<\/span> <span class=\"c1\"># hash\u304c\u8fd4\u308b\u306e\u3067\u3001\u3042\u3068\u306f response json: result \u3059\u308b\u3060\u3051\u3002<\/span>\r\n  <span class=\"k\">end<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># \u7701\u7565<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>Graphql\u7684Schema\u8d1f\u8d23\u89e3\u91ca\u63a5\u6536\u5230\u7684query\u548cvariables\u3002<br \/>\n\u670d\u52a1\u5668\u5de5\u7a0b\u5e08\u7684\u5de5\u4f5c\u662f\u5728Schema\u4e2d\u5b9a\u4e49&#8221;\u5f53\u6536\u5230\u8be5Field\u65f6\u8fd4\u56de\u8fd9\u4e9b\u6570\u636e&#8221;\u3002<\/p>\n<p>\u8fd9\u4e2a\u90e8\u5206\u4ece2018\/05\/18\u53d1\u5e03\u7684v1.8.0\u5f00\u59cb\u6709\u4e86\u5f88\u5927\u7684\u6539\u53d8\uff0c\u5e76\u4e14\u53d8\u4e3a\u4e86\u57fa\u4e8e\u7c7b\u7684\u5b9e\u73b0\u65b9\u5f0f\u3002<br \/>\n\u6709\u5173\u57fa\u4e8e\u7c7b\u7684\u5b9e\u73b0\u7684\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728\u5b98\u65b9\u6587\u6863\u4e2d\u627e\u5230\u3002<\/p>\n<p>\u867d\u7136\u5982\u6b64\uff0c\u7531\u4e8e\u5728\u7f51\u7edc\u4e0a\u53ef\u4ee5\u627e\u5230\u5927\u591a\u6570\u662f\u57fa\u4e8e\u65e7\u6709\u65b9\u5f0f\u7684\u6587\u7ae0\uff0c\u56e0\u6b64\u672c\u6587\u5c06\u91c7\u7528\u57fa\u4e8e\u7c7b\u7684\u5199\u4f5c\u65b9\u5f0f\u3002<\/p>\n<p>\u7ec8\u4e8e\u6765\u5230\u672c\u6587\u7684\u6b63\u6587\u90e8\u5206\u4e86\u3002<\/p>\n<h2>\u5b9e\u65bdSchema<\/h2>\n<h3>\u4ee5\u4e0b\u662fGraphQL\u53ef\u4ee5\u5904\u7406\u7684\u4e09\u79cd\u8bf7\u6c42\u3002<\/h3>\n<p>GraphQL\u6709\u4e09\u79cd\u7c7b\u578b\u7684\u8bf7\u6c42\u5b58\u5728\u3002<\/p>\n<p>query<\/p>\n<p>\u53c2\u7167\u7cfb Read<\/p>\n<p>mutation<\/p>\n<p>\u66f4\u65b0\u7cfb Create Update Delete<\/p>\n<p>subscription<\/p>\n<p>websocket\u306e\u3088\u3046\u306b\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u30b5\u30fc\u30d0\u30fc\u3092\u30aa\u30d6\u30b6\u30fc\u30d6\u3059\u308b\u4ed5\u7d44\u307f\u3092\u63d0\u4f9b\u3057\u307e\u3059<br \/>\n\u3061\u3087\u3063\u3068\u307e\u3060\u4f7f\u3063\u305f\u3053\u3068\u304c\u306a\u3044\u306e\u3067\u7701\u7565!<br \/>\n&gt; Subscriptions allow GraphQL clients to observe specific events and receive updates from the server when those events occur. This supports live updates, such as websocket pushes. Subscriptions introduce several new concepts:<\/p>\n<p>\u9996\u5148\uff0c\u4e3a\u4e86\u7406\u89e3GraphQL\u7684\u57fa\u7840\u77e5\u8bc6\uff0c\u6211\u4eec\u5c06\u770b\u4e00\u4e0bQuery\u3002<\/p>\n<h2>\u67e5\u8be2\u7f16\u8f91<\/h2>\n<h3>GraphQL-Ruby\u7684\u670d\u52a1\u5668\u7aef\u6574\u4f53\u67b6\u6784\u3002<\/h3>\n<p>\u9996\u5148\u6211\u4eec\u6765\u770b\u4e00\u4e0b\u5728graphql-ruby\u4e0b\u7684\u5904\u7406\u6d41\u7a0b\u3002<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>GraphqlController#execute<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>MySchema.execute<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u5728execute\u4e2d\u68c0\u89c6\u6bcf\u4e2aTypes::QueryType\u7684field<\/ol>\n<\/li>\n<\/ol>\n<p>\u6307\u5b9afield\u503c\u7684\u7c7b\u578b<br \/>\n\u63cf\u8ff0\u5982\u4f55\u83b7\u53d6\u4e0efield\u503c\u76f8\u5bf9\u5e94\u7684\u5185\u5bb9\uff0c\u4f5c\u4e3aresolve\u5904\u7406\u7a0b\u5e8f<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/98-0.png\" alt=\"server_folow.png\" \/><\/div>\n<p>\u5b9a\u4e49\u201c\u5f53\u8fd9\u4e2a\u5b57\u6bb5\u51fa\u73b0\u65f6\u8fd4\u56de\u8fd9\u4e2a\u6570\u636e\u201d\u5230Schema\u4e2d\uff0c\u5c31\u662f\u5b9e\u65bd\u7b2c\u4e09\u4e2a\u7684\u610f\u601d\u3002<\/p>\n<h3>\u9886\u57df\u7684\u57fa\u672c\u5b9e\u65bd\u65b9\u5f0f<\/h3>\n<p>\u9996\u5148\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\u3002<\/p>\n<p>\u8fd9\u91cc\u8bb0\u5f55\u4e86\u57fa\u672c\u7684\u5b9e\u73b0\uff0c\u4f46\u5176\u4e2d\u4e5f\u5305\u542b\u4e86\u65e0\u6cd5\u5728\u57fa\u4e8e\u7c7b\u7684\u5b9e\u73b0\u4e2d\u4f7f\u7528\u7684\u63cf\u8ff0\u3002<\/p>\n<p>\u7531\u4e8e\u53ef\u4ee5\u4f20\u9012\u4e30\u5bcc\u7684\u9009\u9879\uff0c\u67e5\u770b gems\/graphql-1.8.1\/lib\/graphql\/schema\/field.rb \u53ef\u4ee5\u83b7\u5f97\u51c6\u786e\u7684\u9009\u9879\uff0c\u8fd9\u6837\u66f4\u4e0d\u5bb9\u6613\u51fa\u9519\u3002<\/p>\n<p>&#8220;field\u7684\u5b9e\u73b0\u662f&#8221; (Field de sh\u00ec)<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u5b9a\u4e49\u5b57\u6bb5\uff08\u540d\u79f0\uff0c\u7c7b\u578b\uff0c\u63cf\u8ff0\uff0c\u662f\u5426\u4e3a\u7a7a\uff09<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u4f7f\u5b57\u6bb5\u89e3\u6790<\/ol>\n<\/li>\n<\/ol>\n<p>\u89e3\u6790=\u786e\u5b9a\u5b57\u6bb5\u8fd4\u56de\u7684\u503c\u7684\u65b9\u6cd5<\/p>\n<p>\u6211\u4f1a\u6309\u7167\u4e24\u4e2a\u6b65\u9aa4\u8fdb\u884c\u64cd\u4f5c\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Types::QueryType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Object<\/span>\r\n  <span class=\"c1\"># \u57fa\u672c\u306f field(name, type, description, null:)<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:ping<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\u758e\u901a\u78ba\u8a8d'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"c1\"># Types::QueryType\u3067\u306ffield\u540d\u3068\u540c\u540d\u306e\u30e1\u30bd\u30c3\u30c9\u3092\u5b9a\u7fa9\u3057(\u4fbf\u5b9c\u4e0a\u3053\u308c\u3092resolve\u30e1\u30bd\u30c3\u30c9\u3068\u547c\u3073\u307e\u3059)\u3001\u305d\u306e\u8fd4\u308a\u5024\u3092field\u304c\u8fd4\u3059\u5024\u3068\u3057\u3066\u7528\u3044\u308b<\/span>\r\n  <span class=\"c1\"># \u3053\u3053\u3067\u306fping\u306efield\u306b\u305f\u3044\u3057\u3066\u3001'pong'\u3068\u3044\u3046\u6587\u5b57\u5217\u3092\u8fd4\u3059ping\u30e1\u30bd\u30c3\u30c9\u3092\u5b9a\u7fa9\u3057\u3001<\/span>\r\n  <span class=\"c1\"># \u3053\u308c\u3092resolve\u30e1\u30bd\u30c3\u30c9\u3068\u3057\u3066\u3044\u308b<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">ping<\/span>\r\n    <span class=\"s1\">'pong'<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6b64\u5916\uff0c\u6709\u591a\u79cd\u89e3\u51b3\u65b9\u6cd5\uff0c\u6211\u7a0d\u540e\u4f1a\u63d0\u53ca\u3002<\/p>\n<p>\u5728\u7c7b\u578b(type)\u4e2d\u53ef\u4ee5\u5b9a\u4e49\u9ed8\u8ba4\u5b58\u5728\u7684\u7c7b\u578b\uff08String\u3001Int\u3001Float\u3001Boolean\u548cID\uff08\u7528\u4e8e\u6307\u5b9a\u6574\u6570\u7684\u5b57\u7b26\u4e32\u6216\u6574\u6570\u7c7b\u578b\uff09\uff09\uff0c\u8fd8\u53ef\u4ee5\u5b9a\u4e49\u4e0e\u6a21\u578b\u76f8\u9002\u5e94\u7684\u81ea\u5b9a\u4e49\u7c7b\u578b\u3002<\/p>\n<h3>\u751f\u6210schema<\/h3>\n<p>\u5728\u8fd9\u4e2a\u9636\u6bb5\uff0c\u53ef\u4ee5\u8c03\u7528GraphQL\uff0c\u4f46\u662f\u5728\u6b64\u4e4b\u524d\uff0cGraphQL\u4f1a\u81ea\u52a8\u4ece\u67b6\u6784\u4e2d\u751f\u6210API\u67b6\u6784\u3002\u8ba9\u6211\u4eec\u5148\u751f\u6210\u5e76\u4fdd\u7559\u5b83\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nv\">$ <\/span>rails graphql:schema:dump\r\nSchema IDL dumped into .\/schema.graphql\r\nSchema JSON dumped into .\/schema.json\r\n<\/code><\/pre>\n<p>\u5728\u8fd9\u79cd\u72b6\u6001\u4e0b\uff0c\u8bbf\u95ee\u6d4b\u8bd5\u5ba2\u6237\u7aef\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/113-0.gif\" alt=\"ping.gif\" \/><\/div>\n<p>\u6211\u786e\u8ba4root\u7684QueryType\u4e2d\u6709\u4e00\u4e2a\u7c7b\u578b\u4e3aString\u7684ping\u5b57\u6bb5\u3002\u5e76\u4e14\u901a\u8fc7\u5bfc\u51faschema\uff0c\u5b83\u4e5f\u63d0\u4f9b\u4e86\u81ea\u52a8\u8865\u5168\u548c\u663e\u793a\u6587\u6863\u7684\u529f\u80fd\u3002<br \/>\n(\u8bf7\u6682\u65f6\u5ffd\u7565event)<\/p>\n<h3>\u4f7f\u7528\u539f\u59cb\u7c7b\u578b\u7684\u5b57\u6bb5\u5b9e\u73b0<\/h3>\n<p>\u5728\u4ee5\u4e0b\u793a\u4f8b\u4e2d\uff0c\u4f7f\u7528event field\u4f1a\u8fd4\u56deEventType\u7c7b\u578b\u7684\u54cd\u5e94\u3002<br \/>\n\u540c\u65f6\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u4f7f\u7528field\u53c2\u6570\uff0c\u5c06\u4f20\u5165\u7684id\u7528\u4e8e\u68c0\u7d22Event\u5b9e\u4f8b\uff0c\u5e76\u5c06\u5176\u5e94\u7528\u4e8e\u4e8b\u4ef6\u5b57\u6bb5\uff08resolve\uff09\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Types::QueryType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Object<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># \u5358\u4f53\u306e\u30ea\u30bd\u30fc\u30b9\u53d6\u5f97sample<\/span>\r\n  <span class=\"c1\"># Types::EventType \u304c\u30aa\u30ea\u30b8\u30ca\u30eb\u306e\u578b<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:event<\/span><span class=\"p\">,<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">EventType<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">true<\/span> <span class=\"k\">do<\/span>\r\n    <span class=\"n\">description<\/span> <span class=\"s1\">'\u30a4\u30d9\u30f3\u30c8\u3092id\u30671\u4ef6\u53d6\u5f97'<\/span> <span class=\"c1\"># field\u306edescription\u5f15\u6570\u306f\u30d6\u30ed\u30c3\u30af\u5185\u3067\u5b9a\u7fa9\u3057\u3066\u3082OK<\/span>\r\n    <span class=\"c1\">#<\/span>\r\n    <span class=\"c1\"># \u57fa\u672c argument(arg_name, arg_type, description, required:)<\/span>\r\n    <span class=\"c1\">#<\/span>\r\n    <span class=\"n\">argument<\/span> <span class=\"ss\">:id<\/span><span class=\"p\">,<\/span> <span class=\"no\">ID<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\u30a4\u30d9\u30f3\u30c8\u306eID'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">true<\/span>\r\n  <span class=\"k\">end<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># argument\u304c\u3042\u308b\u3068\u304d\u3001resolve\u30e1\u30bd\u30c3\u30c9\u306f\u5fc5\u9808\u30ad\u30fc\u30ef\u30fc\u30c9\u5f15\u6570\u3068\u3057\u3066\u305d\u308c\u3092\u53d7\u3051\u53d6\u308c\u308b<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">event<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">:)<\/span>\r\n    <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u5efa\u8bae\u67e5\u770bgems\/graphql-1.8.1\/lib\/graphql\/schema\/argument.rb\uff0c\u5176\u4e2d\u5305\u542b\u4e86argument\u7684\u5b98\u65b9\u8bf4\u660e\u6587\u6863\u3002<\/p>\n<h3>\u5b9a\u4e49\u7c7b\u578b<\/h3>\n<p>\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u5c06\u5b9e\u73b0\u4e00\u4e2a\u540d\u4e3aEventType\u7684\u81ea\u5b9a\u4e49\u7c7b\u578b\u3002<br \/>\n\u7531\u4e8eEventType\u5728resolve\u65b9\u6cd5\u4e2d\u8fd4\u56de\u4e86Event\u6a21\u578b\u7684\u5b9e\u4f8b\uff0c<br \/>\n\u56e0\u6b64\u6211\u4eec\u5e0c\u671b\u5c06Event\u6a21\u578b\u7684\u5c5e\u6027\u4f5c\u4e3a\u5b57\u6bb5\u6dfb\u52a0\u5230EventType\u4e2d\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\"># event\u30e2\u30c7\u30eb<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">CreateEvents<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ActiveRecord<\/span><span class=\"o\">::<\/span><span class=\"no\">Migration<\/span><span class=\"p\">[<\/span><span class=\"mf\">5.2<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">change<\/span>\r\n    <span class=\"n\">create_table<\/span> <span class=\"ss\">:events<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">t<\/span><span class=\"o\">|<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">references<\/span> <span class=\"ss\">:user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">foreign_key: <\/span><span class=\"kp\">true<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span> <span class=\"ss\">:subject<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">text<\/span> <span class=\"ss\">:body<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">timestamps<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Types::EventType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Object<\/span>\r\n  <span class=\"c1\"># [1] resolve\u306einference(\u63a8\u8ad6)\u3068\u3001resolve\u306e\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3 <\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:id<\/span><span class=\"p\">,<\/span>        <span class=\"no\">ID<\/span><span class=\"p\">,<\/span>                    <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:subject<\/span><span class=\"p\">,<\/span>   <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:body<\/span><span class=\"p\">,<\/span>      <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n\r\n  <span class=\"c1\"># [2] resolve\u30e1\u30bd\u30c3\u30c9\u5185\u3067\u5229\u7528\u3067\u304d\u308bhelper\u30e1\u30bd\u30c3\u30c9: object, context<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:bodyHtml<\/span><span class=\"p\">,<\/span>  <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"c1\"># snake_case\u3067\u3042\u308b\u3053\u3068\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/span>\r\n  <span class=\"c1\"># resolve\u30e1\u30bd\u30c3\u30c9\u540d\u3092 `camelize(:lowder)`\u3057\u305f\u5024\u304cfield\u540d\u306eresolve\u306b\u7528\u3044\u3089\u308c\u307e\u3059<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">body_html<\/span>\r\n    <span class=\"n\">object<\/span><span class=\"p\">.<\/span><span class=\"nf\">decorate<\/span><span class=\"p\">.<\/span><span class=\"nf\">body_html<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"c1\"># [3] \u578b\u306e\u7a2e\u985e\u306b\u306f\u3044\u304f\u3064\u304b\u3042\u308b<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:createdAt<\/span><span class=\"p\">,<\/span> <span class=\"no\">ScalarTypes<\/span><span class=\"o\">::<\/span><span class=\"no\">DateTime<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u4eec\u6765\u770b\u4e09\u4e2a\u8981\u70b9\u3002<\/p>\n<h4>[1] \u89e3\u51b3\u7684\u63a8\u65ad\u548c\u89e3\u51b3\u7684\u53d8\u4f53<\/h4>\n<p>\u5728 field \u4e2d\u5e76\u4e0d\u603b\u662f\u9700\u8981\u4e00\u4e2a resolve \u51fd\u6570\uff0c\u6709\u65f6\u5019\u5b83\u4f1a\u81ea\u52a8\u63a8\u65ad\u3002<\/p>\n<p>\u8fd9\u4e2a\u6761\u4ef6\u662f\uff0c<\/p>\n<p>\u5982\u679c\u6211\u80fd\u901a\u8fc7\u53d1\u9001\u9886\u57df\u540d\u79f0\u4f5c\u4e3a\u6d88\u606f\u6765\u5904\u7406\u5f53\u524d\u7684&#8221;object&#8221;\uff08\u4e5f\u5c31\u662f\u8bf4\uff0c\u5982\u679c\u8be5\u9886\u57df\u540d\u79f0\u4e0e\u5c5e\u6027\u3001\u65b9\u6cd5\u7684\u540d\u79f0\u76f8\u5339\u914d\uff09\uff0c\u90a3\u4e48\u6211\u5c31\u53ef\u4ee5\u5229\u7528\u5176\u8fd4\u56de\u503c\u3002<\/p>\n<p>\u662f\u7684\u3002<\/p>\n<p>&#8220;\u4eca\u6b63\u5728\u5904\u7406\u7684\u5bf9\u8c61\u662f\u6307\u67e5\u8be2\u6240\u7ec4\u88c5\u7684&#8217;\u4e0a\u4e00\u5c42\u7ea7\u7684\u503c&#8217;\u3002&#8221;<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">query<\/span> <span class=\"n\">Event<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"p\">{<\/span>\r\n    <span class=\"n\">event<\/span> <span class=\"p\">{<\/span>   <span class=\"c\"># event\u304b\u3089\u307f\u305fobject\u306froot\u306a\u306e\u3067nil\u3002\u306a\u304aMySchema.execute\u306boption\u3092\u6e21\u3059\u3068root\u306eobject\u3092\u6307\u5b9a\u3067\u304d\u308b<\/span>\r\n      <span class=\"n\">id<\/span>\r\n      <span class=\"n\">subject<\/span> <span class=\"c\"># id, subject\u304b\u3089\u307f\u305fobject\u306fevent\u306b\u5bfe\u3057\u3066resolve\u3057\u305f\u5024\u306e\u3053\u3068\u3002<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u4f8b\u5982\uff0c\u5728\u5f53\u524d\u60c5\u51b5\u4e0b\uff0c\u53ef\u4ee5\u901a\u8fc7field :event\u89e3\u6790Event.find(id)\u6765\u83b7\u5f97\u4e8b\u4ef6\u3002<\/p>\n<p>\u7531\u4e8eEvent\u6a21\u578b\u5177\u6709id\u3001subject\u548cbody\u4f5c\u4e3a\u5c5e\u6027\uff0c\u6240\u4ee5\u5728EventType\u7684id\u3001subject\u548cbody\u65b9\u9762\u4e0d\u9700\u8981\u7279\u522b\u89e3\u51b3\u3002<\/p>\n<p>\u5982\u679c\u5141\u8bb8\u4e0d\u5b58\u5728\u4e8e\u6a21\u578b\u4e2d\u7684\u5b57\u6bb5\u7684\u60c5\u51b5<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">bodyHtml\u306e\u3088\u3046\u306bresolve\u30e1\u30bd\u30c3\u30c9\u3092\u305d\u306e\u5834\u306b\u66f8\u304f<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">field\u306e\u30ad\u30fc\u30ef\u30fc\u30c9\u5f15\u6570\u3068\u3057\u3066 method: \u3092\u7528\u3044\u308b<\/ul>\n<\/li>\n<\/ul>\n<p>field\u540d\u3068\u7570\u306a\u308b\u30e1\u30bd\u30c3\u30c9\u3092\u5b9a\u7fa9\u3057\u305f\u969b\u306b\u305d\u308c\u3092\u9069\u7528\u3055\u305b\u308b. \u3042\u307e\u308a\u4f7f\u308f\u306a\u3044\u304b\u3082<\/p>\n<p>object\u306b\u305f\u3044\u3057\u3066hash\u306b\u5bfe\u3059\u308bkey\u306e\u3088\u3046\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308c\u3070 hash_key: \u3092\u7528\u3044\u308b<\/p>\n<p>\u4f8b\u3048\u3070 hash_key: :body \u3059\u308b\u3068 event.body\u3067\u306f\u306a\u304f\u3001 event[:body] \u3067\u5024\u3092\u53d6\u5f97\u3059\u308b<\/p>\n<p>resolver\u30af\u30e9\u30b9\u3092\u7528\u3044\u308b<\/p>\n<p>\u3053\u308c\u3092\u4f7f\u3046\u306e\u306f\u7279\u5b9a\u306e\u7528\u9014\u306b\u9650\u5b9a\u3057\u305f\u307b\u3046\u304c\u826f\u3044\u3068\u516c\u5f0fdocs\u306b\u3042\u308a\u307e\u3059<\/p>\n<p>\u53ef\u4ee5\u505a\u8fd9\u4ef6\u4e8b\u3002<\/p>\n<p>\u57fa\u672c\u4e0a\uff0c\u89e3\u51b3\u65b9\u6cd5\u662f\u5728root\u4e2d\u7f16\u5199resolve\u65b9\u6cd5\uff0c\u6216\u8005\u5728Object\u7c7b\u578b\u4e2d\u7f16\u5199\u4e0emodel\u5bf9\u5e94\u7684\u65b9\u6cd5\u548c\u5c5e\u6027\u3002\u53e6\u5916\uff0c\u5c06object\u4f5c\u4e3adecorator\u5b9e\u4f8b\uff0c\u5e76\u5728decorator\u4e2d\u7f16\u5199\u4e0efield\u5bf9\u5e94\u7684\u65b9\u6cd5\uff0c\u53ef\u80fd\u53ef\u4ee5\u907f\u514d\u5728model\u4e2d\u6dfb\u52a0\u7528\u4e8e\u89c6\u56fe\u903b\u8f91\u7684\u4ee3\u7801\u3002<\/p>\n<p>\u53ef\u4ee5\u5728root\u4e0a\u6307\u5b9aobject\uff0c\u901a\u8fc7\u4f20\u9012\u540d\u4e3aroot_value\u7684\u9009\u9879\u5230MySchema.execute\u6765\u5b9e\u73b0\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"n\">current_team<\/span> <span class=\"o\">=<\/span> <span class=\"n\">current_user<\/span><span class=\"p\">.<\/span><span class=\"nf\">team<\/span>\r\n<span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"no\">MySchema<\/span><span class=\"p\">.<\/span><span class=\"nf\">execute<\/span><span class=\"p\">(<\/span><span class=\"n\">query<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"ss\">root_value: <\/span><span class=\"n\">current_team<\/span> <span class=\"p\">})<\/span>\r\n<\/code><\/pre>\n<p>\u4f60\u53ef\u4ee5\u5728\u8fd9\u91cc\u67e5\u770bexecute\u7684\u5176\u4ed6\u9009\u9879\u3002<\/p>\n<h4>[2] \u5728resolve\u65b9\u6cd5\u4e2d\u53ef\u4f7f\u7528\u7684helper\uff1a\u5bf9\u8c61\uff0c\u4e0a\u4e0b\u6587<\/h4>\n<p>\u5728\u7f16\u5199resolve\u65b9\u6cd5\u65f6\uff0c\u53ef\u4ee5\u4f7f\u7528\u540d\u4e3aobject\u548ccontext\u7684\u8f85\u52a9\u65b9\u6cd5\u3002<\/p>\n<p>\u6839\u636e\u4e4b\u524d\u89e3\u91ca\u7684[1]\uff0cobject\u6307\u7684\u662f\u7ec4\u88c5\u4e86\u67e5\u8be2\u7684\u201c\u4e0a\u7ea7\u503c\u201d\u3002\u5bf9\u4e8e\u6839\u8282\u70b9\uff0c\u5982\u679c\u4e0d\u6307\u5b9aroot_value\uff0c\u5219\u4e3anil\u3002<\/p>\n<p>\u4e0a\u4e0b\u6587\uff08context\uff09\u662f\u6307\u5728GraphqlController#execute\u4e2d\u4f20\u9012\u7ed9execute\u7684\u4e0a\u4e0b\u6587\u3002\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u9884\u671f\u5c06\u5e94\u7528\u7a0b\u5e8f\u8303\u56f4\u5185\u4f7f\u7528\u7684\u4fe1\u606f\uff08\u5982current_user\uff09\u586b\u5145\u5230graphql\u5185\u90e8\u5e76\u4f20\u9012\u3002<\/p>\n<p>\u4f8b\u5982\uff0c\u6211\u4eec\u4f1a\u6267\u884c\u5bf9\u83b7\u53d6\u7684\u5bf9\u8c61\u8fdb\u884c\u8bbf\u95ee\u6743\u9650\u68c0\u67e5\u7b49\u64cd\u4f5c\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">def<\/span> <span class=\"nf\">event<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">:)<\/span>\r\n  <span class=\"n\">ev<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">raise<\/span> <span class=\"no\">Forbidden<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\u3053\u306e\u30a4\u30d9\u30f3\u30c8\u306b\u306f\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093'<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:current_user<\/span><span class=\"p\">].<\/span><span class=\"nf\">can?<\/span><span class=\"p\">(<\/span><span class=\"ss\">:read<\/span><span class=\"p\">,<\/span> <span class=\"n\">ev<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">ev<\/span>\r\n<span class=\"k\">rescue<\/span> <span class=\"no\">Forbidden<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">e<\/span>\r\n  <span class=\"k\">raise<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"p\">.<\/span><span class=\"nf\">message<\/span> <span class=\"c1\"># \u5f8c\u8ff0<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h4>[3] \u6709\u51e0\u79cd\u4e0d\u540c\u7684\u578b\u53f7\u3002<\/h4>\n<p>\u5728\u8fd9\u91cc\u5b9e\u73b0\u7684EventType\u5c06\u6210\u4e3a\u4e00\u79cd\u53eb\u505aObject\u7684\u7c7b\u578b\u3002<\/p>\n<p>\u9664\u4e86GraphQL\uff0c\u8fd8\u6709\u5176\u4ed6\u7684\u9009\u9879<\/p>\n<p>Scalar \u4f8b\u3048\u3070\u65e5\u4ed8\u306a\u3069\u3001primitive\u306a\u30c7\u30fc\u30bf\u578b\u3092\u5b9a\u7fa9\u3059\u308b<\/p>\n<p>Enum enum\u3092\u5b9a\u7fa9<\/p>\n<p>Input \u5165\u529b\u5024\u3092\u578b\u306b\u3057\u3066\u518d\u5229\u7528<\/p>\n<p>Interfaces \u6587\u5b57\u901a\u308a<\/p>\n<p>Unions \u6587\u5b57\u901a\u308a<\/p>\n<p>Non-Null !\u306e\u53d6\u6271<\/p>\n<p>\u6709\u51e0\u79cd\u65b9\u4fbf\u8bb0\u4f4f\u548c\u4f7f\u7528\u7684\u7c7b\u578b\u548c\u7c7b\u578b\u8bed\u6cd5\uff0c\u660e\u786e\u4e86\u4f1a\u5f88\u65b9\u4fbf\uff0c\u4f46\u9700\u8981\u6839\u636e\u9700\u8981\u8fdb\u884c\u8bd5\u9a8c\u3002\u5b98\u65b9\u6587\u6863\u5728\u8fd9\u91cc\u3002<\/p>\n<p>\u5728\u8fd9\u91cc\uff0c\u6211\u4ec5\u4e3e\u4f8b\u5c55\u793a\u4e86Scalar\u7684\u5b9e\u73b0\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">ScalarTypes::DateTime<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Scalar<\/span>\r\n  <span class=\"n\">description<\/span> <span class=\"s1\">'\u65e5\u4ed8\u578b'<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nc\">self<\/span><span class=\"o\">.<\/span><span class=\"nf\">coerce_input<\/span><span class=\"p\">(<\/span><span class=\"n\">value<\/span><span class=\"p\">,<\/span> <span class=\"n\">_context<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"no\">Time<\/span><span class=\"p\">.<\/span><span class=\"nf\">zone<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"n\">value<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nc\">self<\/span><span class=\"o\">.<\/span><span class=\"nf\">coerce_result<\/span><span class=\"p\">(<\/span><span class=\"n\">value<\/span><span class=\"p\">,<\/span> <span class=\"n\">_context<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"no\">I18n<\/span><span class=\"p\">.<\/span><span class=\"nf\">l<\/span><span class=\"p\">(<\/span><span class=\"n\">value<\/span><span class=\"p\">,<\/span> <span class=\"ss\">format: :to_date<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6839\u636eEventType\u4e2d\u7684\u5199\u6cd5\uff0c\u73b0\u5728\u53ef\u4ee5\u4f7f\u7528\u5b57\u6bb5 :createdAt\uff0cScalarTypes::DateTime\uff0cnull: false\u3002<\/p>\n<h3>\u9519\u8bef\u5904\u7406<\/h3>\n<p>\u5728 GraphQL \u4e2d\uff0c\u5f53\u51fa\u73b0\u9519\u8bef\u65f6\uff0c\u4f1a\u5728\u54cd\u5e94\u7684\u9876\u7ea7\u4e2d\u5305\u542b\u4e00\u4e2a\u540d\u4e3a &#8220;errors&#8221; \u7684\u952e\uff0c\u4ee5\u8fd4\u56de\u9519\u8bef\u5185\u5bb9\u3002<\/p>\n<p>\u5982\u679cGraphql\u65e0\u6cd5\u6355\u83b7\u9519\u8bef\uff0c\u5219\u4f1a\u8fd4\u56de\u4e0e\u5176\u5185\u5bb9\u76f8\u5173\u7684\u9519\u8bef\uff0c\u5176\u4e2d\u72b6\u6001\u7801\u4e3a400\u7cfb\u548c500\u7cfb\u3002<br \/>\n\u7531\u4e8egraphql\u5ba2\u6237\u7aef\u4e0d\u9884\u671f\u4ee5\u8fd9\u4e9b\u72b6\u6001\u7801\u8fd4\u56de\uff0c\u56e0\u6b64\u5fc5\u987b\u59cb\u7ec8\u6267\u884c\u5f02\u5e38\u5904\u7406\u3002<\/p>\n<p>\u56e0\u6b64\uff0c\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u672c\u5730\u5316\u7684\u91cd\u65b0\u63cf\u8ff0\uff0c\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff1a<br \/>\n\u56e0\u6b64\uff0c\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u672c\u5730\u5316\u7684\u91cd\u65b0\u63cf\u8ff0\uff0c\u53ea\u9700\u8981\u4e00\u79cd\u9009\u62e9\uff1a<\/p>\n<ol>\u5efa\u7acb\u4e00\u4e2a\u673a\u5236\uff0c\u786e\u4fdd\u4e0d\u7ba1\u51fa\u73b0\u4ec0\u4e48\u60c5\u51b5\uff0c\u5373\u4f7fGraphql\u51fa\u73b0\u65e0\u6cd5\u6355\u83b7\u7684\u9519\u8bef\uff0c\u4e5f\u4e00\u5b9a\u8981\u8fdb\u884c\u6551\u63f4\u3002<\/ol>\n<p>\u8fdb\u884c\u4ee5\u4e0b\u4e24\u4e2a\u70b9<\/p>\n<h4>[1] \u5c06\u9519\u8bef\u8f6c\u5316\u4e3a\u53ef\u4ee5\u6355\u83b7\u7684 GraphQL \u9519\u8bef\u3002<\/h4>\n<p>\u6211\u5011\u5c07\u518d\u6b21\u6aa2\u67e5\u5148\u524d\u7684\u932f\u8aa4\u8655\u7406\u7a0b\u5e8f\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">def<\/span> <span class=\"nf\">event<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">:)<\/span>\r\n  <span class=\"n\">ev<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">raise<\/span> <span class=\"no\">Forbidden<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\u3053\u306e\u30a4\u30d9\u30f3\u30c8\u306b\u306f\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093'<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:current_user<\/span><span class=\"p\">].<\/span><span class=\"nf\">can?<\/span><span class=\"p\">(<\/span><span class=\"ss\">:read<\/span><span class=\"p\">,<\/span> <span class=\"n\">ev<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">ev<\/span>\r\n<span class=\"k\">rescue<\/span> <span class=\"no\">Forbidden<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">e<\/span>\r\n  <span class=\"k\">raise<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"p\">.<\/span><span class=\"nf\">message<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u901a\u8fc7\u4f7f\u7528Graphql::ExecutionError\uff0c\u5728\u8fd9\u91cc\u53ef\u4ee5\u5c06\u53d1\u751f\u7684\u9519\u8bef\u5c01\u88c5\u5728errors\u952e\u4e2d\uff0c\u5e76\u4ee5\u72b6\u6001\u7801200\u8fd4\u56de\u3002<br \/>\n\u540c\u65f6\uff0c\u9519\u8bef\u6d88\u606f\u53ef\u4ee5\u4f20\u9012\u7ed9\u8fd9\u4e2a\u9519\u8bef\uff0c\u5b83\u4f1a\u88ab\u5b58\u50a8\u5728errors\u7684message\u4e2d\u3002<\/p>\n<p>\u4f7f\u7528\u7ee7\u627f\u4e86 Graphql::ExecutionError \u7684\u9519\u8bef\u4f1a\u66f4\u6e05\u6670\u548c\u9002\u5f53\u5730\u63d0\u4f9b\u9519\u8bef\u4fe1\u606f\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">GraphQL::Forbidden<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span>\r\n    <span class=\"k\">super<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\u3053\u306e\u30a4\u30d9\u30f3\u30c8\u306b\u306f\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093'<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>  \r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"c1\"># \u4ee5\u4e0b\u306e\u3088\u3046\u306braise\u3059\u308b\u3053\u3068\u3067\u3001errors\u30ad\u30fc\u306b{ code: 'SOME_ERROR_CODE' }\u3092\u8ffd\u52a0\u3057\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u5074\u3067\u30a8\u30e9\u30fc\u7a2e\u5225\u3092\u5224\u5225\u3057\u3084\u3059\u304f\u3067\u304d\u307e\u3059<\/span>\r\n  <span class=\"c1\">#   raise GraphQL::ExecutionError.new(message, { extensions: { code: 'SOME_ERROR_CODE' } })<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># to_h\u3092override\u3059\u308b\u3053\u3068\u3067\u3001\u3053\u306eextensions\u3092\u5e38\u306b\u8fd4\u3059\u3088\u3046\u306b\u3067\u304d\u307e\u3059\u3002<\/span>\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">to_h<\/span>\r\n    <span class=\"k\">super<\/span><span class=\"p\">.<\/span><span class=\"nf\">merge<\/span><span class=\"p\">({<\/span> <span class=\"s2\">\"extensions\"<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span><span class=\"s2\">\"code\"<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"no\">Graphql<\/span><span class=\"o\">::<\/span><span class=\"s2\">\"FORBIDDEN\"<\/span><span class=\"p\">}<\/span> <span class=\"p\">})<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u53ef\u4ee5\u7528\u4ee5\u4e0b\u65b9\u5f0f\u6539\u5199\uff1a<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">def<\/span> <span class=\"nf\">event<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">:)<\/span>\r\n  <span class=\"n\">ev<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">raise<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Forbidden<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:current_user<\/span><span class=\"p\">].<\/span><span class=\"nf\">can?<\/span><span class=\"p\">(<\/span><span class=\"ss\">:read<\/span><span class=\"p\">,<\/span> <span class=\"n\">ev<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">ev<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h4>[2] \u521b\u5efa\u4e00\u4e2a\u673a\u5236\uff0c\u5373\u4f7f\u51fa\u73b0\u65e0\u6cd5\u6355\u6349\u5230\u7684GraphQL\u9519\u8bef\u4e5f\u8981\u786e\u4fdd\u8fdb\u884c\u6551\u63f4\u3002<\/h4>\n<p>\u4f60\u53ef\u4ee5\u4f7f\u7528Graphql::ExecutionError\u6216\u5176\u5b50\u7c7b\u4f7f\u5ba2\u6237\u7aef\u53ef\u4ee5\u6b63\u786e\u5730\u4f20\u9012\u9519\u8bef\u4fe1\u606f\uff0c\u4ee5\u5728\u53ef\u80fd\u53d1\u751f\u9519\u8bef\u7684\u5730\u65b9\u51fa\u73b0\u9519\u8bef\u3002\u7136\u800c\uff0c\u5728\u6240\u6709\u53ef\u80fd\u51fa\u9519\u7684\u5730\u65b9\u90fd\u4e86\u89e3\u9519\u8bef\u7684\u53d1\u751f\u662f\u56f0\u96be\u7684\uff0c\u6240\u4ee5\u9700\u8981\u4e00\u4e2a\u5b89\u5168\u7f51\u70b9\u3002<\/p>\n<p>\u8fd9\u4e2a\u5b9e\u73b0\u53ef\u4ee5\u5728MySchema\u4e2d\u5b8c\u6210\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">GraphQL::BadRequest<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span><span class=\"p\">;<\/span> <span class=\"k\">end<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">GraphQL::NotFound<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span><span class=\"p\">;<\/span> <span class=\"k\">end<\/span>\r\n\r\n<span class=\"k\">class<\/span> <span class=\"nc\">MySchema<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># \u8d77\u304d\u305f\u30a8\u30e9\u30fc\u3092\u5168\u3066\u62fe\u3046<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"n\">rescue_from<\/span><span class=\"p\">(<\/span><span class=\"no\">Exception<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">error<\/span><span class=\"o\">|<\/span>\r\n    <span class=\"k\">case<\/span> <span class=\"n\">error<\/span>\r\n    <span class=\"k\">when<\/span> <span class=\"no\">ActiveRecord<\/span><span class=\"o\">::<\/span><span class=\"no\">RecordInvalid<\/span>\r\n      <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">BadRequest<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"s1\">'\u30ea\u30af\u30a8\u30b9\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093'<\/span>\r\n    <span class=\"k\">when<\/span> <span class=\"no\">ActiveRecord<\/span><span class=\"o\">::<\/span><span class=\"no\">RecordNotFound<\/span>\r\n      <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">NotFound<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"s1\">'\u898b\u3064\u304b\u308a\u307e\u305b\u3093'<\/span>\r\n    <span class=\"k\">else<\/span>\r\n      <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">ExecutionError<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"s1\">'\u539f\u56e0\u4e0d\u660e\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f'<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"n\">query<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">QueryType<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">mutation<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MutationType<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u5728\u8fd9\u91cc\uff0c\u5173\u4e8e\u9519\u8bef\u7684\u63cf\u8ff0\u662f\u6709\u7684\uff0c\u4f46\u662f\u6ca1\u6709\u5199\u5f97\u5f88\u8be6\u7ec6\uff0c\u6240\u4ee5\u60a8\u9700\u8981\u9605\u8bfb gems\/graphql-1.8.1\/lib\/graphql\/schema.rb \u6765\u4e86\u89e3\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<h3>\u83b7\u53d6\u591a\u4e2a\u8d44\u6e90\u548c\u5206\u9875<\/h3>\n<p>\u5f53\u60f3\u8981\u63d0\u4f9b\u6bcf\u9875\u83b7\u53d6 N \u4e2a Event \u7684\u5206\u9875\u529f\u80fd\u65f6\uff0c\u4f7f\u7528 GraphQL \u53ef\u4ee5\u5f88\u5bb9\u6613\u5730\u5b9e\u73b0\u3002\u5b9e\u9645\u4e0a\uff0c\u5728 GraphQL \u4e2d\u5df2\u7ecf\u9884\u5148\u96c6\u6210\u4e86\u57fa\u4e8e\u6e38\u6807\u7684\u5206\u9875\u5b9e\u73b0\uff0c\u51e0\u4e4e\u53ea\u9700\u901a\u8fc7\u67e5\u8be2\u5c31\u53ef\u4ee5\u5b9e\u73b0\uff0c\u800c\u4e14\u51e0\u4e4e\u6ca1\u6709\u989d\u5916\u7684\u6210\u672c\u3002<\/p>\n<p>\u516c\u5f0f\u6587\u4ef6\u4e2d\u6709\u8bf4\u660e\u3002<\/p>\n<p>\u5927\u81f4\u4e0a\u7684\u4efb\u52a1\u662f<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u5728\u670d\u52a1\u5668\u7aef\u4f7f\u7528connection\uff0c<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\u5728\u5ba2\u6237\u7aef\u4e0a\u6839\u636econnection\u8bbe\u7f6e\u67e5\u8be2\/\u5904\u7406\u4e0econnection\u76f8\u5339\u914d\u7684\u54cd\u5e94\u3002<\/ol>\n<p>\u662f\u7684\u3002<\/p>\n<h4>\u670d\u52a1\u5668\u7aef<\/h4>\n<p>\u5e26\u6709\u5206\u9875\u529f\u80fd\u7684\u5b57\u6bb5\u5b9a\u4e49\u975e\u5e38\u7b80\u5355\u3002<\/p>\n<pre class=\"post-pre\"><code>\r\n<span class=\"c1\"># \u578b\u306e\u6307\u5b9a\u3068\u3057\u3066\u3001EventType\u3092\u8907\u6570\u8fd4\u3059\u578b\u3068\u3057\u3066\u3001Types::EventType.connection_type\u3092\u6307\u5b9a\u3057\u307e\u3059<\/span>\r\n<span class=\"c1\"># NOTE! class-based api\u4ee5\u524d\u306ffield\u306e\u4ee3\u308f\u308a\u306bconnection\u3092\u7528\u3044\u307e\u3057\u305f\u304c\u3082\u3046\u4f7f\u3044\u307e\u305b\u3093\u3002<\/span>\r\n<span class=\"n\">field<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">EventType<\/span><span class=\"p\">.<\/span><span class=\"nf\">connection_type<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">description<\/span> <span class=\"s1\">'\u30a4\u30d9\u30f3\u30c8\u4e00\u89a7\u3092pagination\u3067\u53d6\u5f97\u3057\u307e\u3059'<\/span>\r\n  <span class=\"n\">argument<\/span> <span class=\"ss\">:query<\/span><span class=\"p\">,<\/span>  <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span> <span class=\"c1\"># \u30a4\u30d9\u30f3\u30c8\u3092\u691c\u7d22\u3059\u308b\u6587\u5b57\u5217<\/span>\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">events<\/span><span class=\"p\">(<\/span><span class=\"ss\">query: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">search<\/span><span class=\"p\">({<\/span> \r\n    <span class=\"ss\">subject_or_body_cont: <\/span><span class=\"n\">query<\/span>\r\n  <span class=\"p\">}).<\/span><span class=\"nf\">result<\/span><span class=\"p\">.<\/span><span class=\"nf\">order<\/span><span class=\"p\">(<\/span><span class=\"ss\">created_at: :desc<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u53ea\u9700\u8fd9\u4e00\u4e2a\u9009\u9879\uff0c\u5373\u53ef\u83b7\u5f97\u57fa\u4e8e\u5149\u6807\u7684\u5206\u9875\u3002<\/p>\n<h4>\u5ba2\u6237\u7aef\u65b9<\/h4>\n<p>\u9996\u5148\uff0c\u6211\u5011\u9700\u8981\u69cb\u5efa\u67e5\u8a62\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">query<\/span> <span class=\"n\">Events<\/span><span class=\"p\">(<\/span>\r\n  <span class=\"nv\">$lastEndCursor<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"\"<\/span><span class=\"p\">,<\/span> \r\n  <span class=\"nv\">$offset<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Int<\/span> <span class=\"p\">=<\/span> <span class=\"err\">0<\/span><span class=\"p\">,<\/span> \r\n  <span class=\"nv\">$query<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"\"<\/span>\r\n<span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"c\"># first, after\u304cgraphql\u306b\u3088\u3063\u3066\u4e0e\u3048\u3089\u308c\u308bfield\u5f15\u6570\u3067\u3059<\/span>\r\n    <span class=\"c\">#   first \u8a72\u5f53\u306e\u7bc4\u56f2\u3067\u982d\u304b\u3089\u4f55\u4ef6\u53d6\u5f97\u3059\u308b\u304b<\/span>\r\n    <span class=\"c\">#   after \u6307\u5b9a\u3057\u305fcursor\u4ee5\u5f8c\u3092\u53d6\u5f97\u5bfe\u8c61\u3068\u3059\u308b<\/span>\r\n    <span class=\"c\"># (query\u306f\u72ec\u81ea\u306b\u8ffd\u52a0\u3057\u305ffield\u5f15\u6570\u3002\u3042\u308c\u3070\u3001\u305d\u308c\u3092\u5143\u306bsubject, body\u3092\u691c\u7d22\u3057\u307e\u3059)<\/span>\r\n    <span class=\"n\">events<\/span><span class=\"p\">(<\/span><span class=\"n\">first<\/span><span class=\"p\">:<\/span> <span class=\"mi\">5<\/span><span class=\"p\">,<\/span> <span class=\"n\">after<\/span><span class=\"p\">:<\/span> <span class=\"nv\">$lastEndCursor<\/span><span class=\"p\">,<\/span> <span class=\"n\">query<\/span><span class=\"p\">:<\/span> <span class=\"nv\">$query<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"c\"># connection\u304c\u63d0\u4f9b\u3059\u308b\u30da\u30fc\u30b8\u30cd\u30fc\u30b7\u30e7\u30f3\u60c5\u5831  <\/span>\r\n      <span class=\"n\">pageInfo<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">hasPreviousPage<\/span>  \r\n        <span class=\"n\">hasNextPage<\/span>\r\n        <span class=\"n\">endCursor<\/span>\r\n        <span class=\"n\">startCursor<\/span>\r\n      <span class=\"p\">}<\/span>\r\n      <span class=\"c\"># connection\u306f\u30a2\u30a4\u30c6\u30e0\u306e\u30ea\u30b9\u30c8\u3092edges\u3067\u30e9\u30c3\u30d7\u3059\u308b<\/span>\r\n      <span class=\"n\">edges<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">cursor<\/span> <span class=\"c\"># \u73fe\u5728\u4f4d\u7f6e\u3092\u793a\u3059\u3002after\u306b\u308f\u305f\u3059<\/span>\r\n        <span class=\"n\">node<\/span> <span class=\"p\">{<\/span> <span class=\"c\"># \u4e00\u3064\u4e00\u3064\u306eobject\u3092node\u3068\u3057\u3066\u793a\u3059<\/span>\r\n          <span class=\"n\">id<\/span>\r\n          <span class=\"n\">subject<\/span>\r\n          <span class=\"n\">body<\/span>\r\n        <span class=\"p\">}<\/span>\r\n      <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u8fd9\u662f\u8fd4\u56de\u7684 JSON \u7ed3\u679c\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nl\">\"data\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nl\">\"events\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nl\">\"pageInfo\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nl\">\"hasNextPage\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"hasPreviousPage\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"startCursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Mw==\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"endCursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Nw==\"<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nl\">\"edges\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nl\">\"cursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Mw==\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nl\">\"node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"12\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"test\"<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nl\">\"cursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"NA==\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nl\">\"node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"11\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"asdfasdf\"<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nl\">\"cursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"NQ==\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nl\">\"node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"10\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"asdfadsf\"<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nl\">\"cursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Ng==\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nl\">\"node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"9\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"asdfasdf\"<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nl\">\"cursor\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Nw==\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nl\">\"node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"8\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\u307b\u3052\"<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">}<\/span>\r\n      <span class=\"p\">]<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u6839\u636e\u54cd\u5e94\uff0c\u53ef\u4ee5\u770b\u51fa\u952e\u503c\u4e2d\u5939\u6742\u7740&#8221;edges&#8221;\u548c&#8221;node&#8221;\u3002<br \/>\n\u5728\u5ba2\u6237\u7aef\u4e0a\u9700\u8981\u8fdb\u884c\u4ece\u8fd9\u4e9b\u952e\u503c\u4e2d\u63d0\u53d6\u6240\u9700\u4fe1\u606f\u7684\u5904\u7406\uff0c\u5176\u4e2d\u4f1a\u51fa\u73b0\u5ba2\u6237\u7aef\u4e0a\u56fa\u6709\u7684GraphQL\u4ee3\u7801\uff0c\u5982&#8221;edges&#8221;\u548c&#8221;node&#8221;\u3002<br \/>\n\u8bf7\u5224\u65ad\u662f\u5426\u8981\u8bbe\u7acb\u4e0eGraphQL\u8fdb\u884c\u4ea4\u4e92\u7684\u5c42\uff0c\u6216\u8005\u679c\u65ad\u63a5\u53d7\u6574\u4e2a\u4ee3\u7801\u5e93\u4e2d\u7684GraphQL\u3002<\/p>\n<p>\u5e94\u5f53\u5982\u4e0b\u7684\u54cd\u5e94\u6d41\u7a0b\uff08\u4f2a\u4ee3\u7801\uff09<\/p>\n<pre class=\"post-pre\"><code><span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">API<\/span><span class=\"p\">.<\/span><span class=\"nx\">post<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">\/graphql<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">query<\/span><span class=\"p\">,<\/span> <span class=\"nx\">variables<\/span><span class=\"p\">)<\/span>\r\n<span class=\"c1\">\/\/ edges\u304b\u3089event(node)\u3092\u53d6\u308a\u51fa\u3059\u5fc5\u8981\u304c\u3042\u308b<\/span>\r\n<span class=\"c1\">\/\/ \u3053\u306e\u51e6\u7406\u304cAPI\u30b3\u30fc\u30eb\u3059\u308b\u5404\u6240\u306b\u6563\u3089\u3070\u308b\u306e\u306f\u3061\u3087\u3063\u3068\u5acc\u3002<\/span>\r\n<span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">store<\/span><span class=\"p\">.<\/span><span class=\"nx\">events<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">events<\/span><span class=\"p\">.<\/span><span class=\"nx\">edges<\/span><span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">item<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">node<\/span><span class=\"p\">)<\/span>\r\n<\/code><\/pre>\n<h2>\u7a81\u53d8<\/h2>\n<p>Mutation\u7684\u5b9e\u73b0\u8fc7\u7a0b\u4e0eQuery\u51e0\u4e4e\u5b8c\u5168\u76f8\u540c\u3002<\/p>\n<h3>\u670d\u52a1\u5668\u7aef<\/h3>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">MySchema<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span>\r\n  <span class=\"n\">query<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">QueryType<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">mutation<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MutationType<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># &lt;= ADD<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"c1\"># Mutation\u306eroot\u3067\u3059. \u7d99\u627f\u3059\u308b\u306e\u306fGraphQL::Schema::Object\u306a\u306e\u3067\u3001\u901a\u5e38\u306eObject\u30bf\u30a4\u30d7\u306e\u578b\u3067\u3059\u306d<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">Types::MutationType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Object<\/span>\r\n  <span class=\"c1\"># field\u306emutation\u30ad\u30fc\u30ef\u30fc\u30c9\u5f15\u6570\u306bmutation\u51e6\u7406\u3092\u6e21\u3057\u307e\u3059<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:updateEvent<\/span><span class=\"p\">,<\/span> <span class=\"ss\">mutation: <\/span><span class=\"no\">Mutations<\/span><span class=\"o\">::<\/span><span class=\"no\">UpdateEvent<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u5230\u76ee\u524d\u4e3a\u6b62\u7684\u5b9e\u73b0\u4e0e\u67e5\u8be2\u51e0\u4e4e\u6ca1\u6709\u533a\u522b\u3002<br \/>\n\u5b9e\u9645\u7684\u53d8\u66f4\u5904\u7406\u4e5f\u4e0e\u67e5\u8be2\u5e76\u6ca1\u6709\u592a\u5927\u4e0d\u540c\uff0c\u552f\u4e00\u4e0d\u540c\u7684\u662f\u5b9a\u4e49\u4e86\u4e00\u4e2a\u540d\u4e3a&#8221;resolve&#8221;\u7684\u65b9\u6cd5\uff0c\u5728\u6b64\u5904\u7f16\u5199\u5904\u7406\u903b\u8f91\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Mutations::UpdateEvent<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Mutation<\/span>\r\n  <span class=\"n\">null<\/span> <span class=\"kp\">false<\/span>\r\n\r\n  <span class=\"n\">argument<\/span> <span class=\"ss\">:id<\/span><span class=\"p\">,<\/span>      <span class=\"no\">ID<\/span><span class=\"p\">,<\/span>     <span class=\"ss\">required: <\/span><span class=\"kp\">true<\/span>\r\n  <span class=\"n\">argument<\/span> <span class=\"ss\">:subject<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">argument<\/span> <span class=\"ss\">:body<\/span><span class=\"p\">,<\/span>    <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span>\r\n\r\n  <span class=\"c1\"># \u516c\u5f0f\u306e\u30b5\u30f3\u30d7\u30eb\u3067\u306f\u3001mutation\u306eresponse\u306f { object, errors } \u3092\u8fd4\u3057\u3066\u3044\u307e\u3057\u305f<\/span>\r\n  <span class=\"c1\"># \u30c8\u30c3\u30d7\u30ec\u30d9\u30eb\u306eerror<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:event<\/span><span class=\"p\">,<\/span>    <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">EventType<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:errors<\/span><span class=\"p\">,<\/span>   <span class=\"p\">[<\/span><span class=\"no\">String<\/span><span class=\"p\">],<\/span>         <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n\r\n  <span class=\"c1\"># \u5f15\u6570\u306bargument\u304c\u5165\u3063\u3066\u304f\u308b\u306e\u306fquery\u3068\u540c\u3058\u6319\u52d5<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">:,<\/span> <span class=\"ss\">subject: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">,<\/span> <span class=\"ss\">body: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">event<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nb\">id<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">subject<\/span> <span class=\"o\">=<\/span> <span class=\"n\">subject<\/span> <span class=\"k\">if<\/span> <span class=\"n\">subject<\/span>\r\n    <span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">body<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">body<\/span>    <span class=\"k\">if<\/span> <span class=\"n\">body<\/span>\r\n\r\n    <span class=\"k\">if<\/span> <span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">save<\/span>\r\n      <span class=\"p\">{<\/span> <span class=\"ss\">event: <\/span><span class=\"n\">event<\/span><span class=\"p\">,<\/span> <span class=\"ss\">errors: <\/span><span class=\"p\">[]<\/span> <span class=\"p\">}<\/span>\r\n    <span class=\"k\">else<\/span>\r\n      <span class=\"p\">{<\/span>\r\n        <span class=\"ss\">event: <\/span><span class=\"n\">event<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"ss\">errors: <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">errors<\/span><span class=\"p\">.<\/span><span class=\"nf\">full_messages<\/span>\r\n      <span class=\"p\">}<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"c1\"># \u3053\u3046\u3044\u3046\u66f8\u304d\u65b9\u3067\u3082\u3044\u3044\u304b\u3082 \u5f8c\u8ff0<\/span>\r\n<span class=\"c1\">#   def resolve(id:, subject: nil, body: nil)<\/span>\r\n<span class=\"c1\">#     event = Event.find(id)<\/span>\r\n<span class=\"c1\">#     event.subject = subject if subject<\/span>\r\n<span class=\"c1\">#     event.body    = body    if body<\/span>\r\n\r\n<span class=\"c1\">#     event.valid? &amp;&amp; event.save!<\/span>\r\n<span class=\"c1\">#   rescue ActiveRecord::InvalidRecord =&gt; e<\/span>\r\n<span class=\"c1\">#     # top\u30ec\u30d9\u30eb\u306b\u30a8\u30e9\u30fc\u306e\u7a2e\u985e\u3001\u30a8\u30e9\u30fc\u306e\u8ffd\u52a0\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u3092\u542b\u3081\u3066\u8fd4\u3059<\/span>\r\n<span class=\"c1\">#     raise GraphQL:ExecutionError.new('invalid parameter', extensions: { additional_messages: event.errors.full_messages })  <\/span>\r\n<span class=\"c1\">#   end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h3>\u5ba2\u6237\u7aef\u65b9<\/h3>\n<p>\u5728\u5ba2\u6237\u7aef\u4fa7\uff0c\u4e00\u5207\u4fdd\u6301\u4e0d\u53d8\uff0c\u53ea\u9700\u8981\u6784\u5efa\u67e5\u8be2\u548c\u53d8\u91cf\u7136\u540e\u53d1\u9001\u3002<br \/>\n\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5373\u4f7f\u5728Mutation\u5904\u7406\u4e2d\uff0c\u53c2\u6570\u540d\u4e5f\u662f\u67e5\u8be2\u3002<\/p>\n<p>\u5982\u679c\u53d1\u751f\u66f4\u65b0\u6216\u4fdd\u5b58\u5931\u8d25\uff0c\u9700\u8981\u610f\u8bc6\u5230\u9519\u8bef\u4fe1\u606f\u53ef\u80fd\u4e0d\u4f1a\u51fa\u73b0\u5728\u9876\u5c42\u7684\u4f4d\u7f6e\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">mutation<\/span> <span class=\"n\">UpdateEvent<\/span><span class=\"p\">(<\/span><span class=\"nv\">$id<\/span><span class=\"p\">:<\/span><span class=\"nb\">ID<\/span><span class=\"p\">!,<\/span> <span class=\"nv\">$subject<\/span><span class=\"p\">:<\/span><span class=\"nb\">String<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span> <span class=\"nv\">$body<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">updateEvent<\/span><span class=\"p\">(<\/span><span class=\"n\">id<\/span><span class=\"p\">:<\/span> <span class=\"nv\">$id<\/span><span class=\"p\">,<\/span> <span class=\"n\">subject<\/span><span class=\"p\">:<\/span> <span class=\"nv\">$subject<\/span><span class=\"p\">,<\/span> <span class=\"n\">body<\/span><span class=\"p\">:<\/span> <span class=\"nv\">$body<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">event<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"n\">id<\/span>\r\n      <span class=\"n\">subject<\/span>\r\n      <span class=\"n\">body<\/span>\r\n    <span class=\"p\">}<\/span>\r\n    <span class=\"n\">errors<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u53d8\u91cf<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span> <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">5<\/span><span class=\"p\">,<\/span> <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"11111111\"<\/span> <span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u56de\u61c9 (hu\u00ed<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nl\">\"data\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nl\">\"updateEvent\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nl\">\"event\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"5\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"11111111\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"body\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"asfasdf\"<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nl\">\"errors\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span> <span class=\"err\">\/\/<\/span> <span class=\"err\">\u30a8\u30e9\u30fc\u304c\u3042\u3063\u305f\u5834\u5408\u3053\u3053\u306b\u5165\u3063\u3066\u304f\u308b<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u6b63\u5728\u7814\u7a76\u4e00\u79cd\u65b9\u6cd5\uff0c\u4f7f\u7528 save! \u800c\u4e0d\u662f save \u6765\u5f15\u53d1\u9519\u8bef\uff0c\u5e76\u5728 errors \u7684 extensions \u4e2d\u8fd4\u56de event.errors.full_messages\u3002<\/p>\n<hr \/>\n<h2>\u60ac\u5ff5<\/h2>\n<p>\u6211\u5011\u5c07\u5f9e\u9019\u88e1\u958b\u59cb\uff0c\u5927\u81f4\u5217\u51faGraphQL\u7684\u554f\u984c\uff0c\u4e26\u9010\u4e00\u6aa2\u8996\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u30c6\u30b9\u30c8<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">N+1\u554f\u984c<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u30d5\u30a1\u30a4\u30eb\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9<\/ul>\n<h3>\u8003\u8bd5<\/h3>\n<p>\u516c\u5f0f\u6587\u6863\u4e2d\u5199\u9053\uff0c\u4e0d\u9700\u8981\u8fdb\u884c\u7c7b\u4f3c\u4e8eE2E\u6d4b\u8bd5\u7684\u6d4b\u8bd5\uff0c\u800c\u662f\u8981\u8fdb\u884c\u66f4\u8f7b\u91cf\u7ea7\u7684\u6d4b\u8bd5\u3002<\/p>\n<blockquote><p>\u6d4b\u8bd5GraphQL\u6a21\u5f0f\u884c\u4e3a\u7684\u6700\u7b80\u5355\u65b9\u6cd5\u662f\u5c06\u884c\u4e3a\u62bd\u53d6\u5230\u5355\u72ec\u7684\u5bf9\u8c61\u4e2d\uff0c\u5e76\u5728\u9694\u79bb\u73af\u5883\u4e0b\u6d4b\u8bd5\u8fd9\u4e9b\u5bf9\u8c61\u3002\u5bf9\u4e8eRails\u6846\u67b6\u6765\u8bf4\uff0c\u4f60\u4e0d\u662f\u901a\u8fc7\u8fd0\u884c\u63a7\u5236\u5668\u6d4b\u8bd5\u6765\u6d4b\u8bd5\u6a21\u578b\u7684\u5bf9\u5417\uff1f\u540c\u6837\u5730\uff0c\u4f60\u53ef\u4ee5\u5728\u4e0d\u8fdb\u884c\u7aef\u5230\u7aef\u6d4b\u8bd5\u7684\u60c5\u51b5\u4e0b\uff0c\u5355\u72ec\u6d4b\u8bd5\u7cfb\u7edf\u7684\u201c\u4f4e\u5c42\u201d\u90e8\u5206\u3002<\/p><\/blockquote>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">schema\u5185\u306b(\u305f\u3068\u3048\u3070resolve\u30e1\u30bd\u30c3\u30c9\u306a\u3069)\u30e1\u30bd\u30c3\u30c9\u3092\u3042\u307e\u308a\u66f8\u304b\u305a\u306b\u30e2\u30c7\u30eb\u306b\u5bc4\u305b\u308b\u3053\u3068<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">(\u305d\u3046\u3057\u3066\u304a\u3051\u3070)schema\u306f\u6b86\u3069\u306e\u5834\u5408model\u306emethod, attribute\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u3001\u305d\u306e\u30c6\u30b9\u30c8\u3092\u3061\u3083\u3093\u3068\u66f8\u304f\u3053\u3068<\/ul>\n<p>\u542c\u8bf4\u662f\u8fd9\u6837\u7684\u3002<\/p>\n<p>\u5982\u679c\u4e00\u5b9a\u8981\u8fdb\u884cE2E\u6d4b\u8bd5\uff0c\u53ef\u4ee5\u6d4b\u8bd5MySchema.execute\uff0c\u56e0\u4e3agraphql_controller\u5f88\u8584\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"n\">describe<\/span> <span class=\"s1\">'#execute'<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">subject<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"no\">MySchema<\/span><span class=\"p\">.<\/span><span class=\"nf\">execute<\/span><span class=\"p\">(<\/span>\r\n        <span class=\"n\">query<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"ss\">context: <\/span><span class=\"n\">context<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"ss\">variables: <\/span><span class=\"n\">variables<\/span>\r\n        <span class=\"p\">}<\/span>\r\n      <span class=\"p\">)<\/span>\r\n  <span class=\"p\">}<\/span>\r\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:context<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"p\">{}<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:variables<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"p\">{}<\/span> <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"n\">describe<\/span> <span class=\"s1\">'get event by id'<\/span> <span class=\"k\">do<\/span>\r\n    <span class=\"n\">context<\/span> <span class=\"s1\">'when Event.find(id) exists'<\/span> <span class=\"k\">do<\/span>\r\n      <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:query<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> \r\n        <span class=\"sx\">%| \r\n          query Event ($id:ID!) { \r\n            event(id: $id) {\r\n              id\r\n              subject\r\n            } \r\n          } \r\n        |<\/span>\r\n      <span class=\"p\">}<\/span>\r\n      <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:variables<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"p\">{<\/span><span class=\"ss\">id: <\/span><span class=\"mi\">1<\/span><span class=\"p\">}<\/span> <span class=\"p\">}<\/span> \r\n\r\n      <span class=\"n\">it<\/span> <span class=\"s1\">'returns event with id, subject'<\/span> <span class=\"k\">do<\/span>\r\n        <span class=\"c1\"># <\/span>\r\n        <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">subject<\/span><span class=\"p\">).<\/span><span class=\"nf\">have_key<\/span><span class=\"p\">(<\/span><span class=\"ss\">:id<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">subject<\/span><span class=\"p\">).<\/span><span class=\"nf\">have_key<\/span><span class=\"p\">(<\/span><span class=\"ss\">:subject<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u6709\u4e00\u79cd\u9884\u611f\uff0c\u5b83\u6bd4\u4f20\u7edf\u7684\u8bf7\u6c42\u89c4\u8303\u66f4\u5feb\uff08\u5c1a\u672a\u8fdb\u884c\u6d4b\u91cf\uff09\u3002<\/p>\n<h3>N+1\u95ee\u9898<\/h3>\n<p>Graphql\u4e2d\u7531\u4e8e\u67e5\u8be2\u7684\u81ea\u7531\u6027\uff0c\u5bb9\u6613\u51fa\u73b0 N+1 \u95ee\u9898\u3002\u4f8b\u5982\uff0c<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">query<\/span> <span class=\"n\">Events<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">events<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">edges<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"n\">id<\/span>\r\n            <span class=\"n\">subject<\/span>\r\n            <span class=\"n\">user<\/span> <span class=\"p\">{<\/span> <span class=\"c\"># \u3053\u3053\uff01<\/span>\r\n                <span class=\"n\">id<\/span>\r\n            <span class=\"p\">}<\/span>\r\n        <span class=\"p\">}<\/span>\r\n    <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u5f53\u4f7f\u7528\u8fd9\u6837\u7684\u67e5\u8be2\u65f6\uff0c\u6bcf\u4e2a\u4e8b\u4ef6\u90fd\u8981\u9488\u5bf9\u7528\u6237\u8fdb\u884c\u4e00\u6b21\u4e00\u6b21\u7684\u8be2\u95ee\u3002<\/p>\n<p>\u5728\u8fd9\u4e2a\u89e3\u51b3\u65b9\u6848\u4e2d\uff0c\u901a\u8fc7\u904d\u5386SQL\u67e5\u8be2\u5e76\u6536\u96c6\u76f8\u5173\u8054\u7684ID\uff08\u53ef\u4ee5\u4f7f\u7528\u5176\u4ed6\u5217\uff09\uff0c\u7136\u540e\u4f7f\u7528\u6536\u96c6\u5230\u7684ID\u4e00\u6b21\u6027\u53d1\u9001\u6279\u91cf\u67e5\u8be2\u7684\u673a\u5236\uff0cgraphql-batch\u63d0\u4f9b\u4e86\u8fd9\u4e2a\u529f\u80fd\uff08\u7531Shopify\u5236\u4f5c\uff09\u3002<\/p>\n<h4>\u5b89\u88c5<\/h4>\n<pre class=\"post-pre\"><code><span class=\"n\">gem<\/span> <span class=\"s1\">'graphql-batch'<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>bundle <span class=\"nb\">install<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">MySchema<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span>\r\n  <span class=\"n\">query<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">QueryType<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"n\">mutation<\/span><span class=\"p\">(<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MutationType<\/span><span class=\"p\">)<\/span>\r\n\r\n  <span class=\"n\">use<\/span><span class=\"p\">(<\/span><span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Batch<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># \u8aad\u307f\u8fbc\u307f<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h4>\u8ba9\u6211\u4eec\u7b80\u5355\u5b9e\u65bd\u4e00\u4e0b\u3002<\/h4>\n<p>\u7531\u4e8e`gem`\u516c\u5f0f\u4e2d\u7684\u793a\u4f8b\u80fd\u591f\u6b63\u5e38\u8fd0\u884c\uff0c\u6211\u4eec\u5c06\u76f4\u63a5\u4f7f\u7528\u8fd9\u4e2a\u793a\u4f8b\u3002<br \/>\n\u8bf7\u53c2\u8003\u4ee5\u4e0b\u94fe\u63a5\uff1a<br \/>\nhttps:\/\/github.com\/Shopify\/graphql-batch\/blob\/master\/examples\/record_loader.rb<\/p>\n<pre class=\"post-pre\"><code>\r\n<span class=\"c1\"># event\u306fuser_id\u3092\u3082\u3061\u3001belongs_to :user \u3067\u3042\u308b\u3068\u3057\u307e\u3059<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">Types::EventType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Schema<\/span><span class=\"o\">::<\/span><span class=\"no\">Object<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:id<\/span><span class=\"p\">,<\/span>        <span class=\"no\">ID<\/span><span class=\"p\">,<\/span>                    <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:subject<\/span><span class=\"p\">,<\/span>   <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:body<\/span><span class=\"p\">,<\/span>      <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:bodyHtml<\/span><span class=\"p\">,<\/span>  <span class=\"no\">String<\/span><span class=\"p\">,<\/span>                <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">body_html<\/span>\r\n    <span class=\"n\">object<\/span><span class=\"p\">.<\/span><span class=\"nf\">decorate<\/span><span class=\"p\">.<\/span><span class=\"nf\">body_html<\/span>\r\n  <span class=\"k\">end<\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:createdAt<\/span><span class=\"p\">,<\/span> <span class=\"no\">ScalarTypes<\/span><span class=\"o\">::<\/span><span class=\"no\">DateTime<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"c1\"># UserType\u306f\u5225\u9014\u5b9a\u7fa9\u3057\u305f\u3068\u3057\u307e\u3059\u3002\u672c\u6765event\u306buser\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308c\u308b\u306e\u3067\u306a\u306b\u3082\u305b\u305a\u3068\u3082resolve\u3067\u304d\u307e\u3059\u304c\u3001<\/span>\r\n  <span class=\"c1\"># \u305d\u308c\u3092\u7528\u3044\u305a\u3001graphql-batch\u3092\u7528\u3044\u305fresolve\u3092\u3057\u307e\u3059<\/span>\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"n\">field<\/span> <span class=\"ss\">:user<\/span><span class=\"p\">,<\/span>      <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">UserType<\/span><span class=\"p\">,<\/span>       <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># resolve\u3067\u306fuser\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u8fd4\u3055\u305a\u3001\u4e00\u65e6Promise\u3092\u8fd4\u3057\u3001sql\u554f\u3044\u5408\u308f\u305b\u3092\u4fdd\u7559\u3057\u307e\u3059<\/span>\r\n  <span class=\"c1\"># Promise\u306e\u8a73\u7d30\u306f https:\/\/github.com\/lgierth\/promise.rb \u306b\u3042\u308a\u307e\u3059<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">user<\/span>\r\n    <span class=\"c1\"># Loaders::RecordLoader.new(User, User.primary_key).load(object.user_id)\u3068\u540c\u3058<\/span>\r\n    <span class=\"no\">Loaders<\/span><span class=\"o\">::<\/span><span class=\"no\">RecordLoader<\/span><span class=\"p\">.<\/span><span class=\"nf\">for<\/span><span class=\"p\">(<\/span><span class=\"no\">User<\/span><span class=\"p\">).<\/span><span class=\"nf\">load<\/span><span class=\"p\">(<\/span><span class=\"n\">object<\/span><span class=\"p\">.<\/span><span class=\"nf\">user_id<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Loaders::RecordLoader<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Batch<\/span><span class=\"o\">::<\/span><span class=\"no\">Loader<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># @param [ActiveRecord::Base] model<\/span>\r\n  <span class=\"c1\"># !@param [String] column<\/span>\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span><span class=\"p\">(<\/span><span class=\"n\">model<\/span><span class=\"p\">,<\/span> <span class=\"ss\">column: <\/span><span class=\"n\">model<\/span><span class=\"p\">.<\/span><span class=\"nf\">primary_key<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"vi\">@model<\/span>       <span class=\"o\">=<\/span> <span class=\"n\">model<\/span>\r\n    <span class=\"vi\">@column<\/span>      <span class=\"o\">=<\/span> <span class=\"n\">column<\/span><span class=\"p\">.<\/span><span class=\"nf\">to_s<\/span>\r\n    <span class=\"vi\">@column_type<\/span> <span class=\"o\">=<\/span> <span class=\"n\">model<\/span><span class=\"p\">.<\/span><span class=\"nf\">type_for_attribute<\/span><span class=\"p\">(<\/span><span class=\"vi\">@column<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># load\u3059\u308b\u305f\u3073\u306b\u3042\u3068\u3067\u691c\u7d22\u306b\u7528\u3044\u308bkey(\u901a\u5e38id)\u3092\u305f\u3081\u3053\u307f\u3001Promise\u3092\u8fd4\u3059<\/span>\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"c1\"># @param [Any] key ... \u901a\u5e38\u306fid<\/span>\r\n  <span class=\"c1\"># @return [Promise]<\/span>\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">load<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">super<\/span> <span class=\"vi\">@column_type<\/span><span class=\"p\">.<\/span><span class=\"nf\">cast<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"c1\">#<\/span>\r\n  <span class=\"c1\"># \u8caf\u3081\u305fkeys(ids)\u3092\u5143\u306b\u4e00\u62ec\u3067\u30ec\u30b3\u30fc\u30c9\u3092\u53d6\u5f97 query(keys)\u306e\u304b\u3057\u3087<\/span>\r\n  <span class=\"c1\"># Promise\u3068\u3057\u3066\u3044\u305f\u7b87\u6240\u3092fulfill = \u5b8c\u4e86\u3057\u3001\u5b9f\u969b\u306e\u30ec\u30b3\u30fc\u30c9\u3092\u8fd4\u3059<\/span>\r\n  <span class=\"c1\"># <\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">perform<\/span><span class=\"p\">(<\/span><span class=\"n\">keys<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">query<\/span><span class=\"p\">(<\/span><span class=\"n\">keys<\/span><span class=\"p\">).<\/span><span class=\"nf\">each<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">record<\/span><span class=\"o\">|<\/span>\r\n      <span class=\"c1\"># value: id\u306e\u5024\u3002<\/span>\r\n      <span class=\"n\">value<\/span> <span class=\"o\">=<\/span> <span class=\"vi\">@column_type<\/span><span class=\"p\">.<\/span><span class=\"nf\">cast<\/span><span class=\"p\">(<\/span><span class=\"n\">record<\/span><span class=\"p\">.<\/span><span class=\"nf\">public_send<\/span><span class=\"p\">(<\/span><span class=\"vi\">@column<\/span><span class=\"p\">))<\/span>\r\n      <span class=\"c1\"># \u6e9c\u3081\u8fbc\u3093\u3060Promise\u306e\u3046\u3061\u3001key = 1\u306epromise\u306b\u5bfe\u3057\u3066record\u3092\u5272\u308a\u5f53\u3066\u3066Promise\u3092\u5b8c\u4e86 = fulfill\u3059\u308b<\/span>\r\n      <span class=\"c1\"># \u540c\u3058id\u3092key\u306b\u3082\u3064Promise\u304c\u8907\u6570\u3042\u3063\u3066\u3082\u3001\u4e00\u62ec\u3067fulfill\u3055\u308c\u308b<\/span>\r\n      <span class=\"n\">fulfill<\/span><span class=\"p\">(<\/span><span class=\"n\">value<\/span><span class=\"p\">,<\/span> <span class=\"n\">record<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"c1\"># \u6b8b\u3063\u3066\u3044\u308bkey\u306b\u5bfe\u3059\u308bPromise\u306frecord\u304c\u898b\u3064\u304b\u3089\u306a\u304b\u3063\u305f\u3053\u3068\u3092\u610f\u5473\u3059\u308b\u306e\u3067<\/span>\r\n    <span class=\"n\">keys<\/span><span class=\"p\">.<\/span><span class=\"nf\">each<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">key<\/span><span class=\"o\">|<\/span> <span class=\"n\">fulfill<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">,<\/span> <span class=\"kp\">nil<\/span><span class=\"p\">)<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">fulfilled?<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"kp\">private<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">query<\/span><span class=\"p\">(<\/span><span class=\"n\">keys<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">scope<\/span> <span class=\"o\">=<\/span> <span class=\"vi\">@model<\/span>\r\n    <span class=\"n\">scope<\/span><span class=\"p\">.<\/span><span class=\"nf\">where<\/span><span class=\"p\">(<\/span><span class=\"vi\">@column<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">keys<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u8fd9\u6b21\u7684\u662f\u4e00\u79cd\u5c5e\u4e8eLoader\u7c7b\u578b\u7684Event\uff0c\u5176\u4e2d\u6709\u7528\u6237ID\u5b58\u5728\u3002\u8fd8\u6709\u53e6\u4e00\u79cd\u5c5e\u4e8ehas_many\u7684Loader\u4e5f\u63d0\u4f9b\u4e86\u4f8b\u5b50\uff0c\u56e0\u6b64\u53ef\u4ee5\u53c2\u8003\u90a3\u4e2a\u6765\u89e3\u51b3N+1\u7684\u95ee\u9898\u3002<\/p>\n<h4>\u8bf7\u63d0\u4f9b\u66f4\u5177\u4f53\u7684\u4e0a\u4e0b\u6587\uff0c\u4ee5\u4fbf\u6211\u80fd\u591f\u51c6\u786e\u5730\u4e3a\u60a8\u8fdb\u884c\u4e2d\u6587\u7684\u540c\u4e49\u8f6c\u8ff0\u3002<\/h4>\n<p>\u4ee5\u4e0b\u662f\u4e24\u4e2a\u535a\u5ba2\u7684\u94fe\u63a5\uff1a<br \/>\n<iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" title=\"graphql-batch \u3067\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u3078\u306e\u30af\u30a8\u30ea\u3092\u6e1b\u3089\u3059 - ESM \u30a2\u30b8\u30e3\u30a4\u30eb\u4e8b\u696d\u90e8 \u958b\u767a\u8005\u30d6\u30ed\u30b0\" src=\"https:\/\/hatenablog-parts.com\/embed?url=http%3A%2F%2Fblog.agile.esm.co.jp%2Fentry%2F2017%2F06%2F16%2F113248#?secret=TYz0Dw3Lcl\" data-secret=\"TYz0Dw3Lcl\" scrolling=\"no\" frameborder=\"0\"><\/iframe><br \/>\n<iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" title=\"GraphQL::Batch\u306e\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u3092\u8aad\u3080 &amp; \u4f7f\u3063\u3066\u307f\u308b - kymmt\" src=\"https:\/\/hatenablog-parts.com\/embed?url=http%3A%2F%2Fblog.kymmt.com%2Fentry%2Fgraphql-batch-examples#?secret=NKmfGvFlUp\" data-secret=\"NKmfGvFlUp\" scrolling=\"no\" frameborder=\"0\"><\/iframe><\/p>\n<h3>\u6587\u4ef6\u5904\u7406<\/h3>\n<p>\u7f16\u5199\u4e00\u4e2a\u50cf\u53d1\u9001\u6587\u4ef6\u90a3\u6837\u7684Mutation\u9700\u8981\u4e00\u4e9b\u989d\u5916\u7684\u5de5\u4f5c\uff0c\u4f46\u5b9e\u9645\u7f16\u5199\u65f6\u4e00\u5207\u90fd\u4f1a\u987a\u5229\u8fdb\u884c\uff0c\u6ca1\u6709\u7279\u522b\u56f0\u96be\u7684\u5730\u65b9\u3002<\/p>\n<p>\u5982\u4f55\u5728Apollo + Rails\uff08GraphQL\u670d\u52a1\u5668\uff09\u4e2d\u521b\u5efa\u7528\u4e8e\u4e0a\u4f20\u6587\u4ef6\u7684mutation\u65b9\u6cd5 &#8211; Qiita<\/p>\n<p>\u53ea\u8981\u4f7f\u7528apollo-client\uff0c\u6587\u4ef6\u4e0a\u4f20\u5c31\u53ef\u4ee5\u987a\u5229\u5b9e\u73b0\u3002<\/p>\n<h2>\u6700\u540e<\/h2>\n<p>\u4e86\u89e3\u8bf7\u6c42\/\u54cd\u5e94\u6d41\u7a0b\u3001\u67e5\u8be2\u3001Schema\u3001\u89e3\u6790\u3001\u7c7b\u578b\u3001\u6d4b\u8bd5\u3001\u6587\u4ef6\u5904\u7406\u3001\u9519\u8bef\u5904\u7406\u7b49\u51e0\u4e2a\u4e3b\u8981\u77e5\u8bc6\u70b9\uff0c\u57fa\u672c\u4e0a\u5e94\u8be5\u80fd\u591f\u5b8c\u6210\u5f00\u53d1\u7684\u6574\u4e2a\u8fc7\u7a0b\uff01<\/p>\n<p>\u867d\u7136\u8fd8\u6709\u4e00\u4e9b\u672a\u89e3\u91ca\u7684\u5730\u65b9\uff0c\u50cf`execute`\u7684\u9009\u9879\uff0c`MySchema`\u7684\u914d\u7f6e\uff0c\u7f13\u5b58\uff0c\u76d1\u63a7\u7b49\u7b49\uff0c\u4f46\u6211\u8ba4\u4e3a\u8fd9\u4e9b\u5c06\u4f1a\u5728\u4ee5\u540e\u9010\u6b65\u4e86\u89e3\u3002<br \/>\n\u5982\u679c\u6709\u7591\u60d1\uff0c\u5efa\u8bae\u957f\u65f6\u95f4\u6d4f\u89c8 http:\/\/graphql-ruby.org\/guides\u3002<\/p>\n<p>\u53e6\u5916\uff0c\u7531\u4e8egraphql-ruby\u7684\u5b9e\u73b0\u5e76\u4e0d\u5341\u5206\u590d\u6742\uff08\u800c\u4e14\u5b98\u65b9\u6587\u6863\u6709\u4e9b\u5730\u65b9\u53ef\u80fd\u6709\u70b9\u8fc7\u65f6\uff09\uff0c\u5efa\u8bae\u60a8\u4e5f\u53ef\u4ee5\u53bb\u67e5\u770b\u4e00\u4e0b\u5b9e\u73b0\u4ee3\u7801\u3002<\/p>\n<p>\u5e0c\u671b\u8fd9\u7bc7\u6587\u7ae0\u80fd\u591f\u4fc3\u8fdb\u66f4\u591a\u4eba\u5f00\u59cb\u4f7f\u7528Graphql\uff0c \u7948\u7977\u8fd9\u79cd\u60c5\u51b5\u80fd\u591f\u53d1\u751f\uff01<\/p>\n<p>\u5982\u679c\u6709\u559c\u6b22\u7684\u4eba\u5728\uff0c\u8bf7\u7b49\u5f85\u4ed6\u4eec\u7684\u5c0f\u8d39\u6350\u8d60\uff01<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/246-0.jpeg\" alt=\"image_from_ios.jpg\" \/><\/div>\n<h2>\u4ed6\u53ef\u4ee5\u53c2\u8003\u7684\u6587\u7ae0\u94fe\u63a5<\/h2>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">GraphQL Coding Style Guide | bitjourney Kibela<\/ul>\n<\/li>\n<\/ul>\n<p>https:\/\/bitjourney.kibe.la\/shared\/entries\/1f26acbe-315f-42b8-9ecd-11bcaac5b697<\/p>\n<p>Scrapbox<\/p>\n<p>https:\/\/scrapbox.io\/graphql-ruby-ja\/<\/p>\n<p>GraphQL\u306f\u4f55\u306b\u5411\u3044\u3066\u3044\u308b\u304b &#8211; k0kubun&#8217;s blog<\/p>\n<p><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" title=\"GraphQL\u306f\u4f55\u306b\u5411\u3044\u3066\u3044\u308b\u304b - k0kubun&#039;s blog\" src=\"https:\/\/hatenablog-parts.com\/embed?url=https%3A%2F%2Fk0kubun.hatenablog.com%2Fentry%2Fgraphql#?secret=TqpXammQhy\" data-secret=\"TqpXammQhy\" scrolling=\"no\" frameborder=\"0\"><\/iframe><\/p>\n<p>\u4e16\u306e\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u30a8\u30f3\u30b8\u30cb\u30a2\u306bApollo Client\u3092\u5e03\u6559\u3057\u305f\u3044 &#8211; Qiita<\/p>\n<p>https:\/\/qiita.com\/seya\/items\/26c8a0dc549a10efcdf8<\/p>\n<p>Rails\u3067GraphQL API\u3092\u4f5c\u308b\u6642\u306b\u60a9\u3093\u30605\u3064\u306e\u3053\u3068 | \u30b9\u30da\u30fc\u30b9\u30de\u30fc\u30b1\u30c3\u30c8\u30d6\u30ed\u30b0<\/p>\n<blockquote class=\"wp-embedded-content\" data-secret=\"dBan6YPpLJ\"><p><a href=\"https:\/\/blog.spacemarket.com\/code\/graphql-ruby-concerns\/\">Rails\u3067GraphQL API\u3092\u4f5c\u308b\u6642\u306b\u60a9\u3093\u30605\u3064\u306e\u3053\u3068<\/a><\/p><\/blockquote>\n<p><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Rails\u3067GraphQL API\u3092\u4f5c\u308b\u6642\u306b\u60a9\u3093\u30605\u3064\u306e\u3053\u3068&#8221; &#8212; \u30b9\u30da\u30fc\u30b9\u30de\u30fc\u30b1\u30c3\u30c8\u30d6\u30ed\u30b0\" src=\"https:\/\/blog.spacemarket.com\/code\/graphql-ruby-concerns\/embed\/#?secret=dBan6YPpLJ\" data-secret=\"dBan6YPpLJ\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/p>\n<p>GraphQL | Issus(\u30a4\u30b7\u30e5\u30fc\u30ba)<\/p>\n<p>https:\/\/issus.me\/projects\/141<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u9996\u5148 \u7684 Chinese paraphrase for &#8220;\u76ee\u7684&#8221; could be &#038; [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-47630","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011 - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u5f00\u59cb\u4f7f\u7528-graphql-ruby\u3010\u57fa\u4e8e\u7c7b\u7684api\u3011\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011\" \/>\n<meta property=\"og:description\" content=\"\u9996\u5148 \u7684 Chinese paraphrase for &#8220;\u76ee\u7684&#8221; could be &amp; [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u5f00\u59cb\u4f7f\u7528-graphql-ruby\u3010\u57fa\u4e8e\u7c7b\u7684api\u3011\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-15T20:01:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-29T19:45:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/0-0.png\" \/>\n<meta name=\"author\" content=\"\u65b0, \u97f5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u65b0, \u97f5\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/\",\"name\":\"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2024-01-15T20:01:30+00:00\",\"dateModified\":\"2024-04-29T19:45:45+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\",\"name\":\"\u65b0, \u97f5\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"caption\":\"\u65b0, \u97f5\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011 - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u5f00\u59cb\u4f7f\u7528-graphql-ruby\u3010\u57fa\u4e8e\u7c7b\u7684api\u3011\/","og_locale":"zh_CN","og_type":"article","og_title":"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011","og_description":"\u9996\u5148 \u7684 Chinese paraphrase for &#8220;\u76ee\u7684&#8221; could be & [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u5f00\u59cb\u4f7f\u7528-graphql-ruby\u3010\u57fa\u4e8e\u7c7b\u7684api\u3011\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2024-01-15T20:01:30+00:00","article_modified_time":"2024-04-29T19:45:45+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7fdb913a08637a6a7d7b\/0-0.png"}],"author":"\u65b0, \u97f5","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u65b0, \u97f5","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"9 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/","name":"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2024-01-15T20:01:30+00:00","dateModified":"2024-04-29T19:45:45+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u5f00\u59cb\u4f7f\u7528 GraphQL Ruby\u3010\u57fa\u4e8e\u7c7b\u7684API\u3011"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9","name":"\u65b0, \u97f5","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","caption":"\u65b0, \u97f5"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-graphql-ruby%e3%80%90%e5%9f%ba%e4%ba%8e%e7%b1%bb%e7%9a%84api%e3%80%91\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47630","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=47630"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47630\/revisions"}],"predecessor-version":[{"id":89486,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47630\/revisions\/89486"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=47630"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=47630"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=47630"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}