graphql_rails 2.3.0 → 3.0.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.
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