GraphQL on Rails(三) 結(jié)合Rails的修改API

GraphQL on Rails(一) GraphQL介紹
GraphQL on Rails(二) 結(jié)合Rails的查詢API

接著上一個寫到的GraphQL在RailsAPI應(yīng)用中的查詢功能,這次我們來實現(xiàn)修改數(shù)據(jù)的功能,修改數(shù)據(jù)的操作在GraphQL中被稱為 突變(mutation即修改數(shù)據(jù)),它在GraphQL schema中的定義是這樣的。

QuerySchema =  GraphQL::Schema.new(mutation: TODO)

我們還是延續(xù)上一篇的例子,一個博客系統(tǒng),其中包含三個模型:ArticleUserComment

突變

mutation在GraphQL中與其他元素一樣也是一個類型的定義,那么既然是類型的定義,我們就可以將它存放在 types目錄下面,:

MutationType = GraphQL::ObjectType.define do
  # TODO
end

然后就像上面提到的那樣,我們需要在schema定義中指定需要加載的mutation

QuerySchema =  GraphQL::Schema.new(query: QueryType, mutation: MutationType)

接下來我們就編寫 MutationType中的內(nèi)容,定義一下具體可以操作的數(shù)據(jù)類型。既然構(gòu)建的是博客系統(tǒng)那么系統(tǒng)是要提供,對文章的發(fā)布和修改,以及對文章記性評論,和違禁評論的刪除功能。

MutationType = GraphQL::ObjectType.define do

  field :CreateArticle, field: ArticleMutations::Create
  
  field :UpdateArticle, field: ArticleMutations::Update 
  
  field :CreateComment, field: CommentMutations::Create

  field :DestroyComment, field: CommentMutations::Destroy

end

現(xiàn)在MutationType中就已經(jīng)有了這四種操作的類型,可以看到上面的每一行定義中存在兩個field關(guān)鍵字,這其中第一個field是我們定義的MutationType的字段名,后面的Symbol field才是正在的類型定義存在的地方,當然如果你愿意的話其實可以將它們直接寫在 MutationType的定義當中的,但是因為程序復(fù)雜起來后,像上面的這種寫法更容易模塊化,所以使用這種寫法。
我們將上面提到的四個mutations的文件存放在對應(yīng)的./app/graph/mutations 中

├── app
│   ├── graph
│   │   ├── fields
│   │   ├── schemas
|   |   ├── mutations
│   │   └── types

**app/graph/mutations/article_mutations.rb **

module ArticleMutations

  Create = GraphQL::Field.define do
    type -> { ArticleType }
    description 'create a article'

    argument :title, !types.String

    argument :content, !types.String

    resolve -> (obj, input_fields, ctx)  do
      ctx[:current_user].articles.create(title: input_fields['title'], content: input_fields['content'])
    end

  end

  Update = GraphQL::Field.define do
    type -> { ArticleType }
    description 'update title of article'

    argument :id, types.ID

    argument :title, !types.String

    resolve -> (obj, input_fields, ctx)  do
      article = Article.find_by(id: input_fields['id'])
      article.update(title: input_fields['title'])
      article
    end
  end
end

**app/graph/mutations/comment_mutations.rb **

module CommentMutations
  Create = GraphQL::Field.define do
    type -> { CommentType }
    description 'create a comment of article'

    argument :article_id, types.ID

    argument :content, !types.String

    resolve -> (obj, input_fields, ctx)  do
      article = Article.find_by(id: input_fields['article_id'])
      article.comments.create(content: input_fields['content'], user: ctx[:current_user])
    end

  end

  Destroy = GraphQL::Field.define do
    type -> { types.Boolean }
    description 'delete a comment'

    argument :id, types.ID

    resolve -> (obj, input_fields, ctx)  do
      !!Comment.delete(input_fields['id'])
    end
  end
end

從上面的兩段代碼看到,mutation其實和query是基本一樣的類型定義,首先由type指定修改數(shù)據(jù)后的返回值類型,argument定義可以傳遞的參數(shù),resolve 方法的block參數(shù)是最后具體執(zhí)行操作的代碼。其中還有一個需要注意的就是 resolve 方法中的第三個參數(shù),ctx (context) 它是用于存放controller中傳遞進來的上下文數(shù)據(jù),我們這個博客系統(tǒng)的創(chuàng)建數(shù)據(jù)操作都需要用戶信息所以,需要在controller中把當前用戶傳進來。

class QueriesController < ApplicationController
  def create
    result = ::QuerySchema.execute(params[:query], context: {current_user: current_user})
    render json: result
  end
end  

接下來,讓我們來創(chuàng)建一個文章看看效果:


Paste_Image.png

文章被創(chuàng)建成功,并且返回了作者的ID以及,文章的ID和標題。

總結(jié)

通過上面的實例,我們可以看出GraphQL中不管是查詢還是突變都保持著統(tǒng)一的類型系統(tǒng)的樣子,其中有要注意的幾點是:突變字段中的 resolve方法的返回值的類型要和聲明的類型一致,還有就是多個突變操作在一個查詢中是順序執(zhí)行的。
后面的話這一系列文章會寫到GraphQL的其他高級功能在Rails中的應(yīng)用,以及GraphQL查詢的優(yōu)化方案等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容