graphql_rails 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +3 -2
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile.lock +76 -73
  5. data/docs/README.md +1 -1
  6. data/docs/components/controller.md +15 -1
  7. data/docs/components/model.md +130 -6
  8. data/docs/components/routes.md +20 -10
  9. data/graphql_rails.gemspec +1 -1
  10. data/lib/generators/graphql_rails/templates/graphql_controller.erb +1 -1
  11. data/lib/graphql_rails/attributes/attributable.rb +6 -0
  12. data/lib/graphql_rails/attributes/attribute.rb +22 -9
  13. data/lib/graphql_rails/attributes/attribute_configurable.rb +27 -0
  14. data/lib/graphql_rails/attributes/attribute_name_parser.rb +4 -4
  15. data/lib/graphql_rails/attributes/input_attribute.rb +7 -1
  16. data/lib/graphql_rails/attributes/type_parseable.rb +6 -7
  17. data/lib/graphql_rails/controller/action.rb +4 -4
  18. data/lib/graphql_rails/controller/action_configuration.rb +1 -1
  19. data/lib/graphql_rails/controller/build_controller_action_resolver.rb +4 -15
  20. data/lib/graphql_rails/controller/configuration.rb +7 -2
  21. data/lib/graphql_rails/controller/handle_controller_error.rb +65 -0
  22. data/lib/graphql_rails/controller/log_controller_action.rb +1 -0
  23. data/lib/graphql_rails/controller/request/format_errors.rb +1 -1
  24. data/lib/graphql_rails/controller/request.rb +3 -2
  25. data/lib/graphql_rails/controller.rb +9 -6
  26. data/lib/graphql_rails/decorator/relation_decorator.rb +2 -2
  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/model/configuration.rb +15 -2
  30. data/lib/graphql_rails/model/find_or_build_graphql_input_type.rb +36 -0
  31. data/lib/graphql_rails/model/find_or_build_graphql_type.rb +47 -13
  32. data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +7 -3
  33. data/lib/graphql_rails/model/input.rb +3 -3
  34. data/lib/graphql_rails/router/event_route.rb +52 -0
  35. data/lib/graphql_rails/router/mutation_route.rb +1 -1
  36. data/lib/graphql_rails/router/query_route.rb +1 -1
  37. data/lib/graphql_rails/router/resource_routes_builder.rb +0 -8
  38. data/lib/graphql_rails/router/route.rb +12 -2
  39. data/lib/graphql_rails/router/schema_builder.rb +15 -10
  40. data/lib/graphql_rails/router.rb +8 -8
  41. data/lib/graphql_rails/rspec_controller_helpers.rb +17 -3
  42. data/lib/graphql_rails/types/hidable_by_group.rb +23 -3
  43. data/lib/graphql_rails/types/input_object_type.rb +16 -0
  44. data/lib/graphql_rails/version.rb +1 -1
  45. metadata +10 -14
  46. data/lib/graphql_rails/model/build_graphql_input_type.rb +0 -43
  47. data/lib/graphql_rails/router/subscription_route.rb +0 -22
@@ -21,18 +21,12 @@ module GraphqlRails
21
21
  @attributes ||= {}
22
22
  end
23
23
 
24
- def property(new_value = NOT_SET)
25
- return @property if new_value == NOT_SET
26
-
27
- @property = new_value.to_s
28
- self
29
- end
30
-
31
24
  def field_args
32
25
  [
33
26
  field_name,
34
27
  type_parser.type_arg,
35
- description
28
+ description,
29
+ *field_args_options
36
30
  ].compact
37
31
  end
38
32
 
@@ -42,7 +36,9 @@ module GraphqlRails
42
36
  null: optional?,
43
37
  camelize: camelize?,
44
38
  groups: groups,
45
- **deprecation_reason_params
39
+ hidden_in_groups: hidden_in_groups,
40
+ **deprecation_reason_params,
41
+ **extras_options
46
42
  }
47
43
  end
48
44
 
@@ -52,6 +48,12 @@ module GraphqlRails
52
48
 
53
49
  private
54
50
 
51
+ def extras_options
52
+ return {} if extras.empty?
53
+
54
+ { extras: extras }
55
+ end
56
+
55
57
  def camelize?
56
58
  options[:input_format] != :original && options[:attribute_name_format] != :original
57
59
  end
@@ -59,6 +61,17 @@ module GraphqlRails
59
61
  def deprecation_reason_params
60
62
  { deprecation_reason: deprecation_reason }.compact
61
63
  end
64
+
65
+ def field_args_options
66
+ options = { **field_args_pagination_options }
67
+ return nil if options.empty?
68
+
69
+ [options]
70
+ end
71
+
72
+ def field_args_pagination_options
73
+ pagination_options || {}
74
+ end
62
75
  end
63
76
  end
64
77
  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
@@ -55,6 +64,24 @@ module GraphqlRails
55
64
  def deprecation_reason
56
65
  @deprecation_reason
57
66
  end
67
+
68
+ def property(new_value = ChainableOptions::NOT_SET)
69
+ return @property if new_value == ChainableOptions::NOT_SET
70
+
71
+ @property = new_value.to_s
72
+ self
73
+ end
74
+
75
+ def same_as(other_attribute)
76
+ other = other_attribute.dup
77
+ other.instance_variables.each do |instance_variable|
78
+ next if instance_variable == :@initial_name
79
+
80
+ instance_variable_set(instance_variable, other.instance_variable_get(instance_variable))
81
+ end
82
+
83
+ self
84
+ end
58
85
  end
59
86
  end
60
87
  end
@@ -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,7 +31,9 @@ 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,
36
+ **property_params,
35
37
  **deprecation_reason_params
36
38
  }
37
39
  end
@@ -58,6 +60,10 @@ module GraphqlRails
58
60
  { deprecation_reason: deprecation_reason }.compact
59
61
  end
60
62
 
63
+ def property_params
64
+ { as: property }.compact
65
+ end
66
+
61
67
  def attribute_naming_options
62
68
  options.slice(:input_format)
63
69
  end
@@ -79,7 +85,7 @@ module GraphqlRails
79
85
  end
80
86
 
81
87
  def raw_input_type
82
- return type if type.is_a?(GraphQL::InputObjectType)
88
+ return type if type.is_a?(GraphQL::Schema::InputObject)
83
89
  return type.graphql_input_type if type.is_a?(Model::Input)
84
90
  end
85
91
  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
@@ -95,9 +94,9 @@ module GraphqlRails
95
94
  end
96
95
 
97
96
  def graphql_type_object?(type_class)
98
- return false unless type_class.is_a?(Class)
97
+ return false if !type_class.is_a?(Class) && !type_class.is_a?(Module)
99
98
 
100
- type_class < GraphQL::Schema::Member
99
+ type_class < GraphQL::Schema::Member::GraphQLTypeNames
101
100
  end
102
101
 
103
102
  def applicable_graphql_type?(type)
@@ -43,16 +43,16 @@ module GraphqlRails
43
43
  { null: !type_parser.required? }
44
44
  end
45
45
 
46
+ def action_config
47
+ controller.controller_configuration.action_config(name)
48
+ end
49
+
46
50
  private
47
51
 
48
52
  attr_reader :route
49
53
 
50
54
  delegate :type_parser, to: :action_config
51
55
 
52
- def action_config
53
- controller.controller_configuration.action_config(name)
54
- end
55
-
56
56
  def namespaced_controller_name
57
57
  [route.module_name, controller_name].reject(&:empty?).join('/')
58
58
  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 ActionConfiguration
12
12
  class MissingConfigurationError < GraphqlRails::Error; end
13
13
  class DeprecatedDefaultModelError < GraphqlRails::Error; end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql_rails/controller/action'
4
3
  require 'graphql_rails/concerns/service'
5
4
  require 'graphql_rails/controller/action_configuration'
6
5
  require 'graphql_rails/controller/build_controller_action_resolver/controller_action_resolver'
@@ -11,12 +10,12 @@ module GraphqlRails
11
10
  class BuildControllerActionResolver
12
11
  include ::GraphqlRails::Service
13
12
 
14
- def initialize(route:)
15
- @route = route
13
+ def initialize(action:)
14
+ @action = action
16
15
  end
17
16
 
18
17
  def call # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
19
- action = build_action
18
+ action = self.action
20
19
 
21
20
  Class.new(ControllerActionResolver) do
22
21
  graphql_name("ControllerActionResolver#{SecureRandom.hex}")
@@ -38,17 +37,7 @@ module GraphqlRails
38
37
 
39
38
  private
40
39
 
41
- attr_reader :route
42
-
43
- def build_action
44
- Action.new(route).tap do |action|
45
- assert_action(action)
46
- end
47
- end
48
-
49
- def assert_action(action)
50
- action.return_type
51
- end
40
+ attr_reader :action
52
41
  end
53
42
  end
54
43
  end
@@ -7,13 +7,13 @@ 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
 
14
14
  LIB_REGEXP = %r{/graphql_rails/lib/}
15
15
 
16
- attr_reader :action_by_name
16
+ attr_reader :action_by_name, :error_handlers
17
17
 
18
18
  def initialize(controller)
19
19
  @controller = controller
@@ -25,6 +25,7 @@ module GraphqlRails
25
25
 
26
26
  @action_by_name = {}
27
27
  @action_default = nil
28
+ @error_handlers = {}
28
29
  end
29
30
 
30
31
  def initialize_copy(other)
@@ -56,6 +57,10 @@ module GraphqlRails
56
57
  ActionHook.new(name: hook_name, **options, &block)
57
58
  end
58
59
 
60
+ def add_error_handler(error, with:, &block)
61
+ @error_handlers[error] = with || block
62
+ end
63
+
59
64
  def action_default
60
65
  @action_default ||= ActionConfiguration.new(name: :default, controller: nil)
61
66
  yield(@action_default) if block_given?
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlRails
4
+ class Controller
5
+ # runs {before/around/after}_action controller hooks
6
+ class HandleControllerError
7
+ def initialize(error:, controller:)
8
+ @error = error
9
+ @controller = controller
10
+ end
11
+
12
+ def call
13
+ return custom_handle_error if custom_handle_error?
14
+
15
+ render_unhandled_error(error)
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :error, :controller
21
+
22
+ def render_unhandled_error(error)
23
+ return render(error: error) if error.is_a?(GraphQL::ExecutionError)
24
+
25
+ render(error: SystemError.new(error))
26
+ end
27
+
28
+ def custom_handle_error
29
+ return unless custom_handler
30
+
31
+ begin
32
+ if custom_handler.is_a?(Proc)
33
+ controller.instance_exec(error, &custom_handler)
34
+ else
35
+ controller.send(custom_handler)
36
+ end
37
+ rescue StandardError => e
38
+ render_unhandled_error(e)
39
+ end
40
+ end
41
+
42
+ def custom_handler
43
+ return @custom_handler if defined?(@custom_handler)
44
+
45
+ handler = controller_config.error_handlers.detect do |error_class, _handler|
46
+ error.class <= error_class
47
+ end
48
+
49
+ @custom_handler = handler&.last
50
+ end
51
+
52
+ def custom_handle_error?
53
+ custom_handler.present?
54
+ end
55
+
56
+ def controller_config
57
+ @controller_config ||= controller.class.controller_configuration
58
+ end
59
+
60
+ def render(*args, **kwargs, &block)
61
+ controller.send(:render, *args, **kwargs, &block)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -7,6 +7,7 @@ module GraphqlRails
7
7
  # logs controller start and end times
8
8
  class LogControllerAction
9
9
  require 'graphql_rails/concerns/service'
10
+ require 'active_support/notifications'
10
11
 
11
12
  include ::GraphqlRails::Service
12
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
 
@@ -6,6 +6,7 @@ require 'graphql_rails/controller/configuration'
6
6
  require 'graphql_rails/controller/request'
7
7
  require 'graphql_rails/controller/action_hooks_runner'
8
8
  require 'graphql_rails/controller/log_controller_action'
9
+ require 'graphql_rails/controller/handle_controller_error'
9
10
  require 'graphql_rails/errors/system_error'
10
11
 
11
12
  module GraphqlRails
@@ -45,6 +46,12 @@ module GraphqlRails
45
46
  def controller_configuration
46
47
  @controller_configuration ||= Controller::Configuration.new(self)
47
48
  end
49
+
50
+ def rescue_from(*errors, with: nil, &block)
51
+ Array(errors).each do |error|
52
+ controller_configuration.add_error_handler(error, with: with, &block)
53
+ end
54
+ end
48
55
  end
49
56
 
50
57
  attr_reader :action_name
@@ -86,12 +93,8 @@ module GraphqlRails
86
93
  response = hooks_runner.call { public_send(action_name) }
87
94
 
88
95
  render response if graphql_request.no_object_to_return?
89
- rescue StandardError => error
90
- if error.is_a?(GraphQL::ExecutionError)
91
- render error: error
92
- else
93
- render error: SystemError.new(error)
94
- end
96
+ rescue StandardError => e
97
+ HandleControllerError.new(error: e, controller: self).call
95
98
  end
96
99
 
97
100
  def graphql_errors_from_render_params(rendering_params)
@@ -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)
@@ -24,10 +24,21 @@ module GraphqlRails
24
24
  @input = other.instance_variable_get(:@input)&.transform_values(&:dup)
25
25
  end
26
26
 
27
+ def implements(*interfaces)
28
+ previous_implements = get_or_set_chainable_option(:implements) || []
29
+ return previous_implements if interfaces.blank?
30
+
31
+ full_implements = (previous_implements + interfaces).uniq
32
+
33
+ get_or_set_chainable_option(:implements, full_implements) || []
34
+ end
35
+
27
36
  def attribute(attribute_name, **attribute_options)
28
37
  key = attribute_name.to_s
29
38
 
30
- attributes[key] ||= build_attribute(attribute_name).tap do |new_attribute|
39
+ attributes[key] ||= build_attribute(attribute_name)
40
+
41
+ attributes[key].tap do |new_attribute|
31
42
  new_attribute.with(**attribute_options)
32
43
  yield(new_attribute) if block_given?
33
44
  end
@@ -52,7 +63,8 @@ module GraphqlRails
52
63
  name: name,
53
64
  description: description,
54
65
  attributes: attributes,
55
- type_name: type_name
66
+ type_name: type_name,
67
+ implements: implements
56
68
  )
57
69
  end
58
70
 
@@ -86,6 +98,7 @@ module GraphqlRails
86
98
  description: description,
87
99
  attributes: attributes,
88
100
  type_name: type_name,
101
+ implements: implements,
89
102
  force_define_attributes: true
90
103
  )
91
104
  end
@@ -0,0 +1,36 @@
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
+
27
+ def find_or_build_dynamic_type(attribute)
28
+ graphql_model = attribute.graphql_model
29
+ return unless graphql_model
30
+
31
+ graphql = graphql_model.graphql.input(attribute.subtype)
32
+ find_or_build_graphql_model_type(graphql)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -10,51 +10,85 @@ module GraphqlRails
10
10
 
11
11
  include ::GraphqlRails::Service
12
12
 
13
- def initialize(name:, description:, attributes:, type_name:, force_define_attributes: false)
13
+ # rubocop:disable Metrics/ParameterLists
14
+ def initialize(
15
+ name:,
16
+ description:,
17
+ attributes:,
18
+ type_name:,
19
+ force_define_attributes: false,
20
+ implements: []
21
+ )
14
22
  @name = name
15
23
  @description = description
16
24
  @attributes = attributes
17
25
  @type_name = type_name
18
26
  @force_define_attributes = force_define_attributes
27
+ @implements = implements
19
28
  end
29
+ # rubocop:enable Metrics/ParameterLists
20
30
 
21
31
  def call
22
- klass.tap { add_fields_to_graphql_type if new_class? || force_define_attributes }
32
+ klass.tap do
33
+ add_attributes if new_class? || force_define_attributes
34
+ add_interfaces
35
+ end
23
36
  end
24
37
 
25
38
  private
26
39
 
27
- attr_reader :name, :description, :attributes, :type_name, :force_define_attributes
40
+ attr_reader :name, :description, :attributes, :type_name, :force_define_attributes,
41
+ :implements
28
42
 
29
43
  delegate :klass, :new_class?, to: :type_class_finder
30
44
 
45
+ def parent_class
46
+ GraphqlRails::Types::ObjectType
47
+ end
48
+
49
+ def add_attributes_batch(attributes)
50
+ AddFieldsToGraphqlType.call(klass: klass, attributes: attributes)
51
+ end
52
+
31
53
  def type_class_finder
32
54
  @type_class_finder ||= FindOrBuildGraphqlTypeClass.new(
33
55
  name: name,
34
56
  type_name: type_name,
35
- description: description
57
+ description: description,
58
+ implements: implements,
59
+ parent_class: parent_class
36
60
  )
37
61
  end
38
62
 
39
- def add_fields_to_graphql_type
63
+ def add_attributes
40
64
  scalar_attributes, dynamic_attributes = attributes.values.partition(&:scalar_type?)
41
65
 
42
- AddFieldsToGraphqlType.call(klass: klass, attributes: scalar_attributes)
66
+ add_attributes_batch(scalar_attributes)
43
67
  dynamic_attributes.each { |attribute| find_or_build_dynamic_type(attribute) }
44
- AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
68
+ add_attributes_batch(dynamic_attributes)
69
+ end
70
+
71
+ def add_interfaces
72
+ implements.each do |interface|
73
+ next if klass.interfaces.include?(interface)
74
+
75
+ klass.implements(interface)
76
+ end
45
77
  end
46
78
 
47
79
  def find_or_build_dynamic_type(attribute)
48
80
  graphql_model = attribute.graphql_model
49
- find_or_build_graphql_model_type(graphql_model) if graphql_model
81
+ return unless graphql_model
82
+
83
+ find_or_build_graphql_model_type(graphql_model.graphql)
50
84
  end
51
85
 
52
- def find_or_build_graphql_model_type(graphql_model)
86
+ def find_or_build_graphql_model_type(graphql_config)
53
87
  self.class.call(
54
- name: graphql_model.graphql.name,
55
- description: graphql_model.graphql.description,
56
- attributes: graphql_model.graphql.attributes,
57
- type_name: graphql_model.graphql.type_name
88
+ name: graphql_config.name,
89
+ description: graphql_config.description,
90
+ attributes: graphql_config.attributes,
91
+ type_name: graphql_config.type_name
58
92
  )
59
93
  end
60
94
  end