Recently, I have implemented API with graphql-ruby. Rails has a handy feature called polymorphic for associating models. I will explain how to express this in graphql using UnionType.
Consider the case where the User and PetShop tables are ownerable and polymorphic in the Dog table. When getting a dog with graphql, make sure that the column of its ownerable (user or pet_shop) is also taken.
First, let's review the case of normal associations (belongs_to, has_many, etc.). Suppose User and Dog are one-to-many as shown below.
user.rb
Class User < ApplicationRecord
has_many: dogs
end
dog.rb
Class Dog < ApplicationRecord
belongs_to: user
end
ObjectType To express the association defined in the model with graphql-ruby, write ObjectType as follows.
user_type.rb
Class UserType < Types::BaseObject
field :id, ID, null: false
end
dog_type.rb
Class DogType < Type::BaseObject
field :name, String, null: false
field :user, ObjectTypes::UserType, null: false #Association with user
end
If you define ObjectType as above, it will also get the associated user object when returning the dog object.
Next, consider the case of polymorphic association. Besides user, petShop also owns dog.
For polymorphic, the Rials model association is as follows:
user.rb
Class User < ApplicationRecord
has_many :dogs, as: :ownerable
end
pet_shop.rb
Class PetShop < ApplicationRecord
has_many :dogs, as: :ownerable
end
dog.rb
Class Dog < ApplicationRecord
belongs_to :ownerable, polymorphic: true
end
ObjectType Next, define the Object type. The petShop object has been added and the dogType field has been changed to ownerable to indicate a polymorphic association instead of user.
user_type.rb
Class UserType < Types::BaseObject
field :id, ID, null: false
end
pet_shop_type.rb
Class PetShopType < Types::BaseObject
field :id, ID, null: false
end
dog_type.rb
Class DogType < Type::BaseObject
field :name, String, null: false
field :ownerable, UnionTypes::OwnerableType, null: false #Association with ownerable
end
Note that the ownerable type is UnioTypes instead of ObjectTypes. UnionType will be defined from now on. UnioneType UnioType is the heart of this article. The ownerable defined in dogType is defined as UnionType, and it distinguishes between userType and petShopType.
ownerable_type.rb
module UnionTypes
class OwnerableType < Types::BaseUnion
# possible_Declare the types that can be associated with types
possible_types ObjectTypes::UserType, ObjectTypes::PetShopType
#Describe branch processing
def self.resolve_type(object, _context)
if object.is_a?(User)
ObjectTypes::PostType
elsif object.is_a?(PetShop)
ObjectTypes::ReplyType
end
end
end
end
By writing as above, it will determine the type to be returned by resolver and select User or PetShop. (It doesn't look like ruby, but ...) Query When using UnionType, query is also written in a slightly special way.
query{
dog(id: [dog_id]){
id
ownerable {
__typename #Specify the type
... on User {
id
}
__typename
... on PetShop {
id
}
}
}
}
You can select the owner you want by specifying the typename as above.
Recommended Posts