graphql_rails 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +3 -2
  3. data/CHANGELOG.md +8 -0
  4. data/Gemfile.lock +16 -16
  5. data/docs/README.md +1 -1
  6. data/docs/components/model.md +38 -5
  7. data/docs/components/routes.md +20 -10
  8. data/graphql_rails.gemspec +1 -1
  9. data/lib/generators/graphql_rails/templates/graphql_controller.erb +1 -1
  10. data/lib/graphql_rails/attributes/attribute.rb +9 -1
  11. data/lib/graphql_rails/attributes/attribute_configurable.rb +9 -0
  12. data/lib/graphql_rails/attributes/attribute_name_parser.rb +4 -4
  13. data/lib/graphql_rails/attributes/input_attribute.rb +2 -1
  14. data/lib/graphql_rails/attributes/type_parseable.rb +4 -5
  15. data/lib/graphql_rails/controller/action_configuration.rb +1 -1
  16. data/lib/graphql_rails/controller/configuration.rb +1 -1
  17. data/lib/graphql_rails/controller/request/format_errors.rb +1 -1
  18. data/lib/graphql_rails/controller/request.rb +3 -2
  19. data/lib/graphql_rails/decorator/relation_decorator.rb +2 -2
  20. data/lib/graphql_rails/errors/custom_execution_error.rb +1 -1
  21. data/lib/graphql_rails/errors/execution_error.rb +1 -1
  22. data/lib/graphql_rails/model/find_or_build_graphql_input_type.rb +28 -0
  23. data/lib/graphql_rails/model/find_or_build_graphql_type.rb +14 -5
  24. data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +4 -3
  25. data/lib/graphql_rails/model/input.rb +3 -3
  26. data/lib/graphql_rails/router/event_route.rb +52 -0
  27. data/lib/graphql_rails/router/mutation_route.rb +1 -1
  28. data/lib/graphql_rails/router/query_route.rb +1 -1
  29. data/lib/graphql_rails/router/resource_routes_builder.rb +0 -8
  30. data/lib/graphql_rails/router/route.rb +1 -1
  31. data/lib/graphql_rails/router/schema_builder.rb +15 -10
  32. data/lib/graphql_rails/router.rb +8 -8
  33. data/lib/graphql_rails/rspec_controller_helpers.rb +3 -1
  34. data/lib/graphql_rails/types/hidable_by_group.rb +23 -3
  35. data/lib/graphql_rails/types/input_object_type.rb +16 -0
  36. data/lib/graphql_rails/version.rb +1 -1
  37. metadata +9 -14
  38. data/lib/graphql_rails/model/build_graphql_input_type.rb +0 -43
  39. 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: 9f06459a3c8c16e40dffd181d7c08128558e2bdca598845b9e94f51852681e61
4
- data.tar.gz: 1a4ddc9e11a4c5ef22240f7e36b3070bcf89b712c561cad12e41ede1dc18fbc3
3
+ metadata.gz: 9ef0115ce3d9107ee48ec4e7a725baff242ce81133be4a955d0a81619b106192
4
+ data.tar.gz: dcb027f23eb5f6cd71b3144e2794822ee899796a5e40f7b240ea3cd59ef586b9
5
5
  SHA512:
6
- metadata.gz: 23e0d160c19e3c56c00a474cb77eff10c6a86c3ce1c63f3cdb87f4c374f3c10da79b5f2529a14a026f81e6f3b2c32e9b2fecd671bd7b38066e07d020c65fa93a
7
- data.tar.gz: a0ade6d1ce611baf97ab0a631770273c98953b04eb3991e3234c12a12f21e893962b62a1785ba5da48de7193c366129d29732c7121fbe6c4404d5e1f05cedda2
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.7', '3.0', '3.1']
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/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
+ ## [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
+
12
20
  ## [2.3.0](2022-11-25)
13
21
 
14
22
  * Added support for Ruby 3.1.2, keyword arguments for decorators support included
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_rails (2.3.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.17)
85
- i18n (1.8.11)
84
+ graphql (2.0.21)
85
+ i18n (1.12.0)
86
86
  concurrent-ruby (~> 1.0)
87
- loofah (2.18.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.8.0)
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,7 +101,7 @@ 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.9)
104
+ nokogiri (1.14.3)
105
105
  mini_portile2 (~> 2.8.0)
106
106
  racc (~> 1.4)
107
107
  parallel (1.21.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.1)
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.3)
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
@@ -92,7 +92,7 @@ class Graphql::UsersController < GraphqlApplicationController
92
92
  end
93
93
  ```
94
94
 
95
- See [Controller docs](components/controlle.md) for more info.
95
+ See [Controller docs](components/controller.md) for more info.
96
96
 
97
97
  ## Testing your GraphqlRails::Controller in RSpec
98
98
 
@@ -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
@@ -185,6 +185,24 @@ class User
185
185
  end
186
186
  ```
187
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
+
188
206
  ### attribute.options
189
207
 
190
208
  Allows passing options to attribute definition. Available options:
@@ -200,6 +218,21 @@ class User
200
218
  c.attribute :first_name, options: { attribute_name_format: :original } # will be accessible as first_name from client side
201
219
  end
202
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
+ ```
203
236
 
204
237
  ### attribute.permit
205
238
 
@@ -303,7 +336,7 @@ You can mark collection method as `paginated`. In this case method will return r
303
336
  class User
304
337
  include GraphqlRails::Model
305
338
 
306
- graphql.attribute :items, type: '[Item]', paginatted: true
339
+ graphql.attribute :items, type: '[Item]', paginated: true
307
340
 
308
341
  def items
309
342
  Item.all
@@ -388,7 +421,7 @@ end
388
421
 
389
422
  ## name
390
423
 
391
- 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
392
425
 
393
426
  ```ruby
394
427
  class User
@@ -402,7 +435,7 @@ end
402
435
 
403
436
  ## description
404
437
 
405
- To improve grapqhl documentation, you can description for your graphql type:
438
+ To improve graphql documentation, you can description for your graphql type:
406
439
 
407
440
  ```ruby
408
441
  class User
@@ -419,7 +452,7 @@ end
419
452
  Sometimes it's handy to get raw graphql type. To do so you can call:
420
453
 
421
454
  ```ruby
422
- YourModel.graphql.grapqhl_type
455
+ YourModel.graphql.graphql_type
423
456
  ```
424
457
 
425
458
  ## input
@@ -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
+
78
+ In case you want to have non-CRUD controller with custom actions you can define your own `query`/`mutation` actions like this:
79
+
80
+ ```ruby
81
+ MyGraphqlSchema = GraphqlRails::Router.draw do
82
+ mutation :logIn, to: 'sessions#login'
83
+ query :me, to: 'users#current_user'
84
+ end
77
85
 
78
- in case you want to have non-CRUD controller with custom actions you can define your own `query`/`mutation`/`subscription` actions like this:
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.
79
87
 
80
88
  ```ruby
81
89
  MyGraphqlSchema = GraphqlRails::Router.draw do
82
90
  mutation :logIn, to: 'sessions#login'
83
91
  query :me, to: 'users#current_user'
84
- subscribtion :new_message, to: 'messages#created'
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
 
@@ -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
  {}
@@ -42,7 +42,9 @@ module GraphqlRails
42
42
  null: optional?,
43
43
  camelize: camelize?,
44
44
  groups: groups,
45
- **deprecation_reason_params
45
+ hidden_in_groups: hidden_in_groups,
46
+ **deprecation_reason_params,
47
+ **extras_options
46
48
  }
47
49
  end
48
50
 
@@ -52,6 +54,12 @@ module GraphqlRails
52
54
 
53
55
  private
54
56
 
57
+ def extras_options
58
+ return {} if extras.empty?
59
+
60
+ { extras: extras }
61
+ end
62
+
55
63
  def camelize?
56
64
  options[:input_format] != :original && options[:attribute_name_format] != :original
57
65
  end
@@ -17,6 +17,7 @@ module GraphqlRails
17
17
 
18
18
  chainable_option :description
19
19
  chainable_option :options, default: {}
20
+ chainable_option :extras, default: []
20
21
  chainable_option :type
21
22
  end
22
23
 
@@ -32,6 +33,14 @@ module GraphqlRails
32
33
  groups(*args)
33
34
  end
34
35
 
36
+ def hidden_in_groups(new_groups = ChainableOptions::NOT_SET)
37
+ @hidden_in_groups ||= []
38
+ return @hidden_in_groups if new_groups == ChainableOptions::NOT_SET
39
+
40
+ @hidden_in_groups = Array(new_groups).map(&:to_s)
41
+ self
42
+ end
43
+
35
44
  def required(new_value = true) # rubocop:disable Style/OptionalBooleanParameter
36
45
  @required = new_value
37
46
  self
@@ -3,7 +3,7 @@
3
3
  module GraphqlRails
4
4
  module Attributes
5
5
  # Parses attribute name and can generates graphql scalar type,
6
- # grapqhl name and etc. based on that
6
+ # graphql name and etc. based on that
7
7
  class AttributeNameParser
8
8
  def initialize(original_name, options: {})
9
9
  @original_name = original_name.to_s
@@ -13,9 +13,9 @@ module GraphqlRails
13
13
  def field_name
14
14
  @field_name ||= \
15
15
  if original_format?
16
- preprocesed_name
16
+ preprocessed_name
17
17
  else
18
- preprocesed_name.camelize(:lower)
18
+ preprocessed_name.camelize(:lower)
19
19
  end
20
20
  end
21
21
 
@@ -47,7 +47,7 @@ module GraphqlRails
47
47
  options[:input_format] == :original || options[:attribute_name_format] == :original
48
48
  end
49
49
 
50
- def preprocesed_name
50
+ def preprocessed_name
51
51
  if name.end_with?('?')
52
52
  "is_#{name.remove(/\?\Z/)}"
53
53
  else
@@ -31,6 +31,7 @@ module GraphqlRails
31
31
  description: description,
32
32
  camelize: false,
33
33
  groups: groups,
34
+ hidden_in_groups: hidden_in_groups,
34
35
  **default_value_option,
35
36
  **deprecation_reason_params
36
37
  }
@@ -79,7 +80,7 @@ module GraphqlRails
79
80
  end
80
81
 
81
82
  def raw_input_type
82
- return type if type.is_a?(GraphQL::InputObjectType)
83
+ return type if type.is_a?(GraphQL::Schema::InputObject)
83
84
  return type.graphql_input_type if type.is_a?(Model::Input)
84
85
  end
85
86
  end
@@ -42,14 +42,13 @@ module GraphqlRails
42
42
  WRAPPER_TYPES = [
43
43
  GraphQL::Schema::List,
44
44
  GraphQL::Schema::NonNull,
45
- GraphQL::NonNullType,
46
- GraphQL::ListType
45
+ GraphQL::Language::Nodes::NonNullType,
46
+ GraphQL::Language::Nodes::ListType
47
47
  ].freeze
48
48
 
49
49
  GRAPHQL_BASE_TYPES = [
50
- GraphQL::BaseType,
51
- GraphQL::ObjectType,
52
- GraphQL::InputObjectType
50
+ GraphQL::Schema::Object,
51
+ GraphQL::Schema::InputObject
53
52
  ].freeze
54
53
 
55
54
  RAW_GRAPHQL_TYPES = (WRAPPER_TYPES + GRAPHQL_BASE_TYPES).freeze
@@ -7,7 +7,7 @@ require 'graphql_rails/errors/error'
7
7
 
8
8
  module GraphqlRails
9
9
  class Controller
10
- # stores all graphql_rails contoller specific config
10
+ # stores all graphql_rails controller specific config
11
11
  class ActionConfiguration
12
12
  class MissingConfigurationError < GraphqlRails::Error; end
13
13
  class DeprecatedDefaultModelError < GraphqlRails::Error; end
@@ -7,7 +7,7 @@ require 'graphql_rails/errors/error'
7
7
 
8
8
  module GraphqlRails
9
9
  class Controller
10
- # stores all graphql_rails contoller specific config
10
+ # stores all graphql_rails controller specific config
11
11
  class Configuration
12
12
  class InvalidActionConfiguration < GraphqlRails::Error; end
13
13
 
@@ -8,7 +8,7 @@ require 'graphql_rails/errors/custom_execution_error'
8
8
  module GraphqlRails
9
9
  class Controller
10
10
  class Request
11
- # Converts user provided free-form errors in to meaningfull graphql error classes
11
+ # Converts user provided free-form errors in to meaningful graphql error classes
12
12
  class FormatErrors
13
13
  include Service
14
14
 
@@ -7,11 +7,12 @@ module GraphqlRails
7
7
  require 'graphql_rails/controller/request/format_errors'
8
8
 
9
9
  attr_accessor :object_to_return
10
- attr_reader :errors, :context
10
+ attr_reader :errors, :context, :lookahead
11
11
 
12
12
  def initialize(graphql_object, inputs, context)
13
13
  @graphql_object = graphql_object
14
- @inputs = inputs
14
+ @inputs = inputs.except(:lookahead)
15
+ @lookahead = inputs[:lookahead]
15
16
  @context = context
16
17
  end
17
18
 
@@ -2,10 +2,10 @@
2
2
 
3
3
  module GraphqlRails
4
4
  module Decorator
5
- # wrapps active record relation and returns decorated object instead
5
+ # wraps active record relation and returns decorated object instead
6
6
  class RelationDecorator
7
7
  delegate :map, :each, to: :to_a
8
- delegate :limit_value, :offset_value, :count, :size, :empty?, to: :relation
8
+ delegate :limit_value, :offset_value, :count, :size, :empty?, :loaded?, to: :relation
9
9
 
10
10
  def self.decorates?(object)
11
11
  (defined?(ActiveRecord) && object.is_a?(ActiveRecord::Relation)) ||
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- # base class which is returned in case something bad happens. Contains all error rendering tructure
4
+ # base class which is returned in case something bad happens. Contains all error rendering structure
5
5
  class CustomExecutionError < ExecutionError
6
6
  attr_reader :extra_graphql_data
7
7
 
@@ -3,7 +3,7 @@
3
3
  module GraphqlRails
4
4
  require 'graphql'
5
5
 
6
- # base class which is returned in case something bad happens. Contains all error rendering tructure
6
+ # base class which is returned in case something bad happens. Contains all error rendering structure
7
7
  class ExecutionError < GraphQL::ExecutionError
8
8
  def to_h
9
9
  super.merge(extra_graphql_data)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/input_object_type'
4
+ require 'graphql_rails/concerns/service'
5
+ require 'graphql_rails/model/find_or_build_graphql_type'
6
+
7
+ module GraphqlRails
8
+ module Model
9
+ # stores information about model specific config, like attributes and types
10
+ class FindOrBuildGraphqlInputType < FindOrBuildGraphqlType
11
+ include ::GraphqlRails::Service
12
+
13
+ private
14
+
15
+ def parent_class
16
+ GraphqlRails::Types::InputObjectType
17
+ end
18
+
19
+ def add_attributes_batch(attributes)
20
+ klass.class_eval do
21
+ attributes.each do |attribute|
22
+ argument(*attribute.input_argument_args, **attribute.input_argument_options)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -19,7 +19,7 @@ module GraphqlRails
19
19
  end
20
20
 
21
21
  def call
22
- klass.tap { add_fields_to_graphql_type if new_class? || force_define_attributes }
22
+ klass.tap { add_attributes if new_class? || force_define_attributes }
23
23
  end
24
24
 
25
25
  private
@@ -28,20 +28,29 @@ module GraphqlRails
28
28
 
29
29
  delegate :klass, :new_class?, to: :type_class_finder
30
30
 
31
+ def parent_class
32
+ GraphqlRails::Types::ObjectType
33
+ end
34
+
35
+ def add_attributes_batch(attributes)
36
+ AddFieldsToGraphqlType.call(klass: klass, attributes: attributes)
37
+ end
38
+
31
39
  def type_class_finder
32
40
  @type_class_finder ||= FindOrBuildGraphqlTypeClass.new(
33
41
  name: name,
34
42
  type_name: type_name,
35
- description: description
43
+ description: description,
44
+ parent_class: parent_class
36
45
  )
37
46
  end
38
47
 
39
- def add_fields_to_graphql_type
48
+ def add_attributes
40
49
  scalar_attributes, dynamic_attributes = attributes.values.partition(&:scalar_type?)
41
50
 
42
- AddFieldsToGraphqlType.call(klass: klass, attributes: scalar_attributes)
51
+ add_attributes_batch(scalar_attributes)
43
52
  dynamic_attributes.each { |attribute| find_or_build_dynamic_type(attribute) }
44
- AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
53
+ add_attributes_batch(dynamic_attributes)
45
54
  end
46
55
 
47
56
  def find_or_build_dynamic_type(attribute)
@@ -9,11 +9,12 @@ module GraphqlRails
9
9
 
10
10
  include ::GraphqlRails::Service
11
11
 
12
- def initialize(name:, type_name:, description: nil)
12
+ def initialize(name:, type_name:, parent_class:, description: nil)
13
13
  @name = name
14
14
  @type_name = type_name
15
15
  @description = description
16
16
  @new_class = false
17
+ @parent_class = parent_class
17
18
  end
18
19
 
19
20
  def klass
@@ -27,13 +28,13 @@ module GraphqlRails
27
28
  private
28
29
 
29
30
  attr_accessor :new_class
30
- attr_reader :name, :type_name, :description
31
+ attr_reader :name, :type_name, :description, :parent_class
31
32
 
32
33
  def build_graphql_type_klass
33
34
  graphql_type_name = name
34
35
  graphql_type_description = description
35
36
 
36
- graphql_type_klass = Class.new(GraphqlRails::Types::ObjectType) do
37
+ graphql_type_klass = Class.new(parent_class) do
37
38
  graphql_name(graphql_type_name)
38
39
  description(graphql_type_description)
39
40
  end
@@ -6,7 +6,7 @@ module GraphqlRails
6
6
  class Input
7
7
  require 'graphql_rails/concerns/chainable_options'
8
8
  require 'graphql_rails/model/configurable'
9
- require 'graphql_rails/model/build_graphql_input_type'
9
+ require 'graphql_rails/model/find_or_build_graphql_input_type'
10
10
 
11
11
  include Configurable
12
12
 
@@ -18,8 +18,8 @@ module GraphqlRails
18
18
  end
19
19
 
20
20
  def graphql_input_type
21
- @graphql_input_type ||= BuildGraphqlInputType.call(
22
- name: name, description: description, attributes: attributes
21
+ @graphql_input_type ||= FindOrBuildGraphqlInputType.call(
22
+ name: name, description: description, attributes: attributes, type_name: type_name
23
23
  )
24
24
  end
25
25
 
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'route'
4
+
5
+ module GraphqlRails
6
+ class Router
7
+ # stores subscription type graphql action info
8
+ class EventRoute
9
+ attr_reader :name, :module_name, :subscription_class, :groups, :scope_names
10
+
11
+ def initialize(name, subscription_class: nil, groups: nil, scope_names: [], **options)
12
+ @name = name.to_s.camelize(:lower)
13
+ @module_name = options[:module].to_s
14
+ @groups = groups
15
+ @subscription_class = subscription_class
16
+ @scope_names = scope_names
17
+ end
18
+
19
+ def show_in_group?(group_name)
20
+ return true if groups.nil? || groups.empty?
21
+
22
+ groups.include?(group_name&.to_sym)
23
+ end
24
+
25
+ def field_options
26
+ { subscription: subscription }
27
+ end
28
+
29
+ def subscription
30
+ if subscription_class.present?
31
+ subscription_class.is_a?(String) ? Object.const_get(subscription_class) : subscription_class
32
+ else
33
+ klass_name = ['subscriptions/', name.underscore, 'subscription'].join('_').camelize
34
+
35
+ Object.const_get(klass_name)
36
+ end
37
+ end
38
+
39
+ def mutation?
40
+ false
41
+ end
42
+
43
+ def query?
44
+ false
45
+ end
46
+
47
+ def event?
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
@@ -14,7 +14,7 @@ module GraphqlRails
14
14
  true
15
15
  end
16
16
 
17
- def subscription?
17
+ def event?
18
18
  false
19
19
  end
20
20
  end
@@ -14,7 +14,7 @@ module GraphqlRails
14
14
  false
15
15
  end
16
16
 
17
- def subscription?
17
+ def event?
18
18
  false
19
19
  end
20
20
  end
@@ -28,10 +28,6 @@ module GraphqlRails
28
28
  routes << build_mutation(*args, **kwargs)
29
29
  end
30
30
 
31
- def subscription(*args, **kwargs)
32
- routes << build_subscription(*args, **kwargs)
33
- end
34
-
35
31
  private
36
32
 
37
33
  attr_reader :autogenerated_action_names, :name, :options
@@ -66,10 +62,6 @@ module GraphqlRails
66
62
  build_route(QueryRoute, *args, **kwargs)
67
63
  end
68
64
 
69
- def build_subscription(*args, **kwargs)
70
- build_route(SubscriptionRoute, *args, **kwargs)
71
- end
72
-
73
65
  # rubocop:disable Metrics/ParameterLists
74
66
  def build_route(builder, action, prefix: action, suffix: false, on: :member, **custom_options)
75
67
  if suffix == true
@@ -38,7 +38,7 @@ module GraphqlRails
38
38
  if function
39
39
  { function: function }
40
40
  else
41
- { resolver: resolver }
41
+ { resolver: resolver, extras: [:lookahead] }
42
42
  end
43
43
  end
44
44
 
@@ -7,12 +7,12 @@ module GraphqlRails
7
7
  require_relative './plain_cursor_encoder'
8
8
  require_relative './build_schema_action_type'
9
9
 
10
- attr_reader :queries, :mutations, :subscriptions, :raw_actions
10
+ attr_reader :queries, :mutations, :events, :raw_actions
11
11
 
12
- def initialize(queries:, mutations:, subscriptions:, raw_actions:, group: nil)
12
+ def initialize(queries:, mutations:, events:, raw_actions:, group: nil)
13
13
  @queries = queries
14
14
  @mutations = mutations
15
- @subscriptions = subscriptions
15
+ @events = events
16
16
  @raw_actions = raw_actions
17
17
  @group = group
18
18
  end
@@ -20,26 +20,31 @@ module GraphqlRails
20
20
  def call
21
21
  query_type = build_group_type('Query', queries)
22
22
  mutation_type = build_group_type('Mutation', mutations)
23
- subscription_type = build_group_type('Subscription', subscriptions)
24
- raw = raw_actions
23
+ subscription_type = build_group_type('Subscription', events)
25
24
 
25
+ define_schema_class(query_type, mutation_type, subscription_type, raw_actions)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :group
31
+
32
+ # rubocop:disable Metrics/MethodLength
33
+ def define_schema_class(query_type, mutation_type, subscription_type, raw)
26
34
  Class.new(GraphQL::Schema) do
27
35
  connections.add(
28
36
  GraphqlRails::Decorator::RelationDecorator,
29
37
  GraphQL::Pagination::ActiveRecordRelationConnection
30
38
  )
31
39
  cursor_encoder(Router::PlainCursorEncoder)
32
- raw.each { |action| send(action[:name], *action[:args], &action[:block]) }
40
+ raw.each { |action| send(action[:name], *action[:args], **action[:kwargs], &action[:block]) }
33
41
 
34
42
  query(query_type) if query_type
35
43
  mutation(mutation_type) if mutation_type
36
44
  subscription(subscription_type) if subscription_type
37
45
  end
38
46
  end
39
-
40
- private
41
-
42
- attr_reader :group
47
+ # rubocop:enable Metrics/MethodLength
43
48
 
44
49
  def build_group_type(type_name, routes)
45
50
  group_name = group
@@ -5,7 +5,7 @@ require 'active_support/core_ext/string/inflections'
5
5
  require 'graphql_rails/router/schema_builder'
6
6
  require 'graphql_rails/router/mutation_route'
7
7
  require 'graphql_rails/router/query_route'
8
- require 'graphql_rails/router/subscription_route'
8
+ require 'graphql_rails/router/event_route'
9
9
  require 'graphql_rails/router/resource_routes_builder'
10
10
 
11
11
  module GraphqlRails
@@ -63,13 +63,13 @@ module GraphqlRails
63
63
  routes << build_route(MutationRoute, name, **options)
64
64
  end
65
65
 
66
- def subscription(name, **options)
67
- routes << build_route(SubscriptionRoute, name, **options)
66
+ def event(name, **options)
67
+ routes << build_route(EventRoute, name, **options)
68
68
  end
69
69
 
70
70
  RAW_ACTION_NAMES.each do |action_name|
71
- define_method(action_name) do |*args, &block|
72
- add_raw_action(action_name, *args, &block)
71
+ define_method(action_name) do |*args, **kwargs, &block|
72
+ add_raw_action(action_name, *args, **kwargs, &block)
73
73
  end
74
74
  end
75
75
 
@@ -77,7 +77,7 @@ module GraphqlRails
77
77
  @graphql_schema[group&.to_sym] ||= SchemaBuilder.new(
78
78
  queries: routes.select(&:query?),
79
79
  mutations: routes.select(&:mutation?),
80
- subscriptions: routes.select(&:subscription?),
80
+ events: routes.select(&:event?),
81
81
  raw_actions: raw_graphql_actions,
82
82
  group: group
83
83
  ).call
@@ -110,8 +110,8 @@ module GraphqlRails
110
110
  { module_name: module_name, group_names: group_names, scope_names: scope_names }
111
111
  end
112
112
 
113
- def add_raw_action(name, *args, &block)
114
- raw_graphql_actions << { name: name, args: args, block: block }
113
+ def add_raw_action(name, *args, **kwargs, &block)
114
+ raw_graphql_actions << { name: name, args: args, kwargs: kwargs, block: block }
115
115
  end
116
116
 
117
117
  def build_route(route_builder, name, **options)
@@ -95,7 +95,9 @@ module GraphqlRails
95
95
  # controller request object more suitable for testing
96
96
  class Request < GraphqlRails::Controller::Request
97
97
  def initialize(params, context)
98
- super(nil, params, context)
98
+ inputs = params || {}
99
+ inputs = inputs.merge(lookahead: ::GraphQL::Execution::Lookahead::NullLookahead.new)
100
+ super(nil, inputs, context)
99
101
  end
100
102
  end
101
103
 
@@ -6,10 +6,11 @@ module GraphqlRails
6
6
  module Types
7
7
  # Add visibility option based on groups
8
8
  module HidableByGroup
9
- def initialize(*args, groups: [], **kwargs, &block)
9
+ def initialize(*args, groups: [], hidden_in_groups: [], **kwargs, &block)
10
10
  super(*args, **kwargs, &block)
11
11
 
12
- @groups = groups.map(&:to_s)
12
+ @hidden_in_groups = hidden_in_groups.map(&:to_s)
13
+ @groups = groups.map(&:to_s) - @hidden_in_groups
13
14
  end
14
15
 
15
16
  def visible?(context)
@@ -22,10 +23,29 @@ module GraphqlRails
22
23
  @groups
23
24
  end
24
25
 
26
+ def hidden_in_groups
27
+ @hidden_in_groups
28
+ end
29
+
25
30
  def visible_in_context_group?(context)
31
+ group = context_graphql_group(context)
32
+
33
+ return true if no_visibility_configuration?(group)
34
+ return groups.include?(group) unless groups.empty?
35
+
36
+ !hidden_in_groups.include?(group)
37
+ end
38
+
39
+ def no_visibility_configuration?(group)
40
+ return true if group.nil?
41
+
42
+ groups.empty? && hidden_in_groups.empty?
43
+ end
44
+
45
+ def context_graphql_group(context)
26
46
  group = context[:graphql_group] || context['graphql_group']
27
47
 
28
- group.nil? || groups.empty? || groups.include?(group.to_s)
48
+ group.nil? ? nil : group.to_s
29
49
  end
30
50
  end
31
51
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/argument_type'
4
+
5
+ module GraphqlRails
6
+ module Types
7
+ # Base graphql type class for all GraphqlRails models
8
+ class InputObjectType < GraphQL::Schema::InputObject
9
+ argument_class(GraphqlRails::Types::ArgumentType)
10
+
11
+ def self.inspect
12
+ "#{GraphQL::Schema::InputObject}(#{graphql_name})"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '2.3.0'
4
+ VERSION = '2.4.0'
5
5
  end
metadata CHANGED
@@ -1,35 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Povilas Jurčys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-25 00:00:00.000000000 Z
11
+ date: 2023-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.12'
20
- - - ">="
17
+ - - '='
21
18
  - !ruby/object:Gem::Version
22
- version: 1.12.4
19
+ version: 2.0.21
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '1.12'
30
- - - ">="
24
+ - - '='
31
25
  - !ruby/object:Gem::Version
32
- version: 1.12.4
26
+ version: 2.0.21
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: activesupport
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -209,10 +203,10 @@ files:
209
203
  - lib/graphql_rails/model/build_connection_type.rb
210
204
  - lib/graphql_rails/model/build_connection_type/count_items.rb
211
205
  - lib/graphql_rails/model/build_enum_type.rb
212
- - lib/graphql_rails/model/build_graphql_input_type.rb
213
206
  - lib/graphql_rails/model/call_graphql_model_method.rb
214
207
  - lib/graphql_rails/model/configurable.rb
215
208
  - lib/graphql_rails/model/configuration.rb
209
+ - lib/graphql_rails/model/find_or_build_graphql_input_type.rb
216
210
  - lib/graphql_rails/model/find_or_build_graphql_type.rb
217
211
  - lib/graphql_rails/model/find_or_build_graphql_type_class.rb
218
212
  - lib/graphql_rails/model/input.rb
@@ -220,13 +214,13 @@ files:
220
214
  - lib/graphql_rails/railtie.rb
221
215
  - lib/graphql_rails/router.rb
222
216
  - lib/graphql_rails/router/build_schema_action_type.rb
217
+ - lib/graphql_rails/router/event_route.rb
223
218
  - lib/graphql_rails/router/mutation_route.rb
224
219
  - lib/graphql_rails/router/plain_cursor_encoder.rb
225
220
  - lib/graphql_rails/router/query_route.rb
226
221
  - lib/graphql_rails/router/resource_routes_builder.rb
227
222
  - lib/graphql_rails/router/route.rb
228
223
  - lib/graphql_rails/router/schema_builder.rb
229
- - lib/graphql_rails/router/subscription_route.rb
230
224
  - lib/graphql_rails/rspec_controller_helpers.rb
231
225
  - lib/graphql_rails/tasks/dump_graphql_schema.rb
232
226
  - lib/graphql_rails/tasks/dump_graphql_schemas.rb
@@ -234,6 +228,7 @@ files:
234
228
  - lib/graphql_rails/types/argument_type.rb
235
229
  - lib/graphql_rails/types/field_type.rb
236
230
  - lib/graphql_rails/types/hidable_by_group.rb
231
+ - lib/graphql_rails/types/input_object_type.rb
237
232
  - lib/graphql_rails/types/object_type.rb
238
233
  - lib/graphql_rails/version.rb
239
234
  homepage: https://github.com/samesystem/graphql_rails
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'graphql_rails/types/argument_type'
4
- require 'graphql_rails/concerns/service'
5
-
6
- module GraphqlRails
7
- module Model
8
- # stores information about model specific config, like attributes and types
9
- class BuildGraphqlInputType
10
- include ::GraphqlRails::Service
11
-
12
- def initialize(name:, description: nil, attributes:)
13
- @name = name
14
- @attributes = attributes
15
- @description = description
16
- end
17
-
18
- def call
19
- type_name = name
20
- type_description = description
21
- type_attributes = attributes
22
-
23
- Class.new(GraphQL::Schema::InputObject) do
24
- argument_class(GraphqlRails::Types::ArgumentType)
25
- graphql_name(type_name)
26
- description(type_description)
27
-
28
- type_attributes.each_value do |type_attribute|
29
- argument(*type_attribute.input_argument_args, **type_attribute.input_argument_options)
30
- end
31
-
32
- def self.inspect
33
- "#{GraphQL::Schema::InputObject}(#{graphql_name})"
34
- end
35
- end
36
- end
37
-
38
- private
39
-
40
- attr_reader :model_configuration, :attributes, :name, :description
41
- end
42
- end
43
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'route'
4
-
5
- module GraphqlRails
6
- class Router
7
- # stores subscription type graphql action info
8
- class SubscriptionRoute < Route
9
- def query?
10
- false
11
- end
12
-
13
- def mutation?
14
- false
15
- end
16
-
17
- def subscription?
18
- true
19
- end
20
- end
21
- end
22
- end