Skip to content

Commit 4980d29

Browse files
committed
Add additional mutations and queries option
1 parent 135227c commit 4980d29

6 files changed

Lines changed: 147 additions & 5 deletions

File tree

lib/graphql_devise/rails/routes.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
module ActionDispatch::Routing
22
class Mapper
33
def mount_graphql_devise_for(resource, opts = {})
4-
custom_operations = opts[:operations] || {}
5-
skipped_operations = opts.fetch(:skip, [])
6-
only_operations = opts.fetch(:only, [])
4+
custom_operations = opts.fetch(:operations, {})
5+
skipped_operations = opts.fetch(:skip, [])
6+
only_operations = opts.fetch(:only, [])
7+
additional_mutations = opts.fetch(:additional_mutations, {})
8+
additional_queries = opts.fetch(:additional_queries, {})
79

810
if [skipped_operations, only_operations].all?(&:any?)
911
raise GraphqlDevise::Error, "Can't specify both `skip` and `only` options when mounting the route."
@@ -62,8 +64,11 @@ def mount_graphql_devise_for(resource, opts = {})
6264

6365
GraphqlDevise::Types::MutationType.field("#{mapping_name}_#{action}", mutation: used_mutation)
6466
end
67+
additional_mutations.each do |action, mutation|
68+
GraphqlDevise::Types::MutationType.field(action, mutation: mutation)
69+
end
6570

66-
if used_mutations.present? &&
71+
if (used_mutations.present? || additional_mutations.present?) &&
6772
(Gem::Version.new(GraphQL::VERSION) <= Gem::Version.new('1.10.0') || GraphqlDevise::Schema.mutation.nil?)
6873
GraphqlDevise::Schema.mutation(GraphqlDevise::Types::MutationType)
6974
end
@@ -87,8 +92,11 @@ def mount_graphql_devise_for(resource, opts = {})
8792

8893
GraphqlDevise::Types::QueryType.field("#{mapping_name}_#{action}", resolver: used_query)
8994
end
95+
additional_queries.each do |action, resolver|
96+
GraphqlDevise::Types::QueryType.field(action, resolver: resolver)
97+
end
9098

91-
if used_queries.blank? && GraphqlDevise::Types::QueryType.fields.blank?
99+
if (used_queries.blank? || additional_queries.present?) && GraphqlDevise::Types::QueryType.fields.blank?
92100
GraphqlDevise::Types::QueryType.field(:dummy, resolver: GraphqlDevise::Resolvers::Dummy)
93101
end
94102

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Mutations
2+
class RegisterConfirmedUser < GraphqlDevise::Mutations::Base
3+
argument :email, String, required: true
4+
argument :name, String, required: true
5+
argument :password, String, required: true
6+
argument :password_confirmation, String, required: true
7+
8+
field :user, Types::UserType, null: true
9+
10+
def resolve(**attrs)
11+
user = User.new(attrs.merge(confirmed_at: Time.zone.now))
12+
13+
if user.save
14+
{ user: user }
15+
else
16+
raise_user_error_list(
17+
'Custom registration failed',
18+
errors: user.errors.full_messages
19+
)
20+
end
21+
end
22+
end
23+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Resolvers
2+
class PublicUser < GraphQL::Schema::Resolver
3+
type Types::UserType, null: false
4+
5+
argument :id, Int, required: true
6+
7+
def resolve(id:)
8+
User.find(id)
9+
end
10+
end
11+
end

spec/dummy/config/routes.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
mount_graphql_devise_for 'User', at: '/api/v1/graphql_auth', operations: {
33
login: Mutations::Login,
44
sign_up: Mutations::SignUp
5+
}, additional_mutations: {
6+
register_confirmed_user: Mutations::RegisterConfirmedUser
7+
}, additional_queries: {
8+
public_user: Resolvers::PublicUser
59
}
610

711
mount_graphql_devise_for(
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe 'Additional Mutations' do
4+
include_context 'with graphql query request'
5+
6+
let(:name) { Faker::Name.name }
7+
let(:password) { Faker::Internet.password }
8+
let(:password_confirmation) { password }
9+
let(:email) { Faker::Internet.email }
10+
let(:redirect) { Faker::Internet.url }
11+
12+
context 'when using the user model' do
13+
let(:query) do
14+
<<-GRAPHQL
15+
mutation {
16+
registerConfirmedUser(
17+
email: "#{email}",
18+
name: "#{name}",
19+
password: "#{password}",
20+
passwordConfirmation: "#{password_confirmation}"
21+
) {
22+
user {
23+
email
24+
name
25+
}
26+
}
27+
}
28+
GRAPHQL
29+
end
30+
31+
context 'when params are correct' do
32+
it 'creates a new resource that is already confirmed' do
33+
expect { post_request }.to(
34+
change(User, :count).by(1)
35+
.and(not_change(ActionMailer::Base.deliveries, :count))
36+
)
37+
38+
user = User.last
39+
40+
expect(user).to be_confirmed
41+
expect(json_response[:data][:registerConfirmedUser]).to include(
42+
user: {
43+
email: email,
44+
name: name
45+
}
46+
)
47+
end
48+
end
49+
50+
context 'when params are incorrect' do
51+
let(:password_confirmation) { 'not the same' }
52+
53+
it 'returns descriptive errors' do
54+
expect { post_request }.to not_change(User, :count)
55+
56+
expect(json_response[:errors]).to contain_exactly(
57+
hash_including(
58+
message: 'Custom registration failed',
59+
extensions: { code: 'USER_ERROR', detailed_errors: ["Password confirmation doesn't match Password"] }
60+
)
61+
)
62+
end
63+
end
64+
end
65+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe 'Additional Queries' do
4+
include_context 'with graphql query request'
5+
6+
let(:public_user) { create(:user, :confirmed) }
7+
8+
context 'when using the user model' do
9+
let(:query) do
10+
<<-GRAPHQL
11+
query {
12+
publicUser(
13+
id: #{public_user.id}
14+
) {
15+
email
16+
name
17+
}
18+
}
19+
GRAPHQL
20+
end
21+
22+
before { post_request }
23+
24+
it 'fetches a user by ID' do
25+
expect(json_response[:data][:publicUser]).to include(
26+
email: public_user.email,
27+
name: public_user.name
28+
)
29+
end
30+
end
31+
end

0 commit comments

Comments
 (0)