💬
How to GraphQLを試す(connecting nodes)
前記事
この記事は、以下の続きです。
ノードの接続
リンクへの投票
ユーザがリンクに投票できるようにしていきます。
% bundle exec rails generate model Vote link:references user:references
% bundle exec rails db:migrate
これにより、Voteモデルが作成されます。
app/models/vote.rb
class Vote < ApplicationRecord
belongs_to :link, validate: true
belongs_to :user, validate: true
end
次に、VoteTypeを追加します。
% bundle exec rails generate graphql:object VoteType id:ID! user:UserType! link:LinkType!
CreateVoteリゾルバを定義します。
module Mutations
class CreateVote < BaseMutation
argument :link_id, ID, required: false
type Types::VoteType
def resolve(link_id: nil)
Vote.create!(
link: Link.find(link_id),
user: context[:current_user]
)
end
end
end
最後に、create_voteフィールドをmutation_typeに追加します。
module Types
class MutationType < Types::BaseObject
field :create_link, mutation: Mutations::CreateLink
field :create_user, mutation: Mutations::CreateUser
field :sign_in_user, mutation: Mutations::SignInUser
field :create_vote, mutation: Mutations::CreateVote
end
end
https://zenn.dev/tossy21/articles/d0bb29cb0fcd2b#サインインするmutation と同様に、SignInUser mutationを実行し、サインインしておきます。
その後、createVote mutationを実行してください。
mutation {
createVote(input:{
linkId: "9"
}
){
link {
description
}
user{
name
}
}
}
私の環境だと、context[:current_user]
がうまくいかず、app/graphql/mutations/create_vote.rb
を以下のように変更すると成功しました。
...
def resolve(link_id: nil)
Vote.create!(
link_id: link_id,
user: User.find_by(id: 1)
)
...
成功した際の応答は以下。
{
"data": {
"createVote": {
"link": {
"description": "Your testing playground"
},
"user": {
"name": "Test User"
}
}
}
}
投票とリンクを関連付ける
投票を作成できましたが、現時点では投票を取得する方法がありません。
各リンクの投票を取得できるようにするため、LinkモデルにVotesモデルを関連づけます。
app/models/link.rb
class Link < ApplicationRecord
belongs_to :user, optional: true
has_many :votes
end
次に、LinkTypeにvotesフィールドを追加します。
module Types
class LinkType < Types::BaseObject
field :id, ID, null: false
field :url, String, null: false
field :description, String, null: false
field :posted_by, UserType, null: true, method: :user
field :votes, [Types::VoteType], null: false
end
end
これで、allLinksのQueryを叩くと、すべての投票を確認できます。
query{
allLinks{
votes{
id
}
}
}
応答
{
"data": {
"allLinks": [
{
"votes": []
},
...
{
"votes": []
},
{
"votes": [
{
"id": "1"
},
{
"id": "2"
}
]
}
]
}
}
ユーザと投票を関連付ける
次にユーザが行ったすべての投票を見つけられるようにします。
app/models/user.rb
class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
validates :password, presence: true
has_many :votes
has_many :links
end
次にUserTypeにlinksフィールドを追加します。
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :name, String, null: false
field :email, String, null: false
field :votes, [Types::VoteType], null: false
field :links, [Types::LinkType], null: false
end
end
ユーザの全ての投票を確認します。
query{
allLinks{
id
postedBy{
name
votes{
link{
description
}
}
}
}
}
応答。
ここは、current_userに正しくセッション情報が入っていれば、うまく情報が取得できると思われます。
{
"data": {
"allLinks": [
{
"id": "1",
"postedBy": null
},
...
{
"id": "9",
"postedBy": null
}
]
}
}
Discussion