なかなか情報がなかったので、書いときます。
model名が◯◯Typeで終わることって、ままあるのかなと思います。Company
モデルとCompanyType
モデルのような感じで。これをGraphQLでTypeを定義しようとすると、Types::CompanyType
とTypes::CompanyTypeType
になってしまいます。読みにくすぎる…。
後ろにTypeがつかないといかんのか?っていうところも疑問だったのですが、別にそんなルールもないみたいでした。
GraphQL - Scalars をみていたら、class Types::Url < Types::BaseScalar
とやっていたので。
また、デフォルトのディレクトリ構造のままだとtypesディレクトリに大量のファイルが作られて見辛くなってきたので、ディレクトリを分けました。
ここを参考に、ほぼ同様の構成にしました。
app/graphql/enum_types/ /input_types/ /interface_types/ /mutations/ /object_types/ /scalar_types/ /types/ /union_types/
ディレクトリ名を名前空間として、ファイル名をクラス名にした構成にしないといけないため、ファイルの移動後はリネーム祭りに。
Types::FooType
はObjectTypes::Foo
のように修正です。
これで、Types::CompanyType
がObjectTypes::Company
へ、Types::CompanyTypeType
がObjectTypes::CompanyType
へと分かりやすく変更できてよかった!と思っていたのですが、これだけだと動きません。
query { company(id: 1) { id name companyType { id name } } }
上記のようなクエリを発行しようとすると、エラーで落ちました。
{ "error": { "message": "Duplicate type definition found for name 'Company' at 'Field Company.companyType's return type' (ObjectTypes::Company, ObjectTypes::CompanyType)", "backtrace": [ # 略
Companyで定義されているcompanyTypeに当てはまるTypeが重複してるぞ!って言われてます。
module ObjectTypes class Company < Types::BaseObject field :id, ID, null: false field :name, String, null: false field :company_type, ObjectTypes::CompanyType, null: false # ここ end end
いやいや、ObjectTypes::CompanyType
って指定してるじゃん!って思うんですが、メタプログラミングしてるんでしょう。多分、別名をつけるメソッドとかあるだろう…と思ってググるとDSL形式の頃のgraphql-rubyのコードだったけれど、name = 'CompanyType'
みたいなことをしているページを発見。
Shinosaka.rb #27 (GraphQL) に参加した - @znz blog
CompanyTypeのほうに、雑にname 'CompanyType'
を追加してみます。
module ObjectTypes class CompanyType < Types::BaseObject name 'CompanyType' # 雑に追加 field :id, ID, null: false field :name, String, null: false end end
その後、適当にクエリを投げてみると、エラーメッセージが変わりました。
{ "error": { "message": "The new name override method is `graphql_name`, not `name`. Usage: graphql_name \"CompanyType\"", "backtrace": [ # 略
graphql_nameメソッドで別名を定義しろと。
module ObjectTypes class CompanyType < Types::BaseObject graphql_name 'CompanyType' # 修正 field :id, ID, null: false field :name, String, null: false end end
すると、エラーが消え、ちゃんとcompany(id: 1)に紐づくCompanyTypeの情報が取得できました😀
追記:rails cで検証
検証のために、該当箇所をコメントアウトしてみます。
module ObjectTypes class CompanyType < Types::BaseObject # graphql_name 'CompanyType' # コメントアウト field :id, ID, null: false field :name, String, null: false end end
rails c
して確認します。
$ bin/rails c Loading development environment (Rails 5.2.2.1) Frame number: 0/16 [1] pry(main)> ObjectTypes::CompanyType.graphql_name => "Company" [2] pry(main)> ObjectTypes::Company.graphql_name => "Company"
CompanyTypeのgrqphql_nameはCompanyとなってしまい、重複してますね。その後、コメントアウトを解除して再度rails c
してみます。
$ bin/rails c Loading development environment (Rails 5.2.2.1) Frame number: 0/16 [1] pry(main)> ObjectTypes::CompanyType.graphql_name => "CompanyType" [2] pry(main)> ObjectTypes::Company.graphql_name => "Company"
重複しなくなったのでOK!