Skip to content

Commit 3a12f80

Browse files
committed
Generator can mount operations in main app schema
1 parent 03f2c3c commit 3a12f80

4 files changed

Lines changed: 102 additions & 25 deletions

File tree

README.md

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
1212
* [Table of Contents](#table-of-contents)
1313
* [Introduction](#introduction)
1414
* [Installation](#installation)
15+
* [Running the Generator](#running-the-generator)
16+
* [Mounting the Schema in a Separate Route](#mounting-the-schema-in-a-separate-route)
17+
* [Mounting Operations in Your Own Schema](#mounting-operations-in-your-own-schema)
1518
* [Important](#important)
1619
* [Usage](#usage)
1720
* [Mounting Auth Schema on a Separate Route](#mounting-auth-schema-on-a-separate-route)
@@ -30,12 +33,13 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
3033
* [More Configuration Options](#more-configuration-options)
3134
* [Devise Token Auth Initializer](#devise-token-auth-initializer)
3235
* [Devise Initializer](#devise-initializer)
36+
* [GraphQL Interpreter](#graphql-interpreter)
3337
* [Using Alongside Standard Devise](#using-alongside-standard-devise)
3438
* [Future Work](#future-work)
3539
* [Contributing](#contributing)
3640
* [License](#license)
3741

38-
<!-- Added by: mcelicalderon, at: Wed Jun 10 00:48:00 -05 2020 -->
42+
<!-- Added by: mcelicalderon, at: Wed Jun 10 22:10:26 -05 2020 -->
3943

4044
<!--te-->
4145

@@ -59,20 +63,23 @@ gem 'graphql_devise'
5963
```
6064

6165
And then execute:
66+
```bash
67+
$ bundle
68+
```
6269

63-
$ bundle
64-
65-
Next, you need to run the generator:
66-
67-
$ bundle exec rails generate graphql_devise:install
68-
70+
### Running the Generator
6971
Graphql Devise generator will execute `Devise` and `Devise Token Auth`
7072
generators for you. These will make the required changes for the gems to
7173
work correctly. All configurations for [Devise](https://github.com/plataformatec/devise) and
7274
[Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) are available,
7375
so you can read the docs there to customize your options.
7476
Configurations are done via initializer files as usual, one per gem.
7577

78+
#### Mounting the Schema in a Separate Route
79+
```bash
80+
$ bundle exec rails generate graphql_devise:install
81+
```
82+
7683
The generator accepts 2 params: `user_class` and `mount_path`. The params
7784
will be used to mount the route in `config/routes.rb`. For instance the executing:
7885

@@ -92,16 +99,24 @@ Will do the following:
9299
`Admin` could be any model name you are going to be using for authentication,
93100
and `api/auth` could be any mount path you would like to use for auth.
94101

102+
#### Mounting Operations in Your Own Schema
103+
Now you can provide to the generator an option specifying
104+
the name of your GQL schema. Doing this will skip the insertion of the mount method in the
105+
routes file and will also add our `SchemaPlugin` to the specified schema. `user_class` param is still optional (`Admin`) in the following example.
106+
107+
```bash
108+
$ bundle exec rails g graphql_devise:install Admin --mount MySchema
109+
```
110+
95111
### Important
96-
Remember this gem mounts a completely separate GraphQL schema on a separate controller in the route
97-
provided by the `at` option in the `mount_graphql_devise_for` method in the `config/routes.rb` file by default. If no `at`
112+
Remember that by default this gem mounts a completely separate GraphQL schema on a separate controller in the route
113+
provided by the `at` option in the `mount_graphql_devise_for` method in the `config/routes.rb` file. If no `at`
98114
option is provided, the route will be `/graphql_auth`.
99115

100-
**Starting with `v0.12.0`** you can opt-in to a new behavior where you actually load this gem's
101-
queries and mutations into your own application's schema. If you do this, but also run the
102-
generator, you will have to remove the generated lines from your `config/routes.rb` file.
103-
You can actually mount a resource's auth schema in a separate route and in your app's
104-
schema at the same time, but that's probably not a common scenario. More on this in the next section.
116+
**Starting with `v0.12.0`** you can opt-in to load this gem's queries and mutations into your
117+
own application's schema. You can actually mount a resource's auth schema in a separate route
118+
and in your app's schema at the same time, but that's probably not a common scenario. More on
119+
this in the next section.
105120

106121
## Usage
107122
### Mounting Auth Schema on a Separate Route
@@ -141,9 +156,7 @@ options go [here](#available-mount-options)
141156

142157
### Mounting Operations Into Your Own Schema
143158
Starting with `v0.12.0` you can now mount the GQL operations provided by this gem into your
144-
app's main schema. If you used the generator, remember that the mount method might have
145-
been included in your `config/routes.rb` file and you can remove it if you are using this
146-
mechanism.
159+
app's main schema.
147160

148161
```ruby
149162
# app/graphql/dummy_schema.rb
@@ -183,7 +196,7 @@ options. This should be the same `MutationType` you provide to the `mutation` me
183196
in your schema.
184197
1. `resource_loaders`: This is an optional array of `GraphqlDevise::ResourceLoader` instances.
185198
Here is where you specify the operations that you want to load into your app's schema.
186-
If no loader is provided no operations will be added to your schema, but you will still be
199+
If no loader is provided, no operations will be added to your schema, but you will still be
187200
able to authenticate queries and mutations selectively. More on this in the controller
188201
authentication [section](#authenticating-controller-actions).
189202
1. `authenticate_default`: This is a boolean value which is `true` by default. This value
@@ -193,7 +206,8 @@ every root level field requires authentication unless specified otherwise using
193206
authentication unless specified otherwise using the `authenticate: true` option on the field.
194207
1. `unauthenticated_proc`: This param is optional. Here you can provide a proc that receives
195208
one argument (field name) and is called whenever a field that requires authentication
196-
is called without an authenticated resource.
209+
is called without an authenticated resource. By default a `GraphQL::ExecutionError` will be
210+
raised if authentication fails. This will provide a GQL like error message on the response.
197211

198212
### Available Mount Options
199213
Both the `mount_graphql_devise_for` method and the `GraphqlDevise::ResourceLoader` class
@@ -454,6 +468,25 @@ In this section the most important configurations will be highlighted.
454468

455469
**Note:** Remember this gem adds a layer on top of Devise, so some configurations might not apply.
456470

471+
### GraphQL Interpreter
472+
GraphQL-Ruby `>= 1.9.0` includes a new runtime module which you may use for your schema.
473+
Eventually, it will become the default. You can read more about it
474+
[here](https://graphql-ruby.org/queries/interpreter).
475+
476+
This gem supports schemas using the interpreter and it is recommended as it introduces several
477+
improvements which focus mainly on performance.
478+
479+
Using it is as simple as this, but do read about the implications of doing this in an existing
480+
app:
481+
```ruby
482+
class MySchema < GraphQL::Schema
483+
use GraphQL::Execution::Interpreter
484+
# Also required in GraphQL-Ruby 1.10+:
485+
use GraphQL::Analysis::AST
486+
end
487+
```
488+
489+
457490
### Using Alongside Standard Devise
458491
The DeviseTokenAuth gem allows experimental use of the standard Devise gem to be configured at the same time, for more
459492
information you can check [this answer here](https://github.com/lynndylanhurley/devise_token_auth/blob/2a32f18ccce15638a74e72f6cfde5cf15a808d3f/docs/faq.md#can-i-use-this-gem-alongside-standard-devise).

lib/generators/graphql_devise/install_generator.rb

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ class InstallGenerator < ::Rails::Generators::Base
55
argument :user_class, type: :string, default: 'User'
66
argument :mount_path, type: :string, default: 'auth'
77

8+
class_option :mount, type: :string, default: 'separate_route'
9+
810
def execute_devise_installer
911
generate 'devise:install'
1012
end
@@ -29,15 +31,20 @@ def execute_dta_installer
2931

3032
def mount_resource_route
3133
routes_file = 'config/routes.rb'
32-
gem_route = "mount_graphql_devise_for '#{user_class}', at: '#{mount_path}'"
3334
dta_route = "mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'"
3435

35-
if file_contains_str?(routes_file, gem_route)
36+
if options['mount'] != 'separate_route'
3637
gsub_file(routes_file, /^\s+#{Regexp.escape(dta_route + "\n")}/i, '')
37-
38-
say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
3938
else
40-
gsub_file(routes_file, /#{Regexp.escape(dta_route)}/i, gem_route)
39+
gem_route = "mount_graphql_devise_for '#{user_class}', at: '#{mount_path}'"
40+
41+
if file_contains_str?(routes_file, gem_route)
42+
gsub_file(routes_file, /^\s+#{Regexp.escape(dta_route + "\n")}/i, '')
43+
44+
say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
45+
else
46+
gsub_file(routes_file, /#{Regexp.escape(dta_route)}/i, gem_route)
47+
end
4148
end
4249
end
4350

@@ -65,6 +72,22 @@ def set_change_headers_on_each_request_false
6572
)
6673
end
6774

75+
def mount_in_schema
76+
return if options['mount'] == 'separate_route'
77+
78+
inject_into_file "app/graphql/#{options['mount'].underscore}.rb", after: "< GraphQL::Schema\n" do
79+
<<-RUBY
80+
use GraphqlDevise::SchemaPlugin.new(
81+
query: Types::QueryType,
82+
mutation: Types::MutationType,
83+
resource_loaders: [
84+
GraphqlDevise::ResourceLoader.new('#{user_class}'),
85+
]
86+
)
87+
RUBY
88+
end
89+
end
90+
6891
private
6992

7093
def file_contains_str?(filename, regex_str)

lib/graphql_devise/mutations/sign_up.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def resolve(confirm_success_url: nil, **attrs)
3535

3636
{ authenticatable: resource }
3737
else
38-
resource.clean_up_passwords if resource.respond_to?(:clean_up_passwords)
38+
resource.try(:clean_up_passwords)
3939
raise_user_error_list(
4040
I18n.t('graphql_devise.registration_failed'),
4141
errors: resource.errors.full_messages

spec/generators/graphql_devise/install_generator_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@
1717
run_generator(args)
1818
end
1919

20+
context 'when mount option is schema' do
21+
let(:args) { ['Admin', '--mount', 'GqldDummySchema'] }
22+
23+
it 'mounts the SchemaPlugin' do
24+
assert_file 'config/initializers/devise.rb'
25+
assert_file 'config/initializers/devise_token_auth.rb', /^\s{2}#{Regexp.escape('config.change_headers_on_each_request = false')}/
26+
assert_file 'config/locales/devise.en.yml'
27+
28+
assert_migration 'db/migrate/devise_token_auth_create_admins.rb'
29+
30+
assert_file 'app/models/admin.rb', /^\s{2}devise :.+include GraphqlDevise::Concerns::Model/m
31+
32+
assert_file 'app/controllers/application_controller.rb', /^\s{2}include GraphqlDevise::Concerns::SetUserByToken/
33+
34+
assert_file 'app/graphql/gqld_dummy_schema.rb', /\s+#{Regexp.escape("GraphqlDevise::ResourceLoader.new('Admin')")}/
35+
end
36+
end
37+
2038
context 'when passing no params to the generator' do
2139
let(:args) { [] }
2240

@@ -59,5 +77,8 @@ def create_rails_project
5977
FileUtils.cd(File.join(destination_root, '..')) do
6078
`rails new gqld_dummy -S -C --skip-action-mailbox --skip-action-text -T --skip-spring --skip-bundle --skip-keeps -G --skip-active-storage -J --skip-listen --skip-bootsnap`
6179
end
80+
FileUtils.cd(File.join(destination_root, '../gqld_dummy')) do
81+
`rails generate graphql:install`
82+
end
6283
end
6384
end

0 commit comments

Comments
 (0)