graphql_rails 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +89 -2
- data/docs/README.md +16 -0
- data/docs/_sidebar.md +2 -0
- data/docs/components/controller.md +113 -0
- data/docs/components/decorator.md +69 -0
- data/docs/components/model.md +75 -2
- data/docs/logging_and_monitoring/logging_and_monitoring.md +35 -0
- data/graphql_rails.gemspec +1 -0
- data/lib/graphql_rails/attributes/attributable.rb +5 -1
- data/lib/graphql_rails/attributes/attribute.rb +31 -4
- data/lib/graphql_rails/attributes/input_attribute.rb +14 -10
- data/lib/graphql_rails/attributes/input_type_parser.rb +84 -0
- data/lib/graphql_rails/attributes/type_name_info.rb +38 -0
- data/lib/graphql_rails/attributes/type_parser.rb +30 -28
- data/lib/graphql_rails/controller/action_configuration.rb +13 -7
- data/lib/graphql_rails/controller/configuration.rb +2 -0
- data/lib/graphql_rails/controller/log_controller_action.rb +66 -0
- data/lib/graphql_rails/controller.rb +26 -9
- data/lib/graphql_rails/decorator/relation_decorator.rb +79 -0
- data/lib/graphql_rails/decorator.rb +41 -0
- data/lib/graphql_rails/integrations/lograge.rb +39 -0
- data/lib/graphql_rails/integrations/sentry.rb +34 -0
- data/lib/graphql_rails/integrations.rb +19 -0
- data/lib/graphql_rails/model/configuration.rb +20 -7
- data/lib/graphql_rails/model/input.rb +1 -1
- data/lib/graphql_rails/model.rb +7 -0
- data/lib/graphql_rails/version.rb +1 -1
- data/lib/graphql_rails.rb +4 -0
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 233cb42d66f27e1bd3b18d5530977285e84358897d9fa4cde2230a811b4712b1
|
4
|
+
data.tar.gz: 773ff5c8223431e2b606c522fbcc5275157d7255b6348bf475a0aa9c76282926
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1034a92ab82fb88dfb94b2eb6502b51e2d97ef4f04e6804abd6cb3a8900117682f6cc717576d5aa16008d3486a8182dc2f503d5d307ad9184177e7968d13467
|
7
|
+
data.tar.gz: d44a9b5d7ad5d3a2663bc40edcef96240e7525e2060ca57d360b6b8640af03ebfd3dc13eae97e11ac77d07d1d283a9480bd567e84aa0f7dc8960e35d6ad329a1
|
data/CHANGELOG.md
CHANGED
@@ -9,6 +9,14 @@ 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
|
+
## [0.8.0] (2019-09-03)
|
13
|
+
|
14
|
+
* Added: permit_input action config with extended list of permitted input options
|
15
|
+
* Added: model decorators
|
16
|
+
* Added: controller action instrumentation [@povilasjurcys](https://github.com/povilasjurcys)
|
17
|
+
* Added: sentry and lograge integrations
|
18
|
+
* Added: required: true flag for permitted attributes, inputs and model attributes
|
19
|
+
|
12
20
|
## 0.7.0 (2019-05-15)
|
13
21
|
|
14
22
|
* Added: input type now accepts `enum` param which allows create enum fields
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,49 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
graphql_rails (0.
|
4
|
+
graphql_rails (0.8.0)
|
5
5
|
activesupport (>= 4)
|
6
6
|
graphql (~> 1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
+
actioncable (5.2.2.1)
|
12
|
+
actionpack (= 5.2.2.1)
|
13
|
+
nio4r (~> 2.0)
|
14
|
+
websocket-driver (>= 0.6.1)
|
15
|
+
actionmailer (5.2.2.1)
|
16
|
+
actionpack (= 5.2.2.1)
|
17
|
+
actionview (= 5.2.2.1)
|
18
|
+
activejob (= 5.2.2.1)
|
19
|
+
mail (~> 2.5, >= 2.5.4)
|
20
|
+
rails-dom-testing (~> 2.0)
|
21
|
+
actionpack (5.2.2.1)
|
22
|
+
actionview (= 5.2.2.1)
|
23
|
+
activesupport (= 5.2.2.1)
|
24
|
+
rack (~> 2.0)
|
25
|
+
rack-test (>= 0.6.3)
|
26
|
+
rails-dom-testing (~> 2.0)
|
27
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
28
|
+
actionview (5.2.2.1)
|
29
|
+
activesupport (= 5.2.2.1)
|
30
|
+
builder (~> 3.1)
|
31
|
+
erubi (~> 1.4)
|
32
|
+
rails-dom-testing (~> 2.0)
|
33
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
34
|
+
activejob (5.2.2.1)
|
35
|
+
activesupport (= 5.2.2.1)
|
36
|
+
globalid (>= 0.3.6)
|
11
37
|
activemodel (5.2.2.1)
|
12
38
|
activesupport (= 5.2.2.1)
|
13
39
|
activerecord (5.2.2.1)
|
14
40
|
activemodel (= 5.2.2.1)
|
15
41
|
activesupport (= 5.2.2.1)
|
16
42
|
arel (>= 9.0)
|
43
|
+
activestorage (5.2.2.1)
|
44
|
+
actionpack (= 5.2.2.1)
|
45
|
+
activerecord (= 5.2.2.1)
|
46
|
+
marcel (~> 0.3.1)
|
17
47
|
activesupport (5.2.2.1)
|
18
48
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
49
|
i18n (>= 0.7, < 2)
|
@@ -22,6 +52,7 @@ GEM
|
|
22
52
|
arel (9.0.0)
|
23
53
|
ast (2.4.0)
|
24
54
|
bson (4.4.2)
|
55
|
+
builder (3.2.3)
|
25
56
|
byebug (11.0.1)
|
26
57
|
codecov (0.1.14)
|
27
58
|
json
|
@@ -29,20 +60,37 @@ GEM
|
|
29
60
|
url
|
30
61
|
coderay (1.1.2)
|
31
62
|
concurrent-ruby (1.1.5)
|
63
|
+
crass (1.0.4)
|
32
64
|
diff-lcs (1.3)
|
33
65
|
docile (1.3.1)
|
34
|
-
|
66
|
+
erubi (1.8.0)
|
67
|
+
globalid (0.4.2)
|
68
|
+
activesupport (>= 4.2.0)
|
69
|
+
graphql (1.9.7)
|
35
70
|
i18n (1.6.0)
|
36
71
|
concurrent-ruby (~> 1.0)
|
37
72
|
jaro_winkler (1.5.2)
|
38
73
|
json (2.2.0)
|
74
|
+
loofah (2.2.3)
|
75
|
+
crass (~> 1.0.2)
|
76
|
+
nokogiri (>= 1.5.9)
|
77
|
+
mail (2.7.1)
|
78
|
+
mini_mime (>= 0.1.1)
|
79
|
+
marcel (0.3.3)
|
80
|
+
mimemagic (~> 0.3.2)
|
39
81
|
method_source (0.9.2)
|
82
|
+
mimemagic (0.3.3)
|
83
|
+
mini_mime (1.0.1)
|
84
|
+
mini_portile2 (2.4.0)
|
40
85
|
minitest (5.11.3)
|
41
86
|
mongo (2.8.0)
|
42
87
|
bson (>= 4.4.2, < 5.0.0)
|
43
88
|
mongoid (7.0.2)
|
44
89
|
activemodel (>= 5.1, < 6.0.0)
|
45
90
|
mongo (>= 2.5.1, < 3.0.0)
|
91
|
+
nio4r (2.3.1)
|
92
|
+
nokogiri (1.10.4)
|
93
|
+
mini_portile2 (~> 2.4.0)
|
46
94
|
parallel (1.16.0)
|
47
95
|
parser (2.6.2.0)
|
48
96
|
ast (~> 2.4.0)
|
@@ -53,6 +101,33 @@ GEM
|
|
53
101
|
byebug (~> 11.0)
|
54
102
|
pry (~> 0.10)
|
55
103
|
psych (3.1.0)
|
104
|
+
rack (2.0.7)
|
105
|
+
rack-test (1.1.0)
|
106
|
+
rack (>= 1.0, < 3)
|
107
|
+
rails (5.2.2.1)
|
108
|
+
actioncable (= 5.2.2.1)
|
109
|
+
actionmailer (= 5.2.2.1)
|
110
|
+
actionpack (= 5.2.2.1)
|
111
|
+
actionview (= 5.2.2.1)
|
112
|
+
activejob (= 5.2.2.1)
|
113
|
+
activemodel (= 5.2.2.1)
|
114
|
+
activerecord (= 5.2.2.1)
|
115
|
+
activestorage (= 5.2.2.1)
|
116
|
+
activesupport (= 5.2.2.1)
|
117
|
+
bundler (>= 1.3.0)
|
118
|
+
railties (= 5.2.2.1)
|
119
|
+
sprockets-rails (>= 2.0.0)
|
120
|
+
rails-dom-testing (2.0.3)
|
121
|
+
activesupport (>= 4.2.0)
|
122
|
+
nokogiri (>= 1.6)
|
123
|
+
rails-html-sanitizer (1.0.4)
|
124
|
+
loofah (~> 2.2, >= 2.2.2)
|
125
|
+
railties (5.2.2.1)
|
126
|
+
actionpack (= 5.2.2.1)
|
127
|
+
activesupport (= 5.2.2.1)
|
128
|
+
method_source
|
129
|
+
rake (>= 0.8.7)
|
130
|
+
thor (>= 0.19.0, < 2.0)
|
56
131
|
rainbow (3.0.0)
|
57
132
|
rake (10.5.0)
|
58
133
|
rspec (3.8.0)
|
@@ -84,11 +159,22 @@ GEM
|
|
84
159
|
json (>= 1.8, < 3)
|
85
160
|
simplecov-html (~> 0.10.0)
|
86
161
|
simplecov-html (0.10.2)
|
162
|
+
sprockets (3.7.2)
|
163
|
+
concurrent-ruby (~> 1.0)
|
164
|
+
rack (> 1, < 3)
|
165
|
+
sprockets-rails (3.2.1)
|
166
|
+
actionpack (>= 4.0)
|
167
|
+
activesupport (>= 4.0)
|
168
|
+
sprockets (>= 3.0.0)
|
169
|
+
thor (0.20.3)
|
87
170
|
thread_safe (0.3.6)
|
88
171
|
tzinfo (1.2.5)
|
89
172
|
thread_safe (~> 0.1)
|
90
173
|
unicode-display_width (1.5.0)
|
91
174
|
url (0.3.2)
|
175
|
+
websocket-driver (0.7.1)
|
176
|
+
websocket-extensions (>= 0.1.0)
|
177
|
+
websocket-extensions (0.1.4)
|
92
178
|
|
93
179
|
PLATFORMS
|
94
180
|
ruby
|
@@ -100,6 +186,7 @@ DEPENDENCIES
|
|
100
186
|
graphql_rails!
|
101
187
|
mongoid
|
102
188
|
pry-byebug
|
189
|
+
rails (~> 5)
|
103
190
|
rake (~> 10.0)
|
104
191
|
rspec (~> 3.0)
|
105
192
|
rubocop
|
data/docs/README.md
CHANGED
@@ -171,6 +171,22 @@ RSpec.describe MyGraphqlController, type: :graphql_controller do
|
|
171
171
|
end
|
172
172
|
```
|
173
173
|
|
174
|
+
### Integrating GraphqlRails with other tools
|
175
|
+
|
176
|
+
In order to make GraphqlRails work with tools such as lograge or sentry, you need to enable them. In Ruby on Rails, you can add initializer:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
# config/initializers/graphql_rails.rb
|
180
|
+
GraphqlRails::Integrations.enable(:lograge, :sentry)
|
181
|
+
```
|
182
|
+
|
183
|
+
At the moment, GraphqlRails supports following integrations:
|
184
|
+
|
185
|
+
* lograge
|
186
|
+
* sentry
|
187
|
+
|
188
|
+
If you need to build something custom, check [logging_and_monitoring documentation](logging_and_monitoring/logging_and_monitoring.md) for more details.
|
189
|
+
|
174
190
|
## Detailed documentation
|
175
191
|
|
176
192
|
Check https://samesystem.github.io/graphql_rails for more details
|
data/docs/_sidebar.md
CHANGED
@@ -66,6 +66,95 @@ class UsersController < GraphqlRails::Controller
|
|
66
66
|
end
|
67
67
|
```
|
68
68
|
|
69
|
+
### *permit_input*
|
70
|
+
|
71
|
+
Allows to permit single input field. It allows to set additional options for each field.
|
72
|
+
|
73
|
+
#### *type*
|
74
|
+
|
75
|
+
Specifies input type:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class OrderController < GraphqlRails::Controller
|
79
|
+
action(:create)
|
80
|
+
.permit_input(:price, type: :integer!)
|
81
|
+
# Same as `.permit(amount: :integer!)`
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
#### required type
|
86
|
+
|
87
|
+
There are few ways how to mark field as required.
|
88
|
+
|
89
|
+
1. Adding exclamation mark at the end of type name:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class UsersController < GraphqlRails::Controller
|
93
|
+
action(:create).permit_input(:some_field, type: :int!)
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
2. Adding exclamation mark at the end of name
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class UsersController < GraphqlRails::Controller
|
101
|
+
action(:create).permit_input(:some_field!)
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
3. Adding `required: true` options
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
class UsersController < GraphqlRails::Controller
|
109
|
+
action(:create).permit_input(:some_field, type: :bool, required: true)
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
#### *description*
|
114
|
+
|
115
|
+
You can describe each input by adding `description` keyword argument:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
class OrderController < GraphqlRails::Controller
|
119
|
+
action(:create)
|
120
|
+
.permit_input(:price, type: :integer!, description: 'Price in Euro cents')
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
#### *subtype*
|
125
|
+
|
126
|
+
`subtype` allows to specify which named input should be used. Here is an example:
|
127
|
+
|
128
|
+
Let's say you have user with two input types
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
class User
|
132
|
+
graphql.input do |c|
|
133
|
+
c.attribute :full_name
|
134
|
+
c.attribute :email
|
135
|
+
end
|
136
|
+
|
137
|
+
graphql.input(:change_password) do |c|
|
138
|
+
c.attribute :password
|
139
|
+
c.attribute :password_confirmation
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
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
|
+
|
146
|
+
```ruby
|
147
|
+
class OrderController < GraphqlRails::Controller
|
148
|
+
# this is the input with email and full_name:
|
149
|
+
action(:create)
|
150
|
+
.permit_input(:input, type: 'User!')
|
151
|
+
|
152
|
+
# this is the input with password and password_confirmation:
|
153
|
+
action(:update_password)
|
154
|
+
.permit_input(:input, type: 'User!', subtype: :change_password)
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
69
158
|
### *can_return_nil*
|
70
159
|
|
71
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:
|
@@ -96,6 +185,8 @@ class UsersController < GraphqlRails::Controller
|
|
96
185
|
end
|
97
186
|
```
|
98
187
|
|
188
|
+
Also check ['decorating controller responses']('components/decorator') for more details about working with active record and decorators.
|
189
|
+
|
99
190
|
#### *max_page_size*
|
100
191
|
|
101
192
|
Allows to specify max items count per request
|
@@ -153,6 +244,24 @@ class UsersController < GraphqlRails::Controller
|
|
153
244
|
end
|
154
245
|
```
|
155
246
|
|
247
|
+
### configuring action with a block
|
248
|
+
|
249
|
+
If you do not like chainable methods, you can use "block" style action configuration:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
class UsersController < GraphqlRails::Controller
|
253
|
+
action(:index) do |action|
|
254
|
+
action.paginated
|
255
|
+
action.permit(limit: :int!)
|
256
|
+
action.returns '[User!]!'
|
257
|
+
end
|
258
|
+
|
259
|
+
def create
|
260
|
+
User.create(params)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
156
265
|
## *before_action*
|
157
266
|
|
158
267
|
You can add `before_action` to run some filters before calling your controller action. Here is an example:
|
@@ -263,3 +372,7 @@ class UsersController < GraphqlRails::Controller
|
|
263
372
|
end
|
264
373
|
end
|
265
374
|
```
|
375
|
+
|
376
|
+
## decorating objects
|
377
|
+
|
378
|
+
See ['Decorating controller responses']('components/decorator') for various options how you can decorate paginated responses
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Decorator
|
2
|
+
|
3
|
+
Decorator is mostly used whit paginated results, because it can wrap ActiveRecord relations in a "pagination-friendly" way
|
4
|
+
|
5
|
+
## Passing extra options to decorator
|
6
|
+
|
7
|
+
Let's say you want to decorate `comment`, but you also need `user` in order to print some details. Here is decorator for such comment:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class CommentDecorator < SimpleDelegator
|
11
|
+
include GraphqlRails::Decorator
|
12
|
+
|
13
|
+
def initialize(comment, current_user)
|
14
|
+
@comment = comment
|
15
|
+
@current_user = user
|
16
|
+
end
|
17
|
+
|
18
|
+
def author_name
|
19
|
+
if @current_user.can_see_author_name?(@comment)
|
20
|
+
@comment.author_name
|
21
|
+
else
|
22
|
+
'secret author'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
In order to decorate object with exra arguments, simply pass them to `.decorate` method. Like this:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
CommentDecorator.decorate(comment, current_user)
|
32
|
+
```
|
33
|
+
|
34
|
+
The only requirement is that first object should be the object which you are decorating. Other arguments are treated as extra data and they are not modified
|
35
|
+
|
36
|
+
## Decorating controller responses
|
37
|
+
|
38
|
+
If you want to decorate your controller response you can use `GraphqlRails::Decorator` module. It can decorate simple objects and ActiveRecord::Relation objects. This is very handy when you need to decorated paginated actions:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class User < ActiveRecord::Base
|
42
|
+
# it's not GraphqlRails::Model !
|
43
|
+
end
|
44
|
+
|
45
|
+
class UserDecorator < SimpleDelegator
|
46
|
+
include GraphqlRails::Model
|
47
|
+
include GraphqlRails::Decorator
|
48
|
+
|
49
|
+
graphql_rails do
|
50
|
+
# some setup, attributes, etc...
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(user); end
|
54
|
+
end
|
55
|
+
|
56
|
+
class UsersController < GraphqlRails::Controller
|
57
|
+
action(:index).paginated.returns('[UserDecorator!]!')
|
58
|
+
|
59
|
+
def index
|
60
|
+
users = User.where(active: true)
|
61
|
+
UserDecorator.decorate(users)
|
62
|
+
end
|
63
|
+
|
64
|
+
def create
|
65
|
+
user = User.create(params)
|
66
|
+
UserDecorator.decorate(user)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
data/docs/components/model.md
CHANGED
@@ -58,7 +58,7 @@ end
|
|
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
|
|
61
|
-
```
|
61
|
+
```ruby
|
62
62
|
class User
|
63
63
|
include GraphqlRails::Model
|
64
64
|
|
@@ -76,7 +76,7 @@ end
|
|
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
|
|
79
|
-
```
|
79
|
+
```ruby
|
80
80
|
class User
|
81
81
|
include GraphqlRails::Model
|
82
82
|
|
@@ -86,6 +86,39 @@ class User
|
|
86
86
|
end
|
87
87
|
```
|
88
88
|
|
89
|
+
### "attribute" configuration with chainable methods
|
90
|
+
|
91
|
+
If your attribute definition is complex, you can define attribute in more eye-friendly chainable way with:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
class User
|
95
|
+
include GraphqlRails::Model
|
96
|
+
|
97
|
+
graphql do |c|
|
98
|
+
c.attribute(:shop_id)
|
99
|
+
.type('ID!')
|
100
|
+
.description('references to shop')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
### "attribute" configuration with a block
|
106
|
+
|
107
|
+
You can also use block in order to specify attribute configuration:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
class User
|
111
|
+
include GraphqlRails::Model
|
112
|
+
|
113
|
+
graphql do |c|
|
114
|
+
c.attribute(:shop_id) do |attr|
|
115
|
+
attr.type 'ID!'
|
116
|
+
attr.description 'references to shop'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
89
122
|
## name
|
90
123
|
|
91
124
|
By default grapqhl type name will be same as model name, but you can change it via `name` method
|
@@ -171,6 +204,34 @@ class User
|
|
171
204
|
end
|
172
205
|
```
|
173
206
|
|
207
|
+
#### required type
|
208
|
+
|
209
|
+
There are few ways how to mark field as required.
|
210
|
+
|
211
|
+
1. Adding exclamation mark at the end of type name:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
class User
|
215
|
+
include GraphqlRails::Model
|
216
|
+
|
217
|
+
graphql.input do |c|
|
218
|
+
c.attribute :friends_count, type: :integer!
|
219
|
+
end
|
220
|
+
end
|
221
|
+
```
|
222
|
+
|
223
|
+
2. Adding `required: true` value
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
class User
|
227
|
+
include GraphqlRails::Model
|
228
|
+
|
229
|
+
graphql.input do |c|
|
230
|
+
c.attribute :friends_count, type: :integer, required: true
|
231
|
+
end
|
232
|
+
end
|
233
|
+
```
|
234
|
+
|
174
235
|
#### input enum type
|
175
236
|
|
176
237
|
You can specify your input attribute as enum:
|
@@ -185,6 +246,18 @@ class User
|
|
185
246
|
end
|
186
247
|
```
|
187
248
|
|
249
|
+
By default enum type is not required. To make it required add `required: true`:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
class User
|
253
|
+
include GraphqlRails::Model
|
254
|
+
|
255
|
+
graphql.input do |c|
|
256
|
+
c.attribute :favorite_fruit, required: true, enum: %i[apple orange]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
```
|
260
|
+
|
188
261
|
#### input attribute description
|
189
262
|
|
190
263
|
To improve graphql endpoint documentation, you can add description for each input attribute:
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Logging and monitoring
|
2
|
+
|
3
|
+
GraphqlRails behaves similar as Ruby on Rails. This allows to use existing monitoring and logging tools. Here we will add some examples on how to setup various tools for GraphqlRails
|
4
|
+
|
5
|
+
## Integrating GraphqlRails with other tools
|
6
|
+
|
7
|
+
In order to make GraphqlRails work with tools such as lograge or sentry, you need to enable them. In Ruby on Rails, you can add initializer:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# config/initializers/graphql_rails.rb
|
11
|
+
GraphqlRails::Integrations.enable(:lograge, :sentry)
|
12
|
+
```
|
13
|
+
|
14
|
+
At the moment, GraphqlRails supports following integrations:
|
15
|
+
|
16
|
+
* lograge
|
17
|
+
* sentry
|
18
|
+
|
19
|
+
## Instrumentation
|
20
|
+
|
21
|
+
GraphqlRails uses same instrumentation tool (`ActiveSupport::Notifications`) as Ruby on Rails. At the moment there are two notification types:
|
22
|
+
|
23
|
+
* `process_action.graphql_action_controller`
|
24
|
+
* `start_action.graphql_action_controller`
|
25
|
+
|
26
|
+
you can watch those actions using with `ActiveSupport::Notifications#subscribe` like this:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
key = 'process_action.graphql_action_controller'
|
30
|
+
ActiveSupport::Notifications.subscribe(key) do |*_, payload|
|
31
|
+
YourLogger.do_something(payload)
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
or you can do the same with `ActiveSupport::LogSubscriber`. More details about it [here](https://api.rubyonrails.org/classes/ActiveSupport/LogSubscriber.html).
|
data/graphql_rails.gemspec
CHANGED
@@ -21,7 +21,11 @@ module GraphqlRails
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def required?
|
24
|
-
|
24
|
+
if @required.nil?
|
25
|
+
attribute_name_parser.required? || !initial_type.to_s[/!$/].nil?
|
26
|
+
else
|
27
|
+
@required
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def graphql_model
|
@@ -9,17 +9,44 @@ module GraphqlRails
|
|
9
9
|
class Attribute
|
10
10
|
include Attributable
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
def initialize(name, type = nil, description: nil, property: name)
|
12
|
+
def initialize(name, type = nil, description: nil, property: name, required: nil)
|
15
13
|
@initial_type = type
|
16
14
|
@initial_name = name
|
17
15
|
@description = description
|
18
16
|
@property = property.to_s
|
17
|
+
@required = required
|
18
|
+
end
|
19
|
+
|
20
|
+
def type(new_type = nil)
|
21
|
+
return @initial_type if new_type.nil?
|
22
|
+
|
23
|
+
@initial_type = new_type
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def description(new_description = nil)
|
28
|
+
return @description if new_description.nil?
|
29
|
+
|
30
|
+
@description = new_description
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def property(new_property = nil)
|
35
|
+
return @property if new_property.nil?
|
36
|
+
|
37
|
+
@property = new_property.to_s
|
38
|
+
self
|
19
39
|
end
|
20
40
|
|
21
41
|
def field_args
|
22
|
-
[
|
42
|
+
[
|
43
|
+
field_name,
|
44
|
+
graphql_field_type,
|
45
|
+
{
|
46
|
+
property: property.to_sym,
|
47
|
+
description: description
|
48
|
+
}
|
49
|
+
]
|
23
50
|
end
|
24
51
|
|
25
52
|
protected
|
@@ -4,44 +4,48 @@ module GraphqlRails
|
|
4
4
|
module Attributes
|
5
5
|
# contains info about single graphql input attribute
|
6
6
|
class InputAttribute
|
7
|
+
require_relative './input_type_parser'
|
7
8
|
include Attributable
|
8
9
|
|
9
10
|
attr_reader :description
|
10
11
|
|
11
|
-
|
12
|
+
# rubocop:disable Metrics/ParameterLists
|
13
|
+
def initialize(name, type = nil, description: nil, subtype: nil, required: nil, options: {})
|
12
14
|
@initial_name = name
|
13
15
|
@initial_type = type
|
14
16
|
@description = description
|
15
17
|
@options = options
|
18
|
+
@subtype = subtype
|
19
|
+
@required = required
|
16
20
|
end
|
21
|
+
# rubocop:enable Metrics/ParameterLists
|
17
22
|
|
18
23
|
def function_argument_args
|
19
24
|
[field_name, graphql_input_type, { description: description }]
|
20
25
|
end
|
21
26
|
|
22
27
|
def input_argument_args
|
23
|
-
type = raw_input_type ||
|
28
|
+
type = raw_input_type || input_type_parser.nullable_type || nullable_type
|
29
|
+
|
24
30
|
[field_name, type, { required: required?, description: description }]
|
25
31
|
end
|
26
32
|
|
27
33
|
def graphql_input_type
|
28
|
-
raw_input_type ||
|
34
|
+
raw_input_type || input_type_parser.graphql_type || graphql_field_type
|
29
35
|
end
|
30
36
|
|
31
37
|
private
|
32
38
|
|
33
|
-
attr_reader :initial_name, :initial_type, :options
|
39
|
+
attr_reader :initial_name, :initial_type, :options, :subtype
|
40
|
+
|
41
|
+
def input_type_parser
|
42
|
+
@input_type_parser ||= InputTypeParser.new(initial_type, subtype: subtype)
|
43
|
+
end
|
34
44
|
|
35
45
|
def raw_input_type
|
36
46
|
return initial_type if initial_type.is_a?(GraphQL::InputObjectType)
|
37
47
|
return initial_type.graphql_input_type if initial_type.is_a?(Model::Input)
|
38
48
|
end
|
39
|
-
|
40
|
-
def model_input_type
|
41
|
-
return unless graphql_model
|
42
|
-
|
43
|
-
graphql_model.graphql.input.graphql_input_type
|
44
|
-
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|