graphql_rails 0.8.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/Gemfile.lock +20 -23
  4. data/docs/README.md +21 -5
  5. data/docs/_sidebar.md +3 -0
  6. data/docs/components/controller.md +174 -17
  7. data/docs/components/model.md +151 -3
  8. data/docs/components/routes.md +28 -0
  9. data/docs/getting_started/quick_start.md +9 -2
  10. data/docs/other_tools/query_runner.md +49 -0
  11. data/docs/other_tools/schema_dump.md +29 -0
  12. data/docs/testing/testing.md +3 -1
  13. data/graphql_rails.gemspec +1 -1
  14. data/lib/generators/graphql_rails/install_generator.rb +50 -0
  15. data/lib/generators/graphql_rails/templates/example_users_controller.erb +19 -0
  16. data/lib/generators/graphql_rails/templates/graphql_application_controller.erb +8 -0
  17. data/lib/generators/graphql_rails/templates/graphql_controller.erb +20 -0
  18. data/lib/generators/graphql_rails/templates/graphql_router.erb +19 -0
  19. data/lib/generators/graphql_rails/templates/graphql_router_spec.erb +18 -0
  20. data/lib/graphql_rails.rb +2 -0
  21. data/lib/graphql_rails/attributes/attributable.rb +16 -13
  22. data/lib/graphql_rails/attributes/attribute.rb +20 -3
  23. data/lib/graphql_rails/attributes/input_attribute.rb +20 -10
  24. data/lib/graphql_rails/attributes/input_type_parser.rb +24 -46
  25. data/lib/graphql_rails/attributes/type_parseable.rb +128 -0
  26. data/lib/graphql_rails/attributes/type_parser.rb +58 -54
  27. data/lib/graphql_rails/concerns/service.rb +15 -0
  28. data/lib/graphql_rails/controller.rb +20 -16
  29. data/lib/graphql_rails/controller/action.rb +10 -69
  30. data/lib/graphql_rails/controller/action_configuration.rb +70 -34
  31. data/lib/graphql_rails/controller/build_controller_action_resolver.rb +52 -0
  32. data/lib/graphql_rails/controller/build_controller_action_resolver/controller_action_resolver.rb +28 -0
  33. data/lib/graphql_rails/controller/configuration.rb +56 -5
  34. data/lib/graphql_rails/controller/log_controller_action.rb +4 -4
  35. data/lib/graphql_rails/controller/request.rb +29 -8
  36. data/lib/graphql_rails/controller/request/format_errors.rb +58 -0
  37. data/lib/graphql_rails/decorator/relation_decorator.rb +1 -1
  38. data/lib/graphql_rails/errors/custom_execution_error.rb +22 -0
  39. data/lib/graphql_rails/errors/execution_error.rb +6 -7
  40. data/lib/graphql_rails/errors/system_error.rb +14 -0
  41. data/lib/graphql_rails/errors/validation_error.rb +1 -5
  42. data/lib/graphql_rails/input_configurable.rb +47 -0
  43. data/lib/graphql_rails/model.rb +19 -4
  44. data/lib/graphql_rails/model/build_connection_type.rb +48 -0
  45. data/lib/graphql_rails/model/{configuration → build_connection_type}/count_items.rb +4 -4
  46. data/lib/graphql_rails/model/build_enum_type.rb +39 -10
  47. data/lib/graphql_rails/model/build_graphql_input_type.rb +7 -3
  48. data/lib/graphql_rails/model/build_graphql_type.rb +23 -7
  49. data/lib/graphql_rails/model/call_graphql_model_method.rb +59 -0
  50. data/lib/graphql_rails/model/configuration.rb +2 -6
  51. data/lib/graphql_rails/model/input.rb +10 -6
  52. data/lib/graphql_rails/query_runner.rb +68 -0
  53. data/lib/graphql_rails/railtie.rb +10 -0
  54. data/lib/graphql_rails/router.rb +40 -13
  55. data/lib/graphql_rails/router/resource_routes_builder.rb +2 -1
  56. data/lib/graphql_rails/router/route.rb +25 -6
  57. data/lib/graphql_rails/router/schema_builder.rb +26 -11
  58. data/lib/graphql_rails/rspec_controller_helpers.rb +4 -2
  59. data/lib/graphql_rails/tasks/dump_graphql_schema.rb +57 -0
  60. data/lib/graphql_rails/tasks/schema.rake +14 -0
  61. data/lib/graphql_rails/version.rb +1 -1
  62. metadata +29 -9
  63. data/lib/graphql_rails/controller/controller_function.rb +0 -50
  64. data/lib/graphql_rails/controller/format_results.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 233cb42d66f27e1bd3b18d5530977285e84358897d9fa4cde2230a811b4712b1
4
- data.tar.gz: 773ff5c8223431e2b606c522fbcc5275157d7255b6348bf475a0aa9c76282926
3
+ metadata.gz: fcc5df5d34e3bf317dd9bb07e2b846bf8dfa48e990258b4bb2f30ef73d049939
4
+ data.tar.gz: 6cd112b22a0d01f031dd2aba92efc390d44b209c8d6a428e257d1be99377f28c
5
5
  SHA512:
6
- metadata.gz: c1034a92ab82fb88dfb94b2eb6502b51e2d97ef4f04e6804abd6cb3a8900117682f6cc717576d5aa16008d3486a8182dc2f503d5d307ad9184177e7968d13467
7
- data.tar.gz: d44a9b5d7ad5d3a2663bc40edcef96240e7525e2060ca57d360b6b8640af03ebfd3dc13eae97e11ac77d07d1d283a9480bd567e84aa0f7dc8960e35d6ad329a1
6
+ metadata.gz: 59f24a1ad00e309c7617a6ed65200dc11f62680974f3de7ca4e36d96b0d8dab8f286c8c9c4b50dd4b70a375959187ce21d09a309075a4ffa009716d3b74e7df7
7
+ data.tar.gz: ca1500174b1443240db65e3b57dbe0616ad7038da3e6f833ca2979e2fb4de7074c8ce9671c55dfa07bb327f4469b7999b8f00769a686c8829abfcf2eb275b6e0
@@ -9,6 +9,19 @@ 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
+ ## [1.0.0](2020-02-07)
13
+
14
+ * Added: "required" and "optional" flags for attribute
15
+ * Added: grouped routes
16
+ * Added: added argument to model.attribute
17
+ * Added: added graphql_context to model
18
+ * Removed: `action.can_return_nil` was removed, because it does no affect anymore
19
+ * Removed: default `action` model was removed. Now each action must have `returns` part
20
+ * Added: default router added. No need to assign value to constant on Router.draw
21
+ * Added: default action added. Now actions can have custom defaults
22
+ * Added: default controller model added. Now actions can be defined in more dynamic way
23
+ * Added: install generator. Now it's possible to generate boilerplate code
24
+
12
25
  ## [0.8.0] (2019-09-03)
13
26
 
14
27
  * Added: permit_input action config with extended list of permitted input options
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_rails (0.8.0)
4
+ graphql_rails (1.0.0)
5
5
  activesupport (>= 4)
6
- graphql (~> 1)
6
+ graphql (>= 1.9.12)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
@@ -60,18 +60,18 @@ GEM
60
60
  url
61
61
  coderay (1.1.2)
62
62
  concurrent-ruby (1.1.5)
63
- crass (1.0.4)
63
+ crass (1.0.5)
64
64
  diff-lcs (1.3)
65
- docile (1.3.1)
65
+ docile (1.3.2)
66
66
  erubi (1.8.0)
67
67
  globalid (0.4.2)
68
68
  activesupport (>= 4.2.0)
69
- graphql (1.9.7)
69
+ graphql (1.9.17)
70
70
  i18n (1.6.0)
71
71
  concurrent-ruby (~> 1.0)
72
- jaro_winkler (1.5.2)
73
- json (2.2.0)
74
- loofah (2.2.3)
72
+ jaro_winkler (1.5.4)
73
+ json (2.3.0)
74
+ loofah (2.3.1)
75
75
  crass (~> 1.0.2)
76
76
  nokogiri (>= 1.5.9)
77
77
  mail (2.7.1)
@@ -89,10 +89,10 @@ GEM
89
89
  activemodel (>= 5.1, < 6.0.0)
90
90
  mongo (>= 2.5.1, < 3.0.0)
91
91
  nio4r (2.3.1)
92
- nokogiri (1.10.4)
92
+ nokogiri (1.10.5)
93
93
  mini_portile2 (~> 2.4.0)
94
- parallel (1.16.0)
95
- parser (2.6.2.0)
94
+ parallel (1.19.1)
95
+ parser (2.7.0.2)
96
96
  ast (~> 2.4.0)
97
97
  pry (0.12.2)
98
98
  coderay (~> 1.1.0)
@@ -100,8 +100,7 @@ GEM
100
100
  pry-byebug (3.7.0)
101
101
  byebug (~> 11.0)
102
102
  pry (~> 0.10)
103
- psych (3.1.0)
104
- rack (2.0.7)
103
+ rack (2.0.8)
105
104
  rack-test (1.1.0)
106
105
  rack (>= 1.0, < 3)
107
106
  rails (5.2.2.1)
@@ -143,22 +142,20 @@ GEM
143
142
  diff-lcs (>= 1.2.0, < 2.0)
144
143
  rspec-support (~> 3.8.0)
145
144
  rspec-support (3.8.0)
146
- rubocop (0.66.0)
145
+ rubocop (0.79.0)
147
146
  jaro_winkler (~> 1.5.1)
148
147
  parallel (~> 1.10)
149
- parser (>= 2.5, != 2.5.1.1)
150
- psych (>= 3.1.0)
148
+ parser (>= 2.7.0.1)
151
149
  rainbow (>= 2.2.2, < 4.0)
152
150
  ruby-progressbar (~> 1.7)
153
- unicode-display_width (>= 1.4.0, < 1.6)
151
+ unicode-display_width (>= 1.4.0, < 1.7)
154
152
  rubocop-rspec (1.32.0)
155
153
  rubocop (>= 0.60.0)
156
- ruby-progressbar (1.10.0)
157
- simplecov (0.16.1)
154
+ ruby-progressbar (1.10.1)
155
+ simplecov (0.18.1)
158
156
  docile (~> 1.1)
159
- json (>= 1.8, < 3)
160
- simplecov-html (~> 0.10.0)
161
- simplecov-html (0.10.2)
157
+ simplecov-html (~> 0.11.0)
158
+ simplecov-html (0.11.0)
162
159
  sprockets (3.7.2)
163
160
  concurrent-ruby (~> 1.0)
164
161
  rack (> 1, < 3)
@@ -170,7 +167,7 @@ GEM
170
167
  thread_safe (0.3.6)
171
168
  tzinfo (1.2.5)
172
169
  thread_safe (~> 0.1)
173
- unicode-display_width (1.5.0)
170
+ unicode-display_width (1.6.1)
174
171
  url (0.3.2)
175
172
  websocket-driver (0.7.1)
176
173
  websocket-extensions (>= 0.1.0)
@@ -22,12 +22,21 @@ Or install it yourself as:
22
22
 
23
23
  $ gem install graphql_rails
24
24
 
25
+ ## Getting started
26
+
27
+ Execute:
28
+
29
+ $ bundle exec rails g graphql_rails:install
30
+
31
+ This will generate code which will let you start your graphql faster
32
+
25
33
  ## Usage
26
34
 
27
35
  ### Define GraphQL schema as RoR routes
28
36
 
29
37
  ```ruby
30
- MyGraphqlSchema = GraphqlRails::Router.draw do
38
+ # config/graphql/routes.rb
39
+ GraphqlRails::Router.draw do
31
40
  # will create createUser, updateUser, deleteUser mutations and user, users queries.
32
41
  # expects that UsersController class exist
33
42
  resources :users
@@ -41,6 +50,7 @@ end
41
50
  ### Define your Graphql model
42
51
 
43
52
  ```ruby
53
+ # app/models/user.rb
44
54
  class User # works with any class including ActiveRecord
45
55
  include GraphqlRails::Model
46
56
 
@@ -57,10 +67,12 @@ end
57
67
  ### Define controller
58
68
 
59
69
  ```ruby
60
- class UsersController < GraphqlRails::Controller
70
+ # app/controllers/graphql/users_controller.rb
71
+ class Graphql::UsersController < GraphqlApplicationController
61
72
  # graphql requires to describe which attributes controller action accepts and which returns
62
73
  action(:change_user_password)
63
74
  .permit(:password!, :id!) # Bang (!) indicates that attribute is required
75
+ .returns('User!')
64
76
 
65
77
  def change_user_password
66
78
  user = User.find(params[:id])
@@ -70,7 +82,9 @@ class UsersController < GraphqlRails::Controller
70
82
  user # or SomeDecorator.new(user)
71
83
  end
72
84
 
73
- action(:search).permit(search_fields!: SearchFieldsInput) # you can specify your own input fields
85
+ action(:search)
86
+ .permit(search_fields!: SearchFieldsInput) # you can specify your own input fields
87
+ .returns('[User!]!')
74
88
  def search
75
89
  end
76
90
  end
@@ -79,7 +93,7 @@ end
79
93
  ## Routes
80
94
 
81
95
  ```ruby
82
- MyGraphqlSchema = GraphqlRails::Router.draw do
96
+ GraphqlRails::Router.draw do
83
97
  # generates `friend`, `createFriend`, `updateFriend`, `destroyFriend`, `friends` routes
84
98
  resources :friends
85
99
  resources :shops, only: [:show, :index] # generates `shop` and `shops` routes only
@@ -132,11 +146,13 @@ There are 3 helper methods:
132
146
 
133
147
  ```ruby
134
148
  class MyGraphqlController
149
+ action(:create_user).permit(:full_name, :email).returns(User)
150
+ action(:index).returns('String')
151
+
135
152
  def index
136
153
  "Called from index: #{params[:message]}"
137
154
  end
138
155
 
139
- action(:create_user).permit(:full_name, :email)
140
156
  def create_user
141
157
  User.create!(params)
142
158
  end
@@ -9,3 +9,6 @@
9
9
  * [Decorator](components/decorator)
10
10
  * [Logging and monitoring](logging_and_monitoring/logging_and_monitoring)
11
11
  * [Testing](testing/testing)
12
+ * Other tools
13
+ * [Schema Snapshot](other_tools/schema_dump)
14
+ * [Query Runner](other_tools/query_runner)
@@ -155,22 +155,6 @@ class OrderController < GraphqlRails::Controller
155
155
  end
156
156
  ```
157
157
 
158
- ### *can_return_nil*
159
-
160
- By default it is expected that each controller action returns model or array of models. `nil` is not allowed. You can change that by adding `can_return_nil` like this:
161
-
162
- ```ruby
163
- class UsersController < GraphqlRails::Controller
164
- action(:show).permit(:email).can_return_nil
165
-
166
- def show
167
- user = User.find_by(email: params[:email])
168
- return nil if user.blank?
169
- user
170
- end
171
- end
172
- ```
173
-
174
158
  ### *paginated*
175
159
 
176
160
  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)
@@ -201,9 +185,29 @@ class UsersController < GraphqlRails::Controller
201
185
  end
202
186
  ```
203
187
 
188
+ ### *model*
189
+
190
+ If you want to define model dynamically, you can use combination of `model` and `returns_list` or `returns_single`. This is especially handy when model is used with `action_default`:
191
+
192
+ ```ruby
193
+ class OrdersController < GraphqlRails::Controller
194
+ model('Order')
195
+ action(:show).returns_single # returns `Order!`
196
+ action(:index).returns_list # returns `[Order!]!`
197
+
198
+ def show
199
+ Order.first
200
+ end
201
+
202
+ def index
203
+ Order.all
204
+ end
205
+ end
206
+ ```
207
+
204
208
  ### *returns*
205
209
 
206
- By default return type is determined by controller name. When you want to return some custom object, you can specify that with `returns` method:
210
+ You must specify what each action will return. This is done with `returns` method:
207
211
 
208
212
  ```ruby
209
213
  class UsersController < GraphqlRails::Controller
@@ -215,6 +219,32 @@ class UsersController < GraphqlRails::Controller
215
219
  end
216
220
  ```
217
221
 
222
+ ### *returns_list*
223
+
224
+ When you have defined `model` dynamically, you can use `returns_list` to indicate that action must return list without specifying model type for each action. By default list and inner types are required but you can change that with `required_list: false` and `required_inner: false`
225
+
226
+ ```ruby
227
+ class OrdersController < GraphqlRails::Controller
228
+ model('Order')
229
+
230
+ action(:index).returns_list(required_list: false, required_inner: false) # returns `[Order]`
231
+ action(:search).permit(:filter).returns_list # returns `[Order!]!`
232
+ end
233
+ ```
234
+
235
+ ### *returns_single*
236
+
237
+ When you have defined `model` dynamically, you can use `returns_single` to indicate that action must return single item without specifying model type for each action. By default return type is required, but you can change that by providing `required: false` flag:
238
+
239
+ ```ruby
240
+ class OrdersController < GraphqlRails::Controller
241
+ model('Order')
242
+
243
+ action(:show).returns_single(required: false) # returns `Order`
244
+ action(:update).permit(title: :string!).returns_single # returns `Order!`
245
+ end
246
+ ```
247
+
218
248
  ### *describe*
219
249
 
220
250
  If you want to improve graphql documentation, you can add description for each action. To do so, use `describe` method:
@@ -262,6 +292,39 @@ class UsersController < GraphqlRails::Controller
262
292
  end
263
293
  ```
264
294
 
295
+ ## *model*
296
+
297
+ `model` is just a shorter version of `action_default.model`. See `action.model` and `action_default` for more information:
298
+
299
+ ```ruby
300
+ class OrdersController < GraphqlRails::Controller
301
+ model('Order')
302
+ action(:show).returns_single # returns `Order!`
303
+ action(:index).returns_list # returns `[Order!]!`
304
+
305
+ def show
306
+ Order.first
307
+ end
308
+
309
+ def index
310
+ Order.all
311
+ end
312
+ end
313
+ ```
314
+
315
+ ## *action_default*
316
+
317
+ Sometimes you want to have some shared attributes for all your actions. In order to make this possible you need to use `action_default`. It acts identical to `action` and is "inherited" by all actions defined after `action_default` part:
318
+
319
+ ```ruby
320
+ class UsersController < GraphqlRails::Controller
321
+ action_default.permit(token: :string!)
322
+
323
+ action(:update).returns('User!') # action(:update) has `permit(token: :string!)
324
+ action(:create).returns('User') # action(:create) has `permit(token: :string!)
325
+ end
326
+ ```
327
+
265
328
  ## *before_action*
266
329
 
267
330
  You can add `before_action` to run some filters before calling your controller action. Here is an example:
@@ -376,3 +439,97 @@ end
376
439
  ## decorating objects
377
440
 
378
441
  See ['Decorating controller responses']('components/decorator') for various options how you can decorate paginated responses
442
+
443
+ ## Rendering errors
444
+
445
+ ### Rendering strings as errors
446
+
447
+ The simples way to render error is to provide list of error messages, like this:
448
+
449
+ ```ruby
450
+ class UsersController < GraphqlRails::Controller
451
+ action(:update).permit(:id, input: 'UserInput!').returns('User!')
452
+
453
+ def update
454
+ user = User.find(params[:id])
455
+
456
+ if user.update(params[:input])
457
+ user
458
+ else
459
+ render(errors: ['Something went wrong'])
460
+ end
461
+ end
462
+ end
463
+ ```
464
+
465
+ ### Rendering validation errors
466
+
467
+ GraphqlRails controller has `#render` method which you can use to render errors:
468
+
469
+ ```ruby
470
+ class UsersController < GraphqlRails::Controller
471
+ action(:update).permit(:id, input: 'UserInput!').returns('User!')
472
+
473
+ def update
474
+ user = User.find(params[:id])
475
+
476
+ if user.update(params[:input])
477
+ user
478
+ else
479
+ render(errors: user.errors)
480
+ end
481
+ end
482
+ end
483
+ ```
484
+
485
+ ### Rendering errors with custom data
486
+
487
+ When you want to return errors with custom data, you can provide hash like this:
488
+
489
+ ```ruby
490
+ class UsersController < GraphqlRails::Controller
491
+ action(:update).permit(:id, input: 'UserInput!').returns('User!')
492
+
493
+ def update
494
+ user = User.find(params[:id])
495
+
496
+ if user.update(params[:input])
497
+ user
498
+ else
499
+ render(
500
+ errors: [
501
+ { message: 'Something went wrong', code: 500, type: 'fatal' },
502
+ { message: 'Something went wrong', custom_param: true, ... },
503
+ ]
504
+ )
505
+ end
506
+ end
507
+ end
508
+ ```
509
+
510
+ ### Raising custom error classes
511
+
512
+ If you want to have customized error classes you need to create errors which inherits from `GraphqlRails::ExecutionError`
513
+
514
+ ```ruby
515
+ class MyCustomError < GraphqlRails::ExecutionError
516
+ def to_h
517
+ # this part will be rendered in graphl
518
+ { something_custom: 'yes' }
519
+ end
520
+ end
521
+
522
+ class UsersController < GraphqlRails::Controller
523
+ action(:update).permit(:id, input: 'UserInput!').returns('User!')
524
+
525
+ def update
526
+ user = User.find(params[:id])
527
+
528
+ if user.update(params[:input])
529
+ user
530
+ else
531
+ raise MyCustomError, 'ups!'
532
+ end
533
+ end
534
+ end
535
+ ```
@@ -23,7 +23,7 @@ This method must be called inside your model body. `grapqhl` is used for making
23
23
 
24
24
  Most commonly you will use `attribute` to make your model methods and attributes visible via graphql endpoint.
25
25
 
26
- ## attribute type
26
+ ## attribute.type
27
27
 
28
28
  Some types can be determined by attribute name, so you can skip this attribute:
29
29
 
@@ -54,7 +54,7 @@ class User
54
54
  end
55
55
  ```
56
56
 
57
- ### attribute property
57
+ ### attribute.property
58
58
 
59
59
  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 `propery` option:
60
60
 
@@ -72,7 +72,7 @@ class User
72
72
  end
73
73
  ```
74
74
 
75
- ### attribute description
75
+ ### attribute.description
76
76
 
77
77
  You can also describe each attribute and make graphql documentation even more readable. To do so, add `description` option:
78
78
 
@@ -86,6 +86,123 @@ class User
86
86
  end
87
87
  ```
88
88
 
89
+ ### attribute.permit
90
+
91
+ To define attributes which are accepted by each model method, you need to call `permit` method, like this:
92
+
93
+ ```ruby
94
+ class User
95
+ include GraphqlRails::Model
96
+
97
+ graphql do |c|
98
+ c.attribute(:avatar_url).permit(size: :int!)
99
+ end
100
+
101
+ def avatar_url(size:)
102
+ # some code here
103
+ end
104
+ end
105
+ ```
106
+
107
+ ### attribute.permit_input
108
+
109
+ Allows to permit single input field. It allows to set additional options for each field.
110
+
111
+ #### attribute.permit_input.type
112
+
113
+ #### attribute.permit_input: required type
114
+
115
+ There are few ways how to mark field as required.
116
+
117
+ 1. Adding exclamation mark at the end of type name:
118
+
119
+ ```ruby
120
+ class User
121
+ include GraphqlRails::Model
122
+
123
+ graphql.attribute(:avatar_url).permit_input(:size, type: :int!)
124
+ end
125
+ ```
126
+
127
+ 2. Adding `required: true` options
128
+
129
+ ```ruby
130
+ class User
131
+ include GraphqlRails::Model
132
+
133
+ graphql.attribute(:avatar_url).permit_input(:size, type: :int, required: true)
134
+ end
135
+ ```
136
+
137
+ #### attribute.permit_input.description
138
+
139
+ You can describe each input by adding `description` keyword argument:
140
+
141
+ ```ruby
142
+ class User
143
+ include GraphqlRails::Model
144
+
145
+ graphql.attribute(:avatar_url).permit_input(:size, description: 'max size of avatar')
146
+ end
147
+ ```
148
+
149
+ #### *subtype*
150
+
151
+ `subtype` allows to specify which named input should be used. Here is an example:
152
+
153
+ ```ruby
154
+ class Image
155
+ graphql.input(:size_options) do |c|
156
+ c.attribute :width
157
+ c.attribute :height
158
+ end
159
+ end
160
+
161
+ class User
162
+ graphql.attribute(:avatar_url).permit_input(:size, type: Image, subtype: :size_options)
163
+ end
164
+ ```
165
+
166
+ ### attribute.paginated
167
+
168
+ 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)
169
+
170
+ ```ruby
171
+ class User
172
+ include GraphqlRails::Model
173
+
174
+ graphql.attribute :items, type: '[Item]', paginatted: true
175
+
176
+ def items
177
+ Item.all
178
+ end
179
+ end
180
+ ```
181
+
182
+ ### attribute.required
183
+
184
+ You can mark attribute as required using `required` method:
185
+
186
+ ```ruby
187
+ class User
188
+ include GraphqlRails::Model
189
+
190
+ graphql.attribute(:item).type('Item').required
191
+ end
192
+ ```
193
+
194
+ ### attribute.optional
195
+
196
+ You can mark attribute as optional using `optional` method:
197
+
198
+ ```ruby
199
+ class User
200
+ include GraphqlRails::Model
201
+
202
+ graphql.attribute(:item).type('Item').optional
203
+ end
204
+ ```
205
+
89
206
  ### "attribute" configuration with chainable methods
90
207
 
91
208
  If your attribute definition is complex, you can define attribute in more eye-friendly chainable way with:
@@ -271,3 +388,34 @@ class User
271
388
  end
272
389
  end
273
390
  ```
391
+
392
+ ## graphql_context
393
+
394
+ It's possible to access graphql_context in your model using method `graphql_context`:
395
+
396
+ ```ruby
397
+ class User
398
+ include GraphqlRails::Model
399
+
400
+ def method_with_context
401
+ graphql_context[:some_data]
402
+ end
403
+ end
404
+ ```
405
+
406
+ Keep in mind that this value will be set only during graphql execution, but in tests this value will be `nil`. To avoid this, you need to set `show_graphql_context` manually like this:
407
+
408
+ ```ruby
409
+ class User
410
+ include GraphqlRails::Model
411
+
412
+ def show_graphql_context
413
+ graphql_context[:data]
414
+ end
415
+ end
416
+
417
+ user = User.new(...)
418
+ user.show_graphql_context #=> NoMethodError: undefined method `[]' for nil:NilClass
419
+ user.graphql_context = { data: 'goes to context' }
420
+ user.show_graphql_context #=> { data: 'goes to context' }
421
+ ```