{"id":47723,"date":"2023-10-13T20:20:08","date_gmt":"2023-08-31T11:19:41","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/"},"modified":"2024-05-04T04:04:44","modified_gmt":"2024-05-03T20:04:44","slug":"%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/","title":{"rendered":"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL"},"content":{"rendered":"<h1>\u76ee\u6807<\/h1>\n<p>\u786e\u8ba4\u5728\u4f7f\u7528 Rails \u548c GraphQL \u7684\u65f6\u5019\uff0c\u5199\u4f5c\u4f1a\u662f\u4ec0\u4e48\u6837\u5b50\u7684\u3002<\/p>\n<h1>\u5fc5\u9700\u54c1 (b\u00ec x\u016b<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Docker(\u4eca\u56de\u4f7f\u7528\u30d0\u30fc\u30b8\u30e7\u30f3: Docker version 20.10.12, build e91ed57)<\/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\">VSCode(Remote Develpment \u62e1\u5f35\u6a5f\u80fd\u3092\u4f7f\u7528, \u4eca\u56de\u4f7f\u7528\u30d0\u30fc\u30b8\u30e7\u30f3: Version: 1.64.1)<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u30d6\u30e9\u30a6\u30b6(\u4eca\u56de\u306f Chrome \u30d0\u30fc\u30b8\u30e7\u30f3: 98.0.4758.80\uff08Official Build\uff09 \u3092\u4f7f\u7528)<\/ul>\n<h1>\u642d\u5efa\u5f00\u53d1\u73af\u5883<\/h1>\n<h2>\u4f7f\u7528VSCode\u542f\u52a8\u5e76\u521b\u5efaDockerfile\u6765\u542f\u52a8\u865a\u62df\u73af\u5883\u3002<\/h2>\n<p>\u5728VSCode\u4e2d\u6253\u5f00\u4e00\u4e2a\u7528\u4e8e\u5f00\u53d1\u7684\u7a7a\u6587\u4ef6\u5939\uff08\u4f8b\u5982\uff0c\u8fd9\u91cc\u8bbe\u4e3a \/dev\/rails_graphql\uff09\u3002<\/p>\n<p>\u521b\u5efa\u4e00\u4e2a\u9002\u7528\u4e8e Ruby \u73af\u5883\u7684 Dockerfile\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">FROM<\/span><span class=\"s\"> ruby<\/span>\r\n<\/code><\/pre>\n<p>\u4f7f\u7528VSCode\u7684&#8221;Reopen in Container&#8221;\u547d\u4ee4\uff0c\u53ef\u4ee5\u4eceDockerfile\u5207\u6362\u5230\u865a\u62df\u73af\u5883\u3002<\/p>\n<h2>\u521b\u5efa\u7528\u4e8e\u5b89\u88c5 Rails \u7684 Gemfile\u3002<\/h2>\n<pre class=\"post-pre\"><code><span class=\"n\">source<\/span> <span class=\"s2\">\"https:\/\/rubygems.org\"<\/span>\r\n<span class=\"n\">gem<\/span> <span class=\"s1\">'rails'<\/span>\r\n<\/code><\/pre>\n<h2>\u6253\u5f00 VSCode \u7684\u7ec8\u7aef\u5e76\u5b89\u88c5 gem\u3002<\/h2>\n<pre class=\"post-pre\"><code>bundle <span class=\"nb\">install<\/span>\r\n<\/code><\/pre>\n<h2>\u786e\u8ba4Ruby\u548cRails\u7684\u7248\u672c<\/h2>\n<pre class=\"post-pre\"><code>ruby <span class=\"nt\">-v<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>ruby 3.1.0p0 <span class=\"o\">(<\/span>2021-12-25 revision fb4df44d16<span class=\"o\">)<\/span> <span class=\"o\">[<\/span>x86_64-linux]\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>rails <span class=\"nt\">-v<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>Rails 7.0.2.2\r\n<\/code><\/pre>\n<h2>\u521b\u5efa\u4e00\u4e2aRails\u9879\u76ee<\/h2>\n<pre class=\"post-pre\"><code>rails new <span class=\"nt\">--api<\/span> <span class=\"nt\">--minimal<\/span> <span class=\"nb\">.<\/span>\r\n<\/code><\/pre>\n<h2>\u786e\u8ba4\u884c\u52a8<\/h2>\n<p>\u542f\u52a8\u670d\u52a1\u5668<\/p>\n<pre class=\"post-pre\"><code>rails s\r\n<\/code><\/pre>\n<p>\u5982\u679c\u8bbf\u95eehttp:\/\/localhost:3000\uff0c\u60a8\u53ef\u4ee5\u786e\u8ba4Rails\u6b63\u5728\u8fd0\u884c\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/25-0.png\" alt=\"image.png\" \/><\/div>\n<h2>\u6dfb\u52a0\u9002\u7528\u4e8e GraphQL \u7684\u5b9d\u77f3 (gem)\u3002<\/h2>\n<pre class=\"post-pre\"><code>bundle add graphql\r\n<span class=\"hdl\"><span class=\"o\">- <\/span>bundle add <span class=\"nt\">--group<\/span> development graphiql sass-rails\r\n<\/span><span class=\"hil\"><span class=\"o\">+ <\/span>bundle add <span class=\"nt\">--group<\/span> development graphiql-rails sass-rails\r\n<\/span><\/code><\/pre>\n<p>\u203b graphiql \u662f\u7528\u4e8e\u5f00\u53d1\u7684\u5de5\u5177\uff0c\u800c sass-rails \u662f graphiql \u8fd0\u884c\u6240\u5fc5\u9700\u7684\u3002<\/p>\n<h2>\u751f\u6210\u4e0egraphql\u76f8\u5173\u7684\u6587\u4ef6<\/h2>\n<pre class=\"post-pre\"><code>rails g graphql:install\r\n<\/code><\/pre>\n<h1>\u8c03\u6574\u914d\u7f6e\u4ee5\u4f7fGraphiQL\u8fd0\u884c<\/h1>\n<h3>\u542f\u7528\u4f1a\u8bdd<\/h3>\n<p>\u5728 application.rb \u6587\u4ef6\u4e2d\u6dfb\u52a0\u4e86\u4e24\u884c\u4ee3\u7801\u3002<\/p>\n<pre class=\"post-pre\"><code>  <span class=\"n\">config<\/span><span class=\"p\">.<\/span><span class=\"nf\">middleware<\/span><span class=\"p\">.<\/span><span class=\"nf\">use<\/span> <span class=\"no\">ActionDispatch<\/span><span class=\"o\">::<\/span><span class=\"no\">Cookies<\/span>\r\n  <span class=\"n\">config<\/span><span class=\"p\">.<\/span><span class=\"nf\">middleware<\/span><span class=\"p\">.<\/span><span class=\"nf\">use<\/span> <span class=\"no\">ActionDispatch<\/span><span class=\"o\">::<\/span><span class=\"no\">Session<\/span><span class=\"o\">::<\/span><span class=\"no\">CookieStore<\/span>\r\n<\/code><\/pre>\n<h3>\u5728\u8def\u5f84\u4e0a\u6dfb\u52a0\u8bbe\u7f6e\u3002<\/h3>\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\">\"\/graphql\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>\u786e\u8ba4\u884c\u52a8.<\/h2>\n<p>\u5728\u7ec8\u7aef\u8fd0\u884c `rails s` \u542f\u52a8\u670d\u52a1\u5668\uff0c\u7136\u540e\u8bbf\u95ee http:\/\/localhost:3000\/graphiql\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/39-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u6267\u884c\u4e3a\u6d4b\u8bd5\u751f\u6210\u7684\u67e5\u8be2<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/41-0.png\" alt=\"image.png\" \/><\/div>\n<h1>\u521b\u5efaGraphQL\u67e5\u8be2<\/h1>\n<p>\u6211\u5011\u9019\u6b21\u6253\u7b97\u88fd\u4f5c\u4e00\u500b\u9810\u8a08\u4f7f\u7528\u6d3b\u52d5\u65e5\u7a0b\u8868\u7684API\u3002<\/p>\n<p>\u9996\u5148\uff0c\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u7528\u4e8e\u7ba1\u7406\u4e8b\u4ef6\u65e5\u7a0b\u7684\u6a21\u578b\u548cREST API\u3002<\/p>\n<pre class=\"post-pre\"><code>rails g scaffold Event title:string:index start_at:datetime:index end_at:datetime place:string:index tags:string memo:text canceled:boolean:index\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      invoke  active_record\r\n      create    db\/migrate\/20220213115441_create_events.rb\r\n      create    app\/models\/event.rb\r\n      invoke    test_unit\r\n      create      test\/models\/event_test.rb\r\n      create      test\/fixtures\/events.yml\r\n      invoke  resource_route\r\n       route    resources :events\r\n      invoke  scaffold_controller\r\n      create    app\/controllers\/events_controller.rb\r\n      invoke    resource_route\r\n      invoke    test_unit\r\n      create      test\/controllers\/events_controller_test.rb\r\n<\/code><\/pre>\n<p>\u4e0b\u4e00\u6b65\u6211\u4eec\u8981\u751f\u6210\u53c2\u4e0e\u8005\u5217\u8868<\/p>\n<pre class=\"post-pre\"><code>rails g scaffold Member name:string:index email:string:uniq\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      invoke  active_record\r\n      create    db\/migrate\/20220213115747_create_members.rb\r\n      create    app\/models\/member.rb\r\n      invoke    test_unit\r\n      create      test\/models\/member_test.rb\r\n      create      test\/fixtures\/members.yml\r\n      invoke  resource_route\r\n       route    resources :members\r\n      invoke  scaffold_controller\r\n      create    app\/controllers\/members_controller.rb\r\n      invoke    resource_route\r\n      invoke    test_unit\r\n      create      test\/controllers\/members_controller_test.rb\r\n<\/code><\/pre>\n<p>\u6700\u540e\u751f\u6210\u53c2\u52a0\u6d3b\u52a8\u7684\u4eba\u6570\u3002<\/p>\n<pre class=\"post-pre\"><code>rails g scaffold EventMember event:references member:references presented:boolean:index\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      invoke  active_record\r\n      create    db\/migrate\/20220213115822_create_event_members.rb\r\n      create    app\/models\/event_member.rb\r\n      invoke    test_unit\r\n      create      test\/models\/event_member_test.rb\r\n      create      test\/fixtures\/event_members.yml\r\n      invoke  resource_route\r\n       route    resources :event_members\r\n      invoke  scaffold_controller\r\n      create    app\/controllers\/event_members_controller.rb\r\n      invoke    resource_route\r\n      invoke    test_unit\r\n      create      test\/controllers\/event_members_controller_test.rb\r\n<\/code><\/pre>\n<h2>\u5c06\u975e\u7a7a\u503c\u6216\u9ed8\u8ba4\u503c\u6dfb\u52a0\u5230\u8bbe\u7f6e\u4e2d\u3002<\/h2>\n<pre class=\"post-pre\"><code><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\">7.0<\/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\">string<\/span> <span class=\"ss\">:title<\/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\">datetime<\/span> <span class=\"ss\">:start_at<\/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\">datetime<\/span> <span class=\"ss\">:end_at<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span> <span class=\"ss\">:place<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span> <span class=\"ss\">:tags<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">text<\/span> <span class=\"ss\">:memo<\/span>\r\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">boolean<\/span> <span class=\"ss\">:canceled<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span> <span class=\"ss\">default: <\/span><span class=\"kp\">false<\/span>\r\n\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=\"n\">add_index<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:title<\/span>\r\n    <span class=\"n\">add_index<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:start_at<\/span>\r\n    <span class=\"n\">add_index<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:place<\/span>\r\n    <span class=\"n\">add_index<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:canceled<\/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\">CreateMembers<\/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\">7.0<\/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\">:members<\/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\">string<\/span> <span class=\"ss\">:name<\/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\">string<\/span> <span class=\"ss\">:email<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n\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=\"n\">add_index<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:name<\/span>\r\n    <span class=\"n\">add_index<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:email<\/span><span class=\"p\">,<\/span> <span class=\"ss\">unique: <\/span><span class=\"kp\">true<\/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\">CreateEventMembers<\/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\">7.0<\/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\">:event_members<\/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\">:member<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/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\">boolean<\/span> <span class=\"ss\">:presented<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span> <span class=\"ss\">default: <\/span><span class=\"kp\">false<\/span>\r\n\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=\"n\">add_index<\/span> <span class=\"ss\">:event_members<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:presented<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>\u6211\u5011\u57f7\u884c\u9077\u79fb\u3002<\/h2>\n<pre class=\"post-pre\"><code>rails db:migrate\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>== 20220213115441 CreateEvents: migrating =====================================\r\n-- create_table(:events)\r\n   -&gt; 0.0098s\r\n-- add_index(:events, :title)\r\n   -&gt; 0.0016s\r\n-- add_index(:events, :start_at)\r\n   -&gt; 0.0016s\r\n-- add_index(:events, :place)\r\n   -&gt; 0.0015s\r\n-- add_index(:events, :canceled)\r\n   -&gt; 0.0015s\r\n== 20220213115441 CreateEvents: migrated (0.0166s) ============================\r\n\r\n== 20220213115747 CreateMembers: migrating ====================================\r\n-- create_table(:members)\r\n   -&gt; 0.0125s\r\n-- add_index(:members, :name)\r\n   -&gt; 0.0014s\r\n-- add_index(:members, :email, {:unique=&gt;true})\r\n   -&gt; 0.0015s\r\n== 20220213115747 CreateMembers: migrated (0.0157s) ===========================\r\n\r\n== 20220213115822 CreateEventMembers: migrating ===============================\r\n-- create_table(:event_members)\r\n   -&gt; 0.0138s\r\n-- add_index(:event_members, :presented)\r\n   -&gt; 0.0013s\r\n== 20220213115822 CreateEventMembers: migrated (0.0154s) ======================\r\n<\/code><\/pre>\n<h2>\u751f\u6210GraphQL\u7c7b\u578b<\/h2>\n<pre class=\"post-pre\"><code>rails g graphql:object Event\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      create  app\/graphql\/types\/event_type.rb\r\n<\/code><\/pre>\n<p>\u4ece events \u8868\u4e2d\u83b7\u53d6\u4fe1\u606f\u5e76\u81ea\u52a8\u751f\u6210\uff0c\u4f60\u53ef\u4ee5\u8fd9\u6837\u7406\u89e3\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\"># frozen_string_literal: true<\/span>\r\n\r\n<span class=\"k\">module<\/span> <span class=\"nn\">Types<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">EventType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">BaseObject<\/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\">:title<\/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\">:start_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:end_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:place<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:tags<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:memo<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:canceled<\/span><span class=\"p\">,<\/span> <span class=\"no\">Boolean<\/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\">:created_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:updated_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u5011\u4e5f\u6703\u751f\u6210 member \u548c event_member \u7684\u90e8\u5206\u3002<\/p>\n<pre class=\"post-pre\"><code>rails g graphql:object Member\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      create  app\/graphql\/types\/member_type.rb\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>rails g graphql:object EventMember\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      create  app\/graphql\/types\/event_member_type.rb\r\n<\/code><\/pre>\n<h2>\u6dfb\u52a0\u4e00\u4e2a\u53ef\u4ee5\u83b7\u53d6\u6240\u6709\u4e8b\u4ef6\u7684GraphQL\u67e5\u8be2\u3002<\/h2>\n<pre class=\"post-pre\"><code>    <span class=\"n\">field<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/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=\"k\">def<\/span> <span class=\"nf\">events<\/span>\r\n      <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/span>\r\n    <span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>\u5728GraphiQL\u4e2d\u8fdb\u884c\u64cd\u4f5c\u9a8c\u8bc1<\/h2>\n<p>\u8fd0\u884crails s\u547d\u4ee4\u542f\u52a8\u670d\u52a1\u5668\uff0c\u7136\u540e\u8bbf\u95eehttp:\/\/localhost:3000\/graphiql\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/74-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u6267\u884c\u67e5\u8be2\u4ee5\u83b7\u53d6\u4e8b\u4ef6\u7684id\uff0c\u6807\u9898\u548c\u5f00\u59cb\u65f6\u95f4<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"n\">events<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">id<\/span>\r\n    <span class=\"n\">title<\/span>\r\n    <span class=\"n\">startAt<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/77-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u7531\u4e8e\u8fd8\u6ca1\u6709\u4efb\u4f55\u6570\u636e\uff0c\u6240\u4ee5\u5b83\u662f\u4e00\u4e2a\u7a7a\u6570\u7ec4\u3002<\/p>\n<h2>\u5728Rails c\u4e2d\u8f93\u5165\u6d4b\u8bd5\u6570\u636e<\/h2>\n<pre class=\"post-pre\"><code>rails c\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span> <span class=\"ss\">title: <\/span><span class=\"s1\">'\u52c9\u5f37\u4f1a'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">start_at: <\/span><span class=\"s1\">'2022\/02\/18 19:00'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">end_at: <\/span><span class=\"s1\">'2022\/02\/18 21:00'<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>  (13.6ms)  SELECT sqlite_version(*)\r\n  TRANSACTION (0.1ms)  begin transaction\r\n  Event Create (19.8ms)  INSERT INTO \"events\" (\"title\", \"start_at\", \"end_at\", \"place\", \"tags\", \"memo\", \"canceled\", \"created_at\", \"updated_at\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)  [[\"title\", \"\u52c9\u5f37\u4f1a\"], [\"start_at\", \"2022-02-18 19:00:00\"], [\"end_at\", \"2022-02-18 21:00:00\"], [\"place\", nil], [\"tags\", nil], [\"memo\", nil], [\"canceled\", 0], [\"created_at\", \"2022-02-13 13:05:15.499816\"], [\"updated_at\", \"2022-02-13 13:05:15.499816\"]]\r\n  TRANSACTION (45.7ms)  commit transaction\r\n=&gt; \r\n#&lt;Event:0x00007f680970b048\r\n id: 1,\r\n title: \"\u52c9\u5f37\u4f1a\",\r\n start_at: Fri, 18 Feb 2022 19:00:00.000000000 UTC +00:00,\r\n end_at: Fri, 18 Feb 2022 21:00:00.000000000 UTC +00:00,\r\n place: nil,\r\n tags: nil,\r\n memo: nil,\r\n canceled: false,\r\n created_at: Sun, 13 Feb 2022 13:05:15.499816000 UTC +00:00,\r\n updated_at: Sun, 13 Feb 2022 13:05:15.499816000 UTC +00:00&gt;\r\n<\/code><\/pre>\n<h2>\u518d\u6b21\u6267\u884c GraphQL \u67e5\u8be2\u3002<\/h2>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/84-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u4f60\u6295\u5165\u7684\u6570\u636e\u4f1a\u8fd4\u56de\u6765\u7684\u3002<\/p>\n<h1>\u6211\u8981\u521b\u5efa\u4e00\u4e2a\u7528\u4e8e\u6ce8\u518c\u7684\u7a81\u53d8\u3002<\/h1>\n<h2>\u751f\u6210Mutation\u7528\u7684\u6587\u4ef6\u3002<\/h2>\n<pre class=\"post-pre\"><code>rails g graphql:mutation CreateEvent\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      create  app\/graphql\/mutations\/create_event.rb\r\n<\/code><\/pre>\n<p>\u5df2\u751f\u6210\u4ee5\u4e0b\u6587\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">module<\/span> <span class=\"nn\">Mutations<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">CreateEvent<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">BaseMutation<\/span>\r\n    <span class=\"c1\"># TODO: define return fields<\/span>\r\n    <span class=\"c1\"># field :post, Types::PostType, null: false<\/span>\r\n\r\n    <span class=\"c1\"># TODO: define arguments<\/span>\r\n    <span class=\"c1\"># argument :name, String, required: true<\/span>\r\n\r\n    <span class=\"c1\"># TODO: define resolve method<\/span>\r\n    <span class=\"c1\"># def resolve(name:)<\/span>\r\n    <span class=\"c1\">#   { post: ... }<\/span>\r\n    <span class=\"c1\"># end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u5c06\u5bf9\u6b64\u8fdb\u884c\u4fee\u6b63\u3002(W\u01d2 du\u00ec c\u01d0 .)<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">module<\/span> <span class=\"nn\">Mutations<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">CreateEvent<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">BaseMutation<\/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\r\n    <span class=\"n\">argument<\/span> <span class=\"ss\">:title<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/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\">:start_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:end_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:place<\/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\">:tags<\/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\">:memo<\/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=\"k\">def<\/span> <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"o\">**<\/span><span class=\"n\">args<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"p\">{<\/span> <span class=\"ss\">event: <\/span><span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span><span class=\"p\">(<\/span><span class=\"o\">**<\/span><span class=\"n\">args<\/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<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>\u5bf9Mutation\u8fdb\u884c\u64cd\u4f5c\u786e\u8ba4<\/h2>\n<p>\u5728\u6d4f\u89c8\u5668\u4e2d\u6267\u884c\u7a81\u53d8\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">mutation<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">createEvent<\/span><span class=\"p\">(<\/span>\r\n    <span class=\"n\">input<\/span><span class=\"p\">:{<\/span>\r\n      <span class=\"n\">title<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\u5408\u5bbf\"<\/span>\r\n      <span class=\"n\">startAt<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"2022-02-26T09:00:00Z\"<\/span>\r\n      <span class=\"n\">endAt<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"2022-02-27T18:00:00Z\"<\/span>\r\n      <span class=\"n\">place<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\u6709\u99ac\u6e29\u6cc9\"<\/span>\r\n      <span class=\"n\">tags<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Ruby \u5408\u5bbf \u6e29\u6cc9\"<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <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\">title<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/97-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u6211\u8bd5\u7740\u67e5\u8be2\u4e00\u4e0b\u6ce8\u518c\u5185\u5bb9\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"n\">events<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">id<\/span>\r\n    <span class=\"n\">title<\/span>\r\n    <span class=\"n\">startAt<\/span>\r\n    <span class=\"n\">endAt<\/span>\r\n    <span class=\"n\">place<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/100-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u4f60\u5df2\u7ecf\u6210\u529f\u6ce8\u518c\u4e86\u5462\u3002<\/p>\n<h2>\u6dfb\u52a0\u9002\u7528\u4e8e\u4f1a\u5458\u7684\u67e5\u8be2\u548c\u53d8\u66f4\u64cd\u4f5c<\/h2>\n<p>\u6211\u5c06\u6dfb\u52a0\u4ee5\u4e0b\u67e5\u8be2<\/p>\n<pre class=\"post-pre\"><code>    <span class=\"n\">field<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MemberType<\/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\">members<\/span>\r\n      <span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/span>\r\n    <span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u4f1a\u5728\u6d4f\u89c8\u5668\u4e2d\u786e\u8ba4\u67e5\u8be2\u5185\u5bb9\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n    <span class=\"n\">members<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">id<\/span>\r\n        <span class=\"n\">name<\/span>\r\n        <span class=\"n\">email<\/span>\r\n    <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/107-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u6211\u5011\u5c07\u6dfb\u52a0\u7a81\u8b8a\u3002<\/p>\n<pre class=\"post-pre\"><code>rails g graphql:mutation CreateMember\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>      create  app\/graphql\/mutations\/create_member.rb\r\n<\/code><\/pre>\n<p>\u4fee\u6b63 Mutation \u6587\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">module<\/span> <span class=\"nn\">Mutations<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">CreateMember<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">BaseMutation<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:member<\/span><span class=\"p\">,<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MemberType<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n\r\n    <span class=\"n\">argument<\/span> <span class=\"ss\">:name<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/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\">:email<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">true<\/span>\r\n\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"o\">**<\/span><span class=\"n\">args<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"p\">{<\/span> <span class=\"ss\">member: <\/span><span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span><span class=\"p\">(<\/span><span class=\"o\">**<\/span><span class=\"n\">args<\/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<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u5728\u6d4f\u89c8\u5668\u4e2d\u68c0\u67e5\u7a81\u53d8\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">mutation<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">createMember<\/span><span class=\"p\">(<\/span>\r\n    <span class=\"n\">input<\/span><span class=\"p\">:{<\/span>\r\n      <span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\u5c71\u7530\u3000\u592a\u90ce\"<\/span>\r\n      <span class=\"n\">email<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"yamada.taro@example.com\"<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">){<\/span>\r\n    <span class=\"n\">member<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"n\">id<\/span>\r\n      <span class=\"n\">name<\/span>\r\n      <span class=\"n\">email<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/115-0.png\" alt=\"image.png\" \/><\/div>\n<h2>\u521b\u5efa\u53c2\u4e0e\u6d3b\u52a8\u7684\u67e5\u8be2\u548c\u53d8\u66f4\u3002<\/h2>\n<p>\u521b\u9020\u6d3b\u52a8\u53c2\u4e0e\u8005\u7684\u67e5\u8be2\u548c\u53d8\u66f4\u3002<\/p>\n<p>\u7531\u4e8e\u4e8b\u4ef6\uff08Event\uff09\u548c\u6210\u5458\uff08Member\uff09\u4e4b\u95f4\u5b58\u5728\u591a\u5bf9\u591a\u7684\u5173\u7cfb\uff0c\u56e0\u6b64\u9700\u8981\u5148\u5728\u6a21\u578b\u7c7b\uff08Model\uff09\u4e2d\u8bbe\u7f6e\u5173\u8054\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Event<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ApplicationRecord<\/span>\r\n  <span class=\"n\">has_many<\/span> <span class=\"ss\">:event_members<\/span>\r\n  <span class=\"n\">has_many<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"ss\">through: :event_members<\/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\">Member<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ApplicationRecord<\/span>\r\n  <span class=\"n\">has_many<\/span> <span class=\"ss\">:event_members<\/span>\r\n  <span class=\"n\">has_many<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/span> <span class=\"ss\">through: :event_members<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<p>\u5728\u5c06\u6570\u636e\u63d2\u5165event_members\u4e4b\u524d\uff0c\u8bf7\u5148\u51c6\u5907\u597d\u6570\u636e\u3002<\/p>\n<pre class=\"post-pre\"><code>rails c\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span> <span class=\"ss\">name: <\/span><span class=\"s1\">'\u9234\u6728 \u82b1\u5b50'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">email: <\/span><span class=\"s1\">'suzuki.hanako@example.com'<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">first<\/span><span class=\"p\">.<\/span><span class=\"nf\">then<\/span><span class=\"p\">{<\/span><span class=\"o\">|<\/span><span class=\"n\">event<\/span><span class=\"o\">|<\/span> <span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/span><span class=\"p\">.<\/span><span class=\"nf\">each<\/span> <span class=\"p\">{<\/span><span class=\"o\">|<\/span><span class=\"n\">member<\/span><span class=\"o\">|<\/span> <span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">event_members<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span> <span class=\"ss\">member: <\/span><span class=\"p\">}}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>  Event Load (2.0ms)  SELECT \"events\".* FROM \"events\" ORDER BY \"events\".\"id\" ASC LIMIT ?  [[\"LIMIT\", 1]]\r\n  Member Load (2.0ms)  SELECT \"members\".* FROM \"members\"                                                                   \r\n  TRANSACTION (0.1ms)  begin transaction                                                                                   \r\n  EventMember Create (21.4ms)  INSERT INTO \"event_members\" (\"event_id\", \"member_id\", \"presented\", \"created_at\", \"updated_at\") VALUES (?, ?, ?, ?, ?)  [[\"event_id\", 1], [\"member_id\", 1], [\"presented\", nil], [\"created_at\", \"2022-02-13 13:57:02.526484\"], [\"updated_at\", \"2022-02-13 13:57:02.526484\"]]                              \r\n  TRANSACTION (8.1ms)  commit transaction                                                                                  \r\n  TRANSACTION (0.1ms)  begin transaction                                                                                   \r\n  EventMember Create (27.6ms)  INSERT INTO \"event_members\" (\"event_id\", \"member_id\", \"presented\", \"created_at\", \"updated_at\") VALUES (?, ?, ?, ?, ?)  [[\"event_id\", 1], [\"member_id\", 2], [\"presented\", nil], [\"created_at\", \"2022-02-13 13:57:02.561104\"], [\"updated_at\", \"2022-02-13 13:57:02.561104\"]]                              \r\n  TRANSACTION (8.0ms)  commit transaction                                                                                  \r\n=&gt;                                                                                                                         \r\n[#&lt;Member:0x00007efedf8ebfb8                                                                                               \r\n  id: 1,                                                                                                                   \r\n  name: \"\u5c71\u7530\u3000\u592a\u90ce\",                                                                                                      \r\n  email: \"yamada.taro@example.com\",                                                                                        \r\n  created_at: Sun, 13 Feb 2022 13:36:46.345436000 UTC +00:00,\r\n  updated_at: Sun, 13 Feb 2022 13:36:46.345436000 UTC +00:00&gt;,\r\n #&lt;Member:0x00007efedf8ebec8\r\n  id: 2,\r\n  name: \"\u9234\u6728 \u82b1\u5b50\",\r\n  email: \"suzuki.hanako@example.com\",\r\n  created_at: Sun, 13 Feb 2022 13:55:30.446672000 UTC +00:00,\r\n  updated_at: Sun, 13 Feb 2022 13:55:30.446672000 UTC +00:00&gt;]\r\n<\/code><\/pre>\n<p>\u6dfb\u52a0GraphQL\u67e5\u8be2<\/p>\n<pre class=\"post-pre\"><code>    <span class=\"n\">field<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MemberType<\/span><span class=\"p\">],<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>    <span class=\"n\">field<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/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<\/code><\/pre>\n<p>\u6211\u4f1a\u5728\u6d4f\u89c8\u5668\u4e2d\u8fdb\u884c\u64cd\u4f5c\u786e\u8ba4\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"n\">members<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">id<\/span>\r\n    <span class=\"n\">name<\/span>\r\n    <span class=\"n\">email<\/span>\r\n    <span class=\"n\">events<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"n\">id<\/span>\r\n      <span class=\"n\">title<\/span>\r\n      <span class=\"n\">startAt<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/130-0.png\" alt=\"image.png\" \/><\/div>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"n\">events<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">id<\/span>\r\n    <span class=\"n\">title<\/span>\r\n    <span class=\"n\">startAt<\/span>\r\n    <span class=\"n\">members<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"n\">id<\/span>\r\n      <span class=\"n\">name<\/span>\r\n      <span class=\"n\">email<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<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\/657d80b6913a08637a6aaf62\/132-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u53ef\u4ee5\u83b7\u53d6\u5230\u6309\u7167\u6210\u5458\u8fdb\u884c\u5206\u7c7b\u7684\u6d3b\u52a8\uff0c\u4ee5\u53ca\u6309\u7167\u6d3b\u52a8\u8fdb\u884c\u5206\u7c7b\u7684\u6210\u5458\u3002<\/p>\n<p>\u7a81\u53d8\u7684\u4fee\u6b63<\/p>\n<p>\u6211\u4f1a\u4fee\u6539Mutation\uff0c\u4ee5\u4fbf\u5728\u4e8b\u4ef6\u6ce8\u518c\u65f6\u6307\u5b9a\u53c2\u4e0e\u8005\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">module<\/span> <span class=\"nn\">Mutations<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">CreateEvent<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">BaseMutation<\/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\r\n    <span class=\"n\">argument<\/span> <span class=\"ss\">:title<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/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\">:start_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:end_at<\/span><span class=\"p\">,<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">ISO8601DateTime<\/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\">:place<\/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\">:tags<\/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\">:memo<\/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\">:member_ids<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Integer<\/span><span class=\"p\">],<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span>\r\n\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"n\">member_ids<\/span><span class=\"p\">:,<\/span> <span class=\"o\">**<\/span><span class=\"n\">args<\/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\">create!<\/span><span class=\"p\">(<\/span><span class=\"o\">**<\/span><span class=\"n\">args<\/span><span class=\"p\">).<\/span><span class=\"nf\">tap<\/span> <span class=\"k\">do<\/span><span class=\"o\">|<\/span><span class=\"n\">event<\/span><span class=\"o\">|<\/span>\r\n        <span class=\"n\">member_ids<\/span><span class=\"p\">.<\/span><span class=\"nf\">each<\/span><span class=\"p\">{<\/span><span class=\"o\">|<\/span><span class=\"n\">member_id<\/span><span class=\"o\">|<\/span> <span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"nf\">event_members<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span> <span class=\"ss\">member_id: <\/span><span class=\"p\">}<\/span>\r\n      <span class=\"k\">end<\/span>\r\n      <span class=\"p\">{<\/span> <span class=\"ss\">event: <\/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<\/code><\/pre>\n<p>\u203b \u53c2\u6570\uff1amember_ids&#8230;\u7684\u884c\u6dfb\u52a0\u4ee5\u53ca\u4fee\u6b63 def resolve\u3002<\/p>\n<p>\u203b \u53c2\u6570\uff1a\u6b63\u5728\u8fdb\u884c member_ids&#8230; \u884c\u7684\u65b0\u589e\u4ee5\u53ca\u5bf9 def resolve \u7684\u4fee\u6b63\u3002<\/p>\n<p>\u203b \u53c2\u6570\uff1a\u6b63\u5728\u5bf9 member_ids&#8230; \u884c\u8fdb\u884c\u6dfb\u52a0\u5e76\u4fee\u6b63 def resolve\u3002<\/p>\n<p>\u786e\u8ba4\u64cd\u4f5c<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">mutation<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">createEvent<\/span><span class=\"p\">(<\/span>\r\n    <span class=\"n\">input<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span><span class=\"n\">title<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\u61c7\u89aa\u4f1a\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">startAt<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"2022-02-23T19:00:00Z\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">memberIds<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">]}<\/span>\r\n  <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\">title<\/span>\r\n      <span class=\"n\">members<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">id<\/span>\r\n        <span class=\"n\">name<\/span>\r\n        <span class=\"n\">email<\/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<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/140-0.png\" alt=\"image.png\" \/><\/div>\n<p>\u505a\u5f97\u5f88\u68d2<\/p>\n<h1>\u5728Query\u4e2d\u6dfb\u52a0\u7b5b\u9009\u6761\u4ef6<\/h1>\n<p>\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff0c\u8bf7\u5c06\u4ee5\u4e0b\u5185\u5bb9\u4ee5\u4e2d\u6587\u6bcd\u8bed\u8fdb\u884c\u6539\u5199\uff1a\u4fee\u590dquery_type.rb\u4ee5\u4fbf\u5728\u4e8b\u4ef6\u548c\u6210\u5458\u7684\u67e5\u8be2\u4e2d\u53ef\u4ee5\u6307\u5b9aid\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">module<\/span> <span class=\"nn\">Types<\/span>\r\n  <span class=\"k\">class<\/span> <span class=\"nc\">QueryType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">BaseObject<\/span>\r\n    <span class=\"c1\"># Add `node(id: ID!) and `nodes(ids: [ID!]!)`<\/span>\r\n    <span class=\"kp\">include<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">Relay<\/span><span class=\"o\">::<\/span><span class=\"no\">HasNodeField<\/span>\r\n    <span class=\"kp\">include<\/span> <span class=\"no\">GraphQL<\/span><span class=\"o\">::<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">Relay<\/span><span class=\"o\">::<\/span><span class=\"no\">HasNodesField<\/span>\r\n\r\n    <span class=\"c1\"># Add root-level fields here.<\/span>\r\n    <span class=\"c1\"># They will be entry points for queries on your schema.<\/span>\r\n\r\n    <span class=\"c1\"># TODO: remove me<\/span>\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:test_field<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">description: <\/span><span class=\"s2\">\"An example field added by the generator\"<\/span>\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">test_field<\/span>\r\n      <span class=\"s2\">\"Hello World!\"<\/span>\r\n    <span class=\"k\">end<\/span>\r\n\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:events<\/span><span class=\"p\">,<\/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> <span class=\"k\">do<\/span>\r\n      <span class=\"n\">argument<\/span> <span class=\"ss\">:ids<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Integer<\/span><span class=\"p\">],<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">events<\/span><span class=\"p\">(<\/span><span class=\"ss\">ids: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">if<\/span> <span class=\"n\">ids<\/span>\r\n        <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">where<\/span><span class=\"p\">(<\/span><span class=\"ss\">id: <\/span><span class=\"n\">ids<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">else<\/span>\r\n        <span class=\"no\">Event<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n\r\n    <span class=\"n\">field<\/span> <span class=\"ss\">:members<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">MemberType<\/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\">argument<\/span> <span class=\"ss\">:ids<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"no\">Integer<\/span><span class=\"p\">],<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">false<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">members<\/span><span class=\"p\">(<\/span><span class=\"ss\">ids: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">if<\/span> <span class=\"n\">ids<\/span>\r\n        <span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">where<\/span><span class=\"p\">(<\/span><span class=\"ss\">id: <\/span><span class=\"n\">ids<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">else<\/span>\r\n        <span class=\"no\">Member<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/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>\u5728&#8221;field: events&#8221;\u548c&#8221;field: members&#8221;\u4e0a\u6dfb\u52a0\u4e00\u4e2a\u5e26\u6709\u5757\u7684\u53c2\u6570\uff0c\u5982\u679c\u5728\u65b9\u6cd5\u5185\u6307\u5b9a\u4e86\u53c2\u6570\uff0c\u5219\u6307\u5b9a\u63d0\u53d6\u6761\u4ef6\u3002<br \/>\n\u53c2\u6570\u53ef\u4ee5\u7701\u7565\uff0c\u8bbe\u7f6e\u4e3a&#8221;ids: nil&#8221;\u3002<\/p>\n<h1>\u6700\u540e<\/h1>\n<p>\u5bf9\u4e8e\u6211\u7684\u4f7f\u7528\u611f\u53d7\u6765\u8bf4\uff0c\u4e0e\u521b\u5efa REST API \u76f8\u6bd4\uff0c\u8fd9\u79cd\u65b9\u6cd5\u7684\u4ee3\u7801\u91cf\u8f83\u5c11\uff0c\u800c\u4e14\u53ea\u6709\u4e00\u4e2a\u7aef\u70b9\uff0c\u4e0d\u4f1a\u5206\u6563\u3002\u6211\u89c9\u5f97\u8fd9\u662f\u4e00\u4e2a\u5f88\u597d\u7684\u5730\u65b9\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u76ee\u6807 \u786e\u8ba4\u5728\u4f7f\u7528 Rails \u548c GraphQL \u7684\u65f6\u5019\uff0c\u5199\u4f5c\u4f1a\u662f\u4ec0\u4e48\u6837\u5b50\u7684\u3002 \u5fc5\u9700\u54c1 (b\u00ec x\u016b Dock [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-47723","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>\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL - 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\/\u6211\u5c1d\u8bd5\u5728rails-7\u7684api\u6a21\u5f0f\u4e0b\u4f7f\u7528graphql\u3002\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL\" \/>\n<meta property=\"og:description\" content=\"\u76ee\u6807 \u786e\u8ba4\u5728\u4f7f\u7528 Rails \u548c GraphQL \u7684\u65f6\u5019\uff0c\u5199\u4f5c\u4f1a\u662f\u4ec0\u4e48\u6837\u5b50\u7684\u3002 \u5fc5\u9700\u54c1 (b\u00ec x\u016b Dock [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u6211\u5c1d\u8bd5\u5728rails-7\u7684api\u6a21\u5f0f\u4e0b\u4f7f\u7528graphql\u3002\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-08-31T11:19:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-05-03T20:04:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/25-0.png\" \/>\n<meta name=\"author\" content=\"\u79d1, \u96c5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u79d1, \u96c5\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 \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\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/\",\"name\":\"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-08-31T11:19:41+00:00\",\"dateModified\":\"2024-05-03T20:04:44+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL\"}]},{\"@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\/41e222757cdd2a3365361328bd79970a\",\"name\":\"\u79d1, \u96c5\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g\",\"caption\":\"\u79d1, \u96c5\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/keya\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL - 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\/\u6211\u5c1d\u8bd5\u5728rails-7\u7684api\u6a21\u5f0f\u4e0b\u4f7f\u7528graphql\u3002\/","og_locale":"zh_CN","og_type":"article","og_title":"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL","og_description":"\u76ee\u6807 \u786e\u8ba4\u5728\u4f7f\u7528 Rails \u548c GraphQL \u7684\u65f6\u5019\uff0c\u5199\u4f5c\u4f1a\u662f\u4ec0\u4e48\u6837\u5b50\u7684\u3002 \u5fc5\u9700\u54c1 (b\u00ec x\u016b Dock [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u6211\u5c1d\u8bd5\u5728rails-7\u7684api\u6a21\u5f0f\u4e0b\u4f7f\u7528graphql\u3002\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-08-31T11:19:41+00:00","article_modified_time":"2024-05-03T20:04:44+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d80b6913a08637a6aaf62\/25-0.png"}],"author":"\u79d1, \u96c5","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u79d1, \u96c5","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"8 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/","name":"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-08-31T11:19:41+00:00","dateModified":"2024-05-03T20:04:44+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u6211\u5c1d\u8bd5\u5728Rails 7\u7684API\u6a21\u5f0f\u4e0b\u4f7f\u7528GraphQL"}]},{"@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\/41e222757cdd2a3365361328bd79970a","name":"\u79d1, \u96c5","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g","caption":"\u79d1, \u96c5"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/keya\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e6%88%91%e5%b0%9d%e8%af%95%e5%9c%a8rails-7%e7%9a%84api%e6%a8%a1%e5%bc%8f%e4%b8%8b%e4%bd%bf%e7%94%a8graphql%e3%80%82\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47723","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\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=47723"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47723\/revisions"}],"predecessor-version":[{"id":96007,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47723\/revisions\/96007"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=47723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=47723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=47723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}