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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +3 -2
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +16 -0
  5. data/Gemfile.lock +17 -17
  6. data/docs/README.md +23 -45
  7. data/docs/_sidebar.md +0 -1
  8. data/docs/components/controller.md +15 -1
  9. data/docs/components/decorator.md +1 -1
  10. data/docs/components/model.md +100 -5
  11. data/docs/components/routes.md +61 -15
  12. data/graphql_rails.gemspec +1 -1
  13. data/lib/generators/graphql_rails/templates/graphql_controller.erb +1 -1
  14. data/lib/graphql_rails/attributes/attribute.rb +16 -14
  15. data/lib/graphql_rails/attributes/attribute_configurable.rb +24 -0
  16. data/lib/graphql_rails/attributes/attribute_name_parser.rb +4 -4
  17. data/lib/graphql_rails/attributes/input_attribute.rb +19 -2
  18. data/lib/graphql_rails/attributes/type_parseable.rb +4 -5
  19. data/lib/graphql_rails/controller/action_configuration.rb +1 -1
  20. data/lib/graphql_rails/controller/build_controller_action_resolver.rb +2 -0
  21. data/lib/graphql_rails/controller/configuration.rb +1 -1
  22. data/lib/graphql_rails/controller/request/format_errors.rb +1 -1
  23. data/lib/graphql_rails/controller/request.rb +3 -2
  24. data/lib/graphql_rails/controller.rb +1 -1
  25. data/lib/graphql_rails/decorator/relation_decorator.rb +24 -20
  26. data/lib/graphql_rails/decorator.rb +12 -4
  27. data/lib/graphql_rails/errors/custom_execution_error.rb +1 -1
  28. data/lib/graphql_rails/errors/execution_error.rb +1 -1
  29. data/lib/graphql_rails/errors/system_error.rb +11 -1
  30. data/lib/graphql_rails/errors/validation_error.rb +14 -1
  31. data/lib/graphql_rails/model/find_or_build_graphql_input_type.rb +28 -0
  32. data/lib/graphql_rails/model/find_or_build_graphql_type.rb +14 -5
  33. data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +4 -3
  34. data/lib/graphql_rails/model/input.rb +3 -3
  35. data/lib/graphql_rails/router/build_schema_action_type.rb +112 -0
  36. data/lib/graphql_rails/router/event_route.rb +52 -0
  37. data/lib/graphql_rails/router/mutation_route.rb +1 -1
  38. data/lib/graphql_rails/router/query_route.rb +1 -1
  39. data/lib/graphql_rails/router/resource_routes_builder.rb +0 -8
  40. data/lib/graphql_rails/router/route.rb +4 -3
  41. data/lib/graphql_rails/router/schema_builder.rb +18 -26
  42. data/lib/graphql_rails/router.rb +32 -16
  43. data/lib/graphql_rails/rspec_controller_helpers.rb +3 -1
  44. data/lib/graphql_rails/types/hidable_by_group.rb +23 -3
  45. data/lib/graphql_rails/types/input_object_type.rb +16 -0
  46. data/lib/graphql_rails/version.rb +1 -1
  47. metadata +11 -16
  48. data/docs/getting_started/quick_start.md +0 -62
  49. data/lib/graphql_rails/model/build_graphql_input_type.rb +0 -43
  50. 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: 1909c3b76c9addab63bcc0337232c147ceebde0d1f2252da93606b48d1843c64
4
- data.tar.gz: 6b405941e4bae0e98abbcc07b93ac1a95fa22bcbdfcaa962d241740a15453ba7
3
+ metadata.gz: 9ef0115ce3d9107ee48ec4e7a725baff242ce81133be4a955d0a81619b106192
4
+ data.tar.gz: dcb027f23eb5f6cd71b3144e2794822ee899796a5e40f7b240ea3cd59ef586b9
5
5
  SHA512:
6
- metadata.gz: f5292647cd5c49c51bec7f9f1df33be882637ac83bd54fb23259fc2b5c6d8f351f3501c5db23f0ff7c10daafafed531b4026ff3790ff281cfd71890ff2b2c007
7
- data.tar.gz: 054adf43e83c54be23fb33547ee521e17ae8f180f5f4c05bf3a7b78f554367e6531483d9bf66af75fe4567940f2931c56f93c2adc6af412efba8e644043af8bc
6
+ metadata.gz: 8282983f1215feffb37e0541680abd91a44799a95d687cb3adb5cfcb91a1adbf8a07d585fffcd4e477579eebdd9f4a09f0efbc6dfb0b264b0a1a288aa0ac9688
7
+ data.tar.gz: f7cafd9924e8e26abc9a6e5783938ebedbea7a0dd68fc69a5980186affab6593f8af4a25c8205e20fbfb45534bec96aa4b5b36bc558084994200a73f8eca31d7
@@ -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.6', '2.7', '3.0']
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@v2
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.0.1
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.2.0)
4
+ graphql_rails (2.4.0)
5
5
  activesupport (>= 4)
6
- graphql (~> 1.12, >= 1.12.4)
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.9)
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.0)
82
+ globalid (1.0.1)
83
83
  activesupport (>= 5.0)
84
- graphql (1.13.6)
85
- i18n (1.8.11)
84
+ graphql (2.0.21)
85
+ i18n (1.12.0)
86
86
  concurrent-ruby (~> 1.0)
87
- loofah (2.13.0)
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.7.1)
96
- minitest (5.15.0)
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.13.1)
105
- mini_portile2 (~> 2.7.0)
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.0)
117
- rack (2.2.3)
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.2)
139
- loofah (~> 2.3)
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.4)
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.5.3)
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' # redirects request to LogsController
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 :id
60
+ c.attribute(:id)
60
61
 
61
- c.attribute :email, type: :string
62
- c.attribute :surname, type: :string
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
- # graphql requires to describe which attributes controller action accepts and which returns
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
- def change_user_password
78
- user = User.find(params[:id])
79
- user.update!(password: params[:password])
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
- # returned value needs to have all methods defined in model `graphql do` part
82
- user # or SomeDecorator.new(user)
84
+ def index
85
+ User.all
83
86
  end
84
87
 
85
- action(:search)
86
- .permit(search_fields!: SearchFieldsInput) # you can specify your own input fields
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
- ## Routes
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
@@ -1,7 +1,6 @@
1
1
  * [Home](README)
2
2
  * Getting started
3
3
  * [Setup](getting_started/setup)
4
- * [Quick start](getting_started/quick_start)
5
4
  * Components
6
5
  * [Routes](components/routes)
7
6
  * [Model](components/model)
@@ -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 OrderController < GraphqlRails::Controller
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)
@@ -46,7 +46,7 @@ class UserDecorator < SimpleDelegator
46
46
  include GraphqlRails::Model
47
47
  include GraphqlRails::Decorator
48
48
 
49
- graphql_rails do
49
+ graphql do |c|
50
50
  # some setup, attributes, etc...
51
51
  end
52
52
 
@@ -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 grapqhl side, you can use `property` option:
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]', paginatted: true
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 grapqhl type name will be same as model name, but you can change it via `name` method
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 grapqhl documentation, you can description for your graphql type:
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.grapqhl_type
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`:
@@ -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 handeled by `Admin::TranslationsController`
24
+ # `updateTranslations` route will be handled by `Admin::TranslationsController`
25
25
  mutation :updateTranslations, to: 'translations#update'
26
26
 
27
- # all :groups routes will be handeled by `Admin::GroupsController`
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
- resouces :users
44
- resouces :friends, only: :index
45
- resouces :posts, except: [:destroy, :index]
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
- resouces :users do
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
- resouces :users do
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_ & _subscription_
76
+ ## _query_ and _mutation_ & _event_
77
77
 
78
- in case you want to have non-CRUD controller with custom actions you can define your own `query`/`mutation`/`subscription` actions like this:
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
- subscribtion :new_message, to: 'messages#created'
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
- currently `scope` method accepts single option: `module`. `module` allows to specify controller namespace. So you can use scoped controllers, like so:
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
- MyGraphqlSchema = GraphqlRails::Router.draw do
96
- scope module: 'admin/top_secret' do
97
- mutation :logIn, to: 'sessions#login' # this will trigger Admin::TopSecret::SessionsController
98
- end
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:
@@ -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', '~> 1.12', '>= 1.12.4'
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 `grapqhl_request.context`
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
- *description
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