graphql-rubyでフィールド名と別名のメソッドを使用したい場合はmethodオプションを使うと便利
はじめに
今回は、graphql-rubyで field
の method
オプションを使って、フィールド名と別名のメソッドを使用する方法について書きたいと思います。
graphql-rubyのfield
まず、graphql-rubyでは、field
というDSLでフィールドを定義すると、渡されたオブジェクトの同名のメソッドを呼び出してフィールドを解決してくれます。(ハッシュの場合はキー名として検索してくれます)
つまり、以下のように field
が定義されていた場合、top_score
フィールドを返す際に、渡されたオブジェクトの top_score
メソッドが呼び出されます。
field :top_score, Integer, null: false
GraphQLのフィールド名とオブジェクトのメソッド名が一致している場合は何も書くことなくフィールドが解決できてとても便利なのですが、Rubyの慣習でメソッド名に ?
を付けている場合や他の使用箇所との兼ね合いからフィールド名とメソッド名を一致させられない場合もあります。
fieldのmethodオプション
そんな時は、field
の method
オプションを使用して別名のメソッドを指定することができます。
以下のように書くと、top_score
のフィールドを解決する際に、渡されたオブジェクトの best_score
メソッドが呼び出されます。
field :top_score, Integer, null: false, method: :best_score
これによって、フィールド名と別名のメソッドであっても呼び出すことができるようになります。
詳細はドキュメントの以下の箇所に書かれています。
実際の使用例
よくあるユースケースを見ていきましょう。
例えば、以下のようなenumで公開ステータスを定義しているPostモデルについて考えます。
class Post < ApplicationRecord
enum :status, { draft: 0, published: 1 }
end
enumによってモデルには published?
メソッドが定義されるので、これを利用してGraphQLで公開されているかどうかのBooleanの値を取得したいとします。
この場合、GraphQLのフィールド名には ?
は使用できないため、 is_published
のようなフィールド名にすることが多いかと思います。
methodオプションを使わない場合
method
オプションを使わなくても、以下のように紐付けを行うメソッドを定義することでやりたいことは実現できます。
module Types
class PostType < Types::BaseObject
field :id, ID, null: false
field :title, String, null: false
field :is_published, Boolean, null: false
def is_published
object.published?
end
end
end
しかし、1つくらいならまだよいですが、これがどんどん増えてくるとクラスの見通しが悪くなっていきます。
methodオプションを使った場合
これを method
オプションを使うことで、以下のように余分なメソッドを定義することなく書くことができます。
module Types
class PostType < Types::BaseObject
field :id, ID, null: false
field :title, String, null: false
field :is_published, Boolean, null: false, method: :published?
end
end
ドキュメントをしっかりと読めば書いてくれてあるのですが、最初このオプションを知らずにObjectTypeのクラスの中に無駄なメソッドをたくさん定義してしまっていました。
method
オプションを使うことでシンプルに書けるようになるので、使える場所では積極的に使っていきたいですね。
まとめ
今回は、graphql-rubyの field
の method
オプションについて紹介しました。
意外とググっても情報が出てこなかったので、同じように困ってる方の参考になれば幸いです。
株式会社マイベストのテックブログです! 採用情報はこちら > notion.so/mybestcom/mybest-information-for-Engineers-8beadd9c91ef4dc2b21171d48a4b0c49
Discussion