graphql_rails 2.2.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +3 -2
- data/.ruby-version +1 -1
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +17 -17
- data/docs/README.md +23 -45
- data/docs/_sidebar.md +0 -1
- data/docs/components/controller.md +15 -1
- data/docs/components/decorator.md +1 -1
- data/docs/components/model.md +100 -5
- data/docs/components/routes.md +61 -15
- data/graphql_rails.gemspec +1 -1
- data/lib/generators/graphql_rails/templates/graphql_controller.erb +1 -1
- data/lib/graphql_rails/attributes/attribute.rb +16 -14
- data/lib/graphql_rails/attributes/attribute_configurable.rb +24 -0
- data/lib/graphql_rails/attributes/attribute_name_parser.rb +4 -4
- data/lib/graphql_rails/attributes/input_attribute.rb +19 -2
- data/lib/graphql_rails/attributes/type_parseable.rb +4 -5
- data/lib/graphql_rails/controller/action_configuration.rb +1 -1
- data/lib/graphql_rails/controller/build_controller_action_resolver.rb +2 -0
- data/lib/graphql_rails/controller/configuration.rb +1 -1
- data/lib/graphql_rails/controller/request/format_errors.rb +1 -1
- data/lib/graphql_rails/controller/request.rb +3 -2
- data/lib/graphql_rails/controller.rb +1 -1
- data/lib/graphql_rails/decorator/relation_decorator.rb +24 -20
- data/lib/graphql_rails/decorator.rb +12 -4
- data/lib/graphql_rails/errors/custom_execution_error.rb +1 -1
- data/lib/graphql_rails/errors/execution_error.rb +1 -1
- data/lib/graphql_rails/errors/system_error.rb +11 -1
- data/lib/graphql_rails/errors/validation_error.rb +14 -1
- data/lib/graphql_rails/model/find_or_build_graphql_input_type.rb +28 -0
- data/lib/graphql_rails/model/find_or_build_graphql_type.rb +14 -5
- data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +4 -3
- data/lib/graphql_rails/model/input.rb +3 -3
- data/lib/graphql_rails/router/build_schema_action_type.rb +112 -0
- data/lib/graphql_rails/router/event_route.rb +52 -0
- data/lib/graphql_rails/router/mutation_route.rb +1 -1
- data/lib/graphql_rails/router/query_route.rb +1 -1
- data/lib/graphql_rails/router/resource_routes_builder.rb +0 -8
- data/lib/graphql_rails/router/route.rb +4 -3
- data/lib/graphql_rails/router/schema_builder.rb +18 -26
- data/lib/graphql_rails/router.rb +32 -16
- data/lib/graphql_rails/rspec_controller_helpers.rb +3 -1
- data/lib/graphql_rails/types/hidable_by_group.rb +23 -3
- data/lib/graphql_rails/types/input_object_type.rb +16 -0
- data/lib/graphql_rails/version.rb +1 -1
- metadata +11 -16
- data/docs/getting_started/quick_start.md +0 -62
- data/lib/graphql_rails/model/build_graphql_input_type.rb +0 -43
- data/lib/graphql_rails/router/subscription_route.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ef0115ce3d9107ee48ec4e7a725baff242ce81133be4a955d0a81619b106192
|
4
|
+
data.tar.gz: dcb027f23eb5f6cd71b3144e2794822ee899796a5e40f7b240ea3cd59ef586b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8282983f1215feffb37e0541680abd91a44799a95d687cb3adb5cfcb91a1adbf8a07d585fffcd4e477579eebdd9f4a09f0efbc6dfb0b264b0a1a288aa0ac9688
|
7
|
+
data.tar.gz: f7cafd9924e8e26abc9a6e5783938ebedbea7a0dd68fc69a5980186affab6593f8af4a25c8205e20fbfb45534bec96aa4b5b36bc558084994200a73f8eca31d7
|
data/.github/workflows/ruby.yml
CHANGED
@@ -3,14 +3,15 @@ on: [push, pull_request]
|
|
3
3
|
jobs:
|
4
4
|
specs:
|
5
5
|
strategy:
|
6
|
+
fail-fast: false
|
6
7
|
matrix:
|
7
|
-
ruby-version: ['2.
|
8
|
+
ruby-version: ['2.7', '3.0', '3.1', '3.2']
|
8
9
|
|
9
10
|
runs-on: ubuntu-latest
|
10
11
|
env:
|
11
12
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
12
13
|
steps:
|
13
|
-
- uses: actions/checkout@
|
14
|
+
- uses: actions/checkout@v3
|
14
15
|
- uses: ruby/setup-ruby@v1
|
15
16
|
with:
|
16
17
|
ruby-version: ${{ matrix.ruby-version }}
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.1.2
|
data/CHANGELOG.md
CHANGED
@@ -9,6 +9,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
9
9
|
|
10
10
|
* Added/Changed/Deprecated/Removed/Fixed/Security: YOUR CHANGE HERE
|
11
11
|
|
12
|
+
## [2.4.0](2023-27-25)
|
13
|
+
|
14
|
+
* Added: `hidden_in_groups` for attributes to be able to skip attribute from certain groups
|
15
|
+
* Added: `extras` for attributes to be able to include graphql-ruby extensions
|
16
|
+
* Added: `lookahead` as a controller request object field
|
17
|
+
* Changed: `subscription` definition to `event` definition in router configuration page
|
18
|
+
* Fixed: avoid "Found two visible definitions for X" issues for input types
|
19
|
+
|
20
|
+
## [2.3.0](2022-11-25)
|
21
|
+
|
22
|
+
* Added support for Ruby 3.1.2, keyword arguments for decorators support included
|
23
|
+
* Added: error backtrace to SystemError
|
24
|
+
* Fixed: skip "base" field name in validation error messages
|
25
|
+
* Added: router namespaces and named scopes
|
26
|
+
* Added: `deprecate` method/option for attributes and input attributes
|
27
|
+
|
12
28
|
## [2.2.0](2022-01-25)
|
13
29
|
|
14
30
|
* Added: support for subscription type
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
graphql_rails (2.
|
4
|
+
graphql_rails (2.4.0)
|
5
5
|
activesupport (>= 4)
|
6
|
-
graphql (
|
6
|
+
graphql (= 2.0.21)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -74,17 +74,17 @@ GEM
|
|
74
74
|
codecov (0.6.0)
|
75
75
|
simplecov (>= 0.15, < 0.22)
|
76
76
|
coderay (1.1.3)
|
77
|
-
concurrent-ruby (1.1.
|
77
|
+
concurrent-ruby (1.1.10)
|
78
78
|
crass (1.0.6)
|
79
79
|
diff-lcs (1.5.0)
|
80
80
|
docile (1.4.0)
|
81
81
|
erubi (1.10.0)
|
82
|
-
globalid (1.0.
|
82
|
+
globalid (1.0.1)
|
83
83
|
activesupport (>= 5.0)
|
84
|
-
graphql (
|
85
|
-
i18n (1.
|
84
|
+
graphql (2.0.21)
|
85
|
+
i18n (1.12.0)
|
86
86
|
concurrent-ruby (~> 1.0)
|
87
|
-
loofah (2.
|
87
|
+
loofah (2.19.1)
|
88
88
|
crass (~> 1.0.2)
|
89
89
|
nokogiri (>= 1.5.9)
|
90
90
|
mail (2.7.1)
|
@@ -92,8 +92,8 @@ GEM
|
|
92
92
|
marcel (1.0.2)
|
93
93
|
method_source (1.0.0)
|
94
94
|
mini_mime (1.1.2)
|
95
|
-
mini_portile2 (2.
|
96
|
-
minitest (5.
|
95
|
+
mini_portile2 (2.8.1)
|
96
|
+
minitest (5.17.0)
|
97
97
|
mongo (2.17.0)
|
98
98
|
bson (>= 4.8.2, < 5.0.0)
|
99
99
|
mongoid (7.3.3)
|
@@ -101,8 +101,8 @@ GEM
|
|
101
101
|
mongo (>= 2.10.5, < 3.0.0)
|
102
102
|
ruby2_keywords (~> 0.0.5)
|
103
103
|
nio4r (2.5.8)
|
104
|
-
nokogiri (1.
|
105
|
-
mini_portile2 (~> 2.
|
104
|
+
nokogiri (1.14.3)
|
105
|
+
mini_portile2 (~> 2.8.0)
|
106
106
|
racc (~> 1.4)
|
107
107
|
parallel (1.21.0)
|
108
108
|
parser (3.1.0.0)
|
@@ -113,8 +113,8 @@ GEM
|
|
113
113
|
pry-byebug (3.9.0)
|
114
114
|
byebug (~> 11.0)
|
115
115
|
pry (~> 0.13.0)
|
116
|
-
racc (1.6.
|
117
|
-
rack (2.2.
|
116
|
+
racc (1.6.2)
|
117
|
+
rack (2.2.6.4)
|
118
118
|
rack-test (1.1.0)
|
119
119
|
rack (>= 1.0, < 3)
|
120
120
|
rails (6.1.4.4)
|
@@ -135,8 +135,8 @@ GEM
|
|
135
135
|
rails-dom-testing (2.0.3)
|
136
136
|
activesupport (>= 4.2.0)
|
137
137
|
nokogiri (>= 1.6)
|
138
|
-
rails-html-sanitizer (1.4.
|
139
|
-
loofah (~> 2.
|
138
|
+
rails-html-sanitizer (1.4.4)
|
139
|
+
loofah (~> 2.19, >= 2.19.1)
|
140
140
|
railties (6.1.4.4)
|
141
141
|
actionpack (= 6.1.4.4)
|
142
142
|
activesupport (= 6.1.4.4)
|
@@ -193,13 +193,13 @@ GEM
|
|
193
193
|
activesupport (>= 5.2)
|
194
194
|
sprockets (>= 3.0.0)
|
195
195
|
thor (1.2.1)
|
196
|
-
tzinfo (2.0.
|
196
|
+
tzinfo (2.0.5)
|
197
197
|
concurrent-ruby (~> 1.0)
|
198
198
|
unicode-display_width (1.8.0)
|
199
199
|
websocket-driver (0.7.5)
|
200
200
|
websocket-extensions (>= 0.1.0)
|
201
201
|
websocket-extensions (0.1.5)
|
202
|
-
zeitwerk (2.
|
202
|
+
zeitwerk (2.6.6)
|
203
203
|
|
204
204
|
PLATFORMS
|
205
205
|
ruby
|
data/docs/README.md
CHANGED
@@ -42,11 +42,12 @@ GraphqlRails::Router.draw do
|
|
42
42
|
resources :users
|
43
43
|
|
44
44
|
# if you want custom queries or mutation
|
45
|
-
query 'searchLogs', to: 'logs#search' #
|
46
|
-
mutation 'changeUserPassword', to: 'users#change_password'
|
45
|
+
query 'searchLogs', to: 'logs#search' # action is handled by LogsController#search
|
47
46
|
end
|
48
47
|
```
|
49
48
|
|
49
|
+
See [Routes docs](components/routes.md) for more info.
|
50
|
+
|
50
51
|
### Define your Graphql model
|
51
52
|
|
52
53
|
```ruby
|
@@ -56,67 +57,42 @@ class User # works with any class including ActiveRecord
|
|
56
57
|
|
57
58
|
graphql do |c|
|
58
59
|
# most common attributes, like :id, :name, :title has default type, so you don't have to specify it (but you can!)
|
59
|
-
c.attribute
|
60
|
+
c.attribute(:id)
|
60
61
|
|
61
|
-
c.attribute
|
62
|
-
c.attribute
|
62
|
+
c.attribute(:email).type('String')
|
63
|
+
c.attribute(:surname).type('String')
|
63
64
|
end
|
64
65
|
end
|
65
66
|
```
|
66
67
|
|
68
|
+
See [Model docs](components/model.md) for more info.
|
69
|
+
|
67
70
|
### Define controller
|
68
71
|
|
69
72
|
```ruby
|
70
73
|
# app/controllers/graphql/users_controller.rb
|
71
74
|
class Graphql::UsersController < GraphqlApplicationController
|
72
|
-
#
|
73
|
-
action(:change_user_password)
|
74
|
-
.permit(:password!, :id!) # Bang (!) indicates that attribute is required
|
75
|
-
.returns('User!')
|
75
|
+
model('User') # specify that all actions returns User by default
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
# DRUD actions description
|
78
|
+
action(:index).permit(id: 'ID!').returns_many
|
79
|
+
action(:show).permit(id: 'ID!').returns_single
|
80
|
+
action(:create).permit(email: 'String!').returns_single
|
81
|
+
action(:update).permit(id: 'ID!', email: 'String!').returns_single
|
82
|
+
action(:destroy).permit(id: 'ID!').returns_single
|
80
83
|
|
81
|
-
|
82
|
-
|
84
|
+
def index
|
85
|
+
User.all
|
83
86
|
end
|
84
87
|
|
85
|
-
|
86
|
-
.
|
87
|
-
.returns('[User!]!')
|
88
|
-
def search
|
88
|
+
def show
|
89
|
+
User.find(params[:id])
|
89
90
|
end
|
91
|
+
# ... code for create / update / destroy is skipped ...
|
90
92
|
end
|
91
93
|
```
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
```ruby
|
96
|
-
GraphqlRails::Router.draw do
|
97
|
-
# generates `friend`, `createFriend`, `updateFriend`, `destroyFriend`, `friends` routes
|
98
|
-
resources :friends
|
99
|
-
resources :shops, only: [:show, :index] # generates `shop` and `shops` routes only
|
100
|
-
resources :orders, except: :update # generates all routes except `updateOrder`
|
101
|
-
|
102
|
-
resources :users do
|
103
|
-
# generates `findUser` query
|
104
|
-
query :find, on: :member
|
105
|
-
|
106
|
-
# generates `searchUsers` query
|
107
|
-
query :search, on: :collection
|
108
|
-
end
|
109
|
-
|
110
|
-
# you can use namespaced controllers too:
|
111
|
-
scope module: 'admin' do
|
112
|
-
# `updateTranslations` route will be handled by `Admin::TranslationsController`
|
113
|
-
mutation :updateTranslations, to: 'translations#update'
|
114
|
-
|
115
|
-
# all :groups routes will be handled by `Admin::GroupsController`
|
116
|
-
resources :groups
|
117
|
-
end
|
118
|
-
end
|
119
|
-
```
|
95
|
+
See [Controller docs](components/controller.md) for more info.
|
120
96
|
|
121
97
|
## Testing your GraphqlRails::Controller in RSpec
|
122
98
|
|
@@ -134,6 +110,8 @@ RSpec.configure do |config|
|
|
134
110
|
end
|
135
111
|
```
|
136
112
|
|
113
|
+
See [Testing docs](testing/testing.md) for more info.
|
114
|
+
|
137
115
|
### Helper methods
|
138
116
|
|
139
117
|
There are 3 helper methods:
|
data/docs/_sidebar.md
CHANGED
@@ -144,7 +144,7 @@ end
|
|
144
144
|
If you do not specify `subtype` then default (without name) input will be used. You need to specify subtype if you want to use non-default input:
|
145
145
|
|
146
146
|
```ruby
|
147
|
-
class
|
147
|
+
class UsersController < GraphqlRails::Controller
|
148
148
|
# this is the input with email and full_name:
|
149
149
|
action(:create)
|
150
150
|
.permit_input(:input, type: 'User!')
|
@@ -155,6 +155,20 @@ class OrderController < GraphqlRails::Controller
|
|
155
155
|
end
|
156
156
|
```
|
157
157
|
|
158
|
+
#### *deprecated*
|
159
|
+
|
160
|
+
You can mark input input as deprecated with `deprecated` option:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
class UsersController < GraphqlRails::Controller
|
164
|
+
action(:create)
|
165
|
+
.permit_input(:input, type: 'User', deprecated: true)
|
166
|
+
|
167
|
+
action(:update)
|
168
|
+
.permit_input(:input, type: 'User', deprecated: 'use updateBasicUser instead')
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
158
172
|
### *paginated*
|
159
173
|
|
160
174
|
You can mark collection action as `paginated`. In this case controller will return relay connection type and it will be possible to return only partial results. No need to do anything on controller side (you should always return full list of items)
|
data/docs/components/model.md
CHANGED
@@ -101,7 +101,7 @@ Check [graphql-ruby documentation](https://graphql-ruby.org) for more details ab
|
|
101
101
|
|
102
102
|
### attribute.property
|
103
103
|
|
104
|
-
By default graphql attribute names are expected to be same as model methods/attributes, but if you want to use different name on
|
104
|
+
By default graphql attribute names are expected to be same as model methods/attributes, but if you want to use different name on graphql side, you can use `property` option:
|
105
105
|
|
106
106
|
```ruby
|
107
107
|
class User
|
@@ -131,6 +131,21 @@ class User
|
|
131
131
|
end
|
132
132
|
```
|
133
133
|
|
134
|
+
### attribute.deprecated
|
135
|
+
|
136
|
+
Attribute can be marked as deprecated with `deprecated` method:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
class User
|
140
|
+
include GraphqlRails::Model
|
141
|
+
|
142
|
+
graphql do |c|
|
143
|
+
c.attribute(:legacy_name).deprecated
|
144
|
+
c.attribute(:legacy_id).deprecated('This is my custom deprecation reason')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
134
149
|
### attribute.groups
|
135
150
|
|
136
151
|
Groups are handy feature when you want to have multiple schemas. For example, you want to have public graphql endpoint and internal graphql endpoint where each group has some unique nodes. If attribute has `groups` set, then this attribute will be visible only in appropriate group schemas.
|
@@ -170,6 +185,24 @@ class User
|
|
170
185
|
end
|
171
186
|
```
|
172
187
|
|
188
|
+
### attribute.hidden_in_groups
|
189
|
+
|
190
|
+
Opposite for Attribute#groups. It hides attribute in given groups
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
class User
|
194
|
+
include GraphqlRails::Model
|
195
|
+
|
196
|
+
graphql do |c|
|
197
|
+
# visible in all schemas (default):
|
198
|
+
c.attribute(:email)
|
199
|
+
|
200
|
+
# visible in all schemas except "external":
|
201
|
+
c.attribute(:nickname).hidden_in_groups(:external)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
173
206
|
### attribute.options
|
174
207
|
|
175
208
|
Allows passing options to attribute definition. Available options:
|
@@ -185,6 +218,21 @@ class User
|
|
185
218
|
c.attribute :first_name, options: { attribute_name_format: :original } # will be accessible as first_name from client side
|
186
219
|
end
|
187
220
|
end
|
221
|
+
```
|
222
|
+
|
223
|
+
### attribute.extras
|
224
|
+
|
225
|
+
Allows passing extras to enable [graphql-ruby field extensions](https://graphql-ruby.org/type_definitions/field_extensions.html#using-extras)
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
class User
|
229
|
+
include GraphqlRails::Model
|
230
|
+
|
231
|
+
graphql do |c|
|
232
|
+
c.attribute(:items).extras([:lookahead])
|
233
|
+
end
|
234
|
+
end
|
235
|
+
```
|
188
236
|
|
189
237
|
### attribute.permit
|
190
238
|
|
@@ -263,6 +311,23 @@ class User
|
|
263
311
|
end
|
264
312
|
```
|
265
313
|
|
314
|
+
#### *deprecated*
|
315
|
+
|
316
|
+
You can mark input input as deprecated with `deprecated` option:
|
317
|
+
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
class User
|
321
|
+
include GraphqlRails::Model
|
322
|
+
|
323
|
+
graphql.attribute(:avatar_url)
|
324
|
+
.permit_input(:size, type: :int!, deprecated: true)
|
325
|
+
|
326
|
+
graphql.attribute(:logo_url)
|
327
|
+
.permit_input(:size, type: :int!, deprecated: 'custom image size is deprecated')
|
328
|
+
end
|
329
|
+
```
|
330
|
+
|
266
331
|
### attribute.paginated
|
267
332
|
|
268
333
|
You can mark collection method as `paginated`. In this case method will return relay connection type and it will be possible to return only partial results. No need to do anything on method side (you should always return full list of items)
|
@@ -271,7 +336,7 @@ You can mark collection method as `paginated`. In this case method will return r
|
|
271
336
|
class User
|
272
337
|
include GraphqlRails::Model
|
273
338
|
|
274
|
-
graphql.attribute :items, type: '[Item]',
|
339
|
+
graphql.attribute :items, type: '[Item]', paginated: true
|
275
340
|
|
276
341
|
def items
|
277
342
|
Item.all
|
@@ -356,7 +421,7 @@ end
|
|
356
421
|
|
357
422
|
## name
|
358
423
|
|
359
|
-
By default
|
424
|
+
By default graphql type name will be same as model name, but you can change it via `name` method
|
360
425
|
|
361
426
|
```ruby
|
362
427
|
class User
|
@@ -370,7 +435,7 @@ end
|
|
370
435
|
|
371
436
|
## description
|
372
437
|
|
373
|
-
To improve
|
438
|
+
To improve graphql documentation, you can description for your graphql type:
|
374
439
|
|
375
440
|
```ruby
|
376
441
|
class User
|
@@ -387,7 +452,7 @@ end
|
|
387
452
|
Sometimes it's handy to get raw graphql type. To do so you can call:
|
388
453
|
|
389
454
|
```ruby
|
390
|
-
YourModel.graphql.
|
455
|
+
YourModel.graphql.graphql_type
|
391
456
|
```
|
392
457
|
|
393
458
|
## input
|
@@ -523,6 +588,36 @@ class User
|
|
523
588
|
end
|
524
589
|
```
|
525
590
|
|
591
|
+
|
592
|
+
#### input attribute deprecation
|
593
|
+
|
594
|
+
You can mark input attribute as deprecated with `deprecated` method:
|
595
|
+
|
596
|
+
```ruby
|
597
|
+
class User
|
598
|
+
include GraphqlRails::Model
|
599
|
+
|
600
|
+
graphql.input do |c|
|
601
|
+
c.attribute(:full_name).deprecated('Use firstName and lastName instead')
|
602
|
+
c.attribute(:surname).deprecated
|
603
|
+
end
|
604
|
+
end
|
605
|
+
```
|
606
|
+
|
607
|
+
#### input attribute default value
|
608
|
+
|
609
|
+
You can set default value for input attribute:
|
610
|
+
|
611
|
+
```ruby
|
612
|
+
class User
|
613
|
+
include GraphqlRails::Model
|
614
|
+
|
615
|
+
graphql.input do |c|
|
616
|
+
c.attribute(:is_admin).type('Boolean').default_value(false)
|
617
|
+
end
|
618
|
+
end
|
619
|
+
```
|
620
|
+
|
526
621
|
## graphql_context
|
527
622
|
|
528
623
|
It's possible to access graphql_context in your model using method `graphql_context`:
|
data/docs/components/routes.md
CHANGED
@@ -21,10 +21,10 @@ MyGraphqlSchema = GraphqlRails::Router.draw do
|
|
21
21
|
|
22
22
|
# you can use namespaced controllers too:
|
23
23
|
scope module: 'admin' do
|
24
|
-
# `updateTranslations` route will be
|
24
|
+
# `updateTranslations` route will be handled by `Admin::TranslationsController`
|
25
25
|
mutation :updateTranslations, to: 'translations#update'
|
26
26
|
|
27
|
-
# all :groups routes will be
|
27
|
+
# all :groups routes will be handled by `Admin::GroupsController`
|
28
28
|
resources :groups
|
29
29
|
end
|
30
30
|
end
|
@@ -40,9 +40,9 @@ If you want to exclude some actions you can use `only` or `except` options.
|
|
40
40
|
|
41
41
|
```ruby
|
42
42
|
MyGraphqlSchema = GraphqlRails::Router.draw do
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
resources :users
|
44
|
+
resources :friends, only: :index
|
45
|
+
resources :posts, except: [:destroy, :index]
|
46
46
|
end
|
47
47
|
```
|
48
48
|
|
@@ -52,7 +52,7 @@ Sometimes it's handy so have non-CRUD actions in your controller. To define such
|
|
52
52
|
|
53
53
|
```ruby
|
54
54
|
MyGraphqlSchema = GraphqlRails::Router.draw do
|
55
|
-
|
55
|
+
resources :users do
|
56
56
|
mutation :changePassword, on: :member
|
57
57
|
query :active, on: :collection
|
58
58
|
end
|
@@ -65,7 +65,7 @@ Sometimes, especially when working with member queries, it sounds better when ac
|
|
65
65
|
|
66
66
|
```ruby
|
67
67
|
MyGraphqlSchema = GraphqlRails::Router.draw do
|
68
|
-
|
68
|
+
resources :users do
|
69
69
|
query :details, on: :member, suffix: true
|
70
70
|
end
|
71
71
|
end
|
@@ -73,15 +73,25 @@ end
|
|
73
73
|
|
74
74
|
This will generate `userDetails` field on GraphQL side.
|
75
75
|
|
76
|
-
## _query_ and _mutation_ &
|
76
|
+
## _query_ and _mutation_ & _event_
|
77
77
|
|
78
|
-
|
78
|
+
In case you want to have non-CRUD controller with custom actions you can define your own `query`/`mutation` actions like this:
|
79
79
|
|
80
80
|
```ruby
|
81
81
|
MyGraphqlSchema = GraphqlRails::Router.draw do
|
82
82
|
mutation :logIn, to: 'sessions#login'
|
83
83
|
query :me, to: 'users#current_user'
|
84
|
-
|
84
|
+
end
|
85
|
+
|
86
|
+
Subscriptions are not really controller actions with a single response type, thus, they're defined differently. In GraphQL you subscribe to event, for example `userCreated`. To do this in graphql_rails you would define `event :user_created` in router definition.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
MyGraphqlSchema = GraphqlRails::Router.draw do
|
90
|
+
mutation :logIn, to: 'sessions#login'
|
91
|
+
query :me, to: 'users#current_user'
|
92
|
+
|
93
|
+
event :user_created # expects Subscriptions::UserCreatedSubscription class to be present
|
94
|
+
event :user_deleted, subscription_class: 'Subscriptions::UserDeletedSubscription'
|
85
95
|
end
|
86
96
|
```
|
87
97
|
|
@@ -89,18 +99,54 @@ end
|
|
89
99
|
|
90
100
|
### _module_ options
|
91
101
|
|
92
|
-
|
102
|
+
If you want to want to route everything to controllers, located at `controllers/admin/top_secret`, you can use scope with `module` param:
|
93
103
|
|
94
104
|
```ruby
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
105
|
+
scope module: 'admin/top_secret' do
|
106
|
+
mutation :logIn, to: 'sessions#login' # this will trigger Admin::TopSecret::SessionsController
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
### Named scope
|
99
111
|
|
112
|
+
If you want to nest some routes under some other node, you can use named scope:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
scope :admin do
|
100
116
|
mutation :logIn, to: 'sessions#login' # this will trigger ::SessionsController
|
101
117
|
end
|
102
118
|
```
|
103
119
|
|
120
|
+
This action will be accessible via:
|
121
|
+
|
122
|
+
```graphql
|
123
|
+
mutation {
|
124
|
+
admin {
|
125
|
+
logIn(email: 'john@example.com') { ... }
|
126
|
+
}
|
127
|
+
}
|
128
|
+
```
|
129
|
+
|
130
|
+
## _namespace_
|
131
|
+
|
132
|
+
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an `Admin::` namespace, and place these controllers under the app/controllers/admin directory. You can route to such a group by using a namespace block:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
namespace :admin do
|
136
|
+
resources :articles, only: :show
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
On GraphQL side, you can reach such route with the following query:
|
141
|
+
|
142
|
+
```graphql
|
143
|
+
query {
|
144
|
+
admin {
|
145
|
+
article(id: '123') { ... }
|
146
|
+
}
|
147
|
+
}
|
148
|
+
```
|
149
|
+
|
104
150
|
## _group_
|
105
151
|
|
106
152
|
You can have multiple routers / schemas. In order to add resources or query only to specific schema, you need wrap it with `group` method, like this:
|
data/graphql_rails.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_dependency 'graphql', '
|
23
|
+
spec.add_dependency 'graphql', '2.0.21'
|
24
24
|
spec.add_dependency 'activesupport', '>= 4'
|
25
25
|
|
26
26
|
spec.add_development_dependency 'bundler', '~> 2'
|
@@ -12,7 +12,7 @@ class GraphqlController < ApplicationController
|
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
|
-
# data defined here will be accessible via `
|
15
|
+
# data defined here will be accessible via `graphql_request.context`
|
16
16
|
# in GraphqlRails::Controller instances
|
17
17
|
def graphql_context
|
18
18
|
{}
|
@@ -32,8 +32,8 @@ module GraphqlRails
|
|
32
32
|
[
|
33
33
|
field_name,
|
34
34
|
type_parser.type_arg,
|
35
|
-
|
36
|
-
]
|
35
|
+
description
|
36
|
+
].compact
|
37
37
|
end
|
38
38
|
|
39
39
|
def field_options
|
@@ -41,30 +41,32 @@ module GraphqlRails
|
|
41
41
|
method: property.to_sym,
|
42
42
|
null: optional?,
|
43
43
|
camelize: camelize?,
|
44
|
-
groups: groups
|
44
|
+
groups: groups,
|
45
|
+
hidden_in_groups: hidden_in_groups,
|
46
|
+
**deprecation_reason_params,
|
47
|
+
**extras_options
|
45
48
|
}
|
46
49
|
end
|
47
50
|
|
48
|
-
def argument_args
|
49
|
-
[
|
50
|
-
field_name,
|
51
|
-
type_parser.type_arg,
|
52
|
-
{
|
53
|
-
description: description,
|
54
|
-
required: required?
|
55
|
-
}
|
56
|
-
]
|
57
|
-
end
|
58
|
-
|
59
51
|
protected
|
60
52
|
|
61
53
|
attr_reader :initial_name
|
62
54
|
|
63
55
|
private
|
64
56
|
|
57
|
+
def extras_options
|
58
|
+
return {} if extras.empty?
|
59
|
+
|
60
|
+
{ extras: extras }
|
61
|
+
end
|
62
|
+
|
65
63
|
def camelize?
|
66
64
|
options[:input_format] != :original && options[:attribute_name_format] != :original
|
67
65
|
end
|
66
|
+
|
67
|
+
def deprecation_reason_params
|
68
|
+
{ deprecation_reason: deprecation_reason }.compact
|
69
|
+
end
|
68
70
|
end
|
69
71
|
end
|
70
72
|
end
|