graphql_rails 1.2.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +18 -0
  3. data/.hound.yml +1 -1
  4. data/.rubocop.yml +4 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +19 -0
  7. data/Gemfile +3 -3
  8. data/Gemfile.lock +27 -25
  9. data/docs/README.md +1 -1
  10. data/docs/components/model.md +107 -13
  11. data/docs/other_tools/schema_dump.md +8 -8
  12. data/lib/graphql_rails/attributes/attributable.rb +6 -14
  13. data/lib/graphql_rails/attributes/attribute.rb +10 -34
  14. data/lib/graphql_rails/attributes/attribute_configurable.rb +45 -0
  15. data/lib/graphql_rails/attributes/attribute_name_parser.rb +7 -7
  16. data/lib/graphql_rails/attributes/input_attribute.rb +20 -14
  17. data/lib/graphql_rails/attributes/input_type_parser.rb +5 -7
  18. data/lib/graphql_rails/attributes/type_parseable.rb +55 -19
  19. data/lib/graphql_rails/attributes/type_parser.rb +4 -9
  20. data/lib/graphql_rails/concerns/chainable_options.rb +49 -0
  21. data/lib/graphql_rails/controller/build_controller_action_resolver/controller_action_resolver.rb +3 -0
  22. data/lib/graphql_rails/decorator/relation_decorator.rb +2 -2
  23. data/lib/graphql_rails/input_configurable.rb +10 -8
  24. data/lib/graphql_rails/model/build_graphql_input_type.rb +4 -2
  25. data/lib/graphql_rails/model/configurable.rb +30 -8
  26. data/lib/graphql_rails/model/configuration.rb +26 -12
  27. data/lib/graphql_rails/model/find_or_build_graphql_type.rb +23 -21
  28. data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +2 -1
  29. data/lib/graphql_rails/model/input.rb +10 -26
  30. data/lib/graphql_rails/model.rb +1 -1
  31. data/lib/graphql_rails/query_runner.rb +9 -3
  32. data/lib/graphql_rails/router/route.rb +2 -2
  33. data/lib/graphql_rails/tasks/dump_graphql_schema.rb +18 -27
  34. data/lib/graphql_rails/tasks/dump_graphql_schemas.rb +57 -0
  35. data/lib/graphql_rails/tasks/schema.rake +8 -5
  36. data/lib/graphql_rails/types/argument_type.rb +12 -0
  37. data/lib/graphql_rails/types/field_type.rb +14 -0
  38. data/lib/graphql_rails/types/hidable_by_group.rb +32 -0
  39. data/lib/graphql_rails/types/object_type.rb +12 -0
  40. data/lib/graphql_rails/version.rb +1 -1
  41. metadata +15 -8
  42. data/.travis.yml +0 -5
@@ -4,22 +4,19 @@ module GraphqlRails
4
4
  module Attributes
5
5
  # contains info about single graphql input attribute
6
6
  class InputAttribute
7
+ require 'graphql_rails/model/build_enum_type'
7
8
  require_relative './input_type_parser'
8
9
  require_relative './attribute_name_parser'
9
10
  include Attributable
11
+ include AttributeConfigurable
10
12
 
11
- attr_reader :description
13
+ chainable_option :subtype
14
+ chainable_option :enum
12
15
 
13
- # rubocop:disable Metrics/ParameterLists
14
- def initialize(name, type: nil, description: nil, subtype: nil, required: nil, options: {})
16
+ def initialize(name, config:)
17
+ @config = config
15
18
  @initial_name = name
16
- @initial_type = type
17
- @description = description
18
- @options = options
19
- @subtype = subtype
20
- @required = required
21
19
  end
22
- # rubocop:enable Metrics/ParameterLists
23
20
 
24
21
  def input_argument_args
25
22
  type = raw_input_type || input_type_parser.input_type_arg
@@ -28,7 +25,7 @@ module GraphqlRails
28
25
  end
29
26
 
30
27
  def input_argument_options
31
- { required: required?, description: description, camelize: false }
28
+ { required: required?, description: description, camelize: false, groups: groups }
32
29
  end
33
30
 
34
31
  def paginated?
@@ -37,7 +34,7 @@ module GraphqlRails
37
34
 
38
35
  private
39
36
 
40
- attr_reader :initial_name, :initial_type, :options, :subtype
37
+ attr_reader :initial_name, :config
41
38
 
42
39
  def attribute_name_parser
43
40
  @attribute_name_parser ||= AttributeNameParser.new(
@@ -51,14 +48,23 @@ module GraphqlRails
51
48
 
52
49
  def input_type_parser
53
50
  @input_type_parser ||= begin
54
- initial_parseable_type = initial_type || attribute_name_parser.graphql_type
51
+ initial_parseable_type = type || enum_type || attribute_name_parser.graphql_type
55
52
  InputTypeParser.new(initial_parseable_type, subtype: subtype)
56
53
  end
57
54
  end
58
55
 
56
+ def enum_type
57
+ return if enum.blank?
58
+
59
+ ::GraphqlRails::Model::BuildEnumType.call(
60
+ "#{config.name}_#{initial_name}_enum",
61
+ allowed_values: enum
62
+ )
63
+ end
64
+
59
65
  def raw_input_type
60
- return initial_type if initial_type.is_a?(GraphQL::InputObjectType)
61
- return initial_type.graphql_input_type if initial_type.is_a?(Model::Input)
66
+ return type if type.is_a?(GraphQL::InputObjectType)
67
+ return type.graphql_input_type if type.is_a?(Model::Input)
62
68
  end
63
69
  end
64
70
  end
@@ -15,12 +15,6 @@ module GraphqlRails
15
15
  @subtype = subtype
16
16
  end
17
17
 
18
- def graphql_type
19
- return nil if unparsed_type.nil?
20
-
21
- partly_parsed_type || parsed_type
22
- end
23
-
24
18
  def input_type_arg
25
19
  if list?
26
20
  list_type_arg
@@ -34,7 +28,11 @@ module GraphqlRails
34
28
  attr_reader :unparsed_type, :subtype
35
29
 
36
30
  def unwrapped_type
37
- raw_unwrapped_type || unwrapped_scalar_type || unwrapped_model_input_type || raise_not_supported_type_error
31
+ raw_unwrapped_type ||
32
+ unwrapped_scalar_type ||
33
+ unwrapped_model_input_type ||
34
+ graphql_type_object ||
35
+ raise_not_supported_type_error
38
36
  end
39
37
 
40
38
  def raw_unwrapped_type
@@ -16,18 +16,27 @@ module GraphqlRails
16
16
  'int' => GraphQL::Types::Int,
17
17
  'integer' => GraphQL::Types::Int,
18
18
 
19
+ 'big_int' => GraphQL::Types::BigInt,
20
+ 'bigint' => GraphQL::Types::BigInt,
21
+
22
+ 'float' => GraphQL::Types::Float,
23
+ 'double' => GraphQL::Types::Float,
24
+ 'decimal' => GraphQL::Types::Float,
25
+
26
+ 'bool' => GraphQL::Types::Boolean,
27
+ 'boolean' => GraphQL::Types::Boolean,
28
+
19
29
  'string' => GraphQL::Types::String,
20
30
  'str' => GraphQL::Types::String,
21
31
  'text' => GraphQL::Types::String,
22
- 'time' => GraphQL::Types::String,
23
- 'date' => GraphQL::Types::String,
24
32
 
25
- 'bool' => GraphQL::Types::Boolean,
26
- 'boolean' => GraphQL::Types::Boolean,
33
+ 'date' => GraphQL::Types::ISO8601Date,
27
34
 
28
- 'float' => GraphQL::Types::Float,
29
- 'double' => GraphQL::Types::Float,
30
- 'decimal' => GraphQL::Types::Float
35
+ 'time' => GraphQL::Types::ISO8601DateTime,
36
+ 'datetime' => GraphQL::Types::ISO8601DateTime,
37
+ 'date_time' => GraphQL::Types::ISO8601DateTime,
38
+
39
+ 'json' => GraphQL::Types::JSON
31
40
  }.freeze
32
41
 
33
42
  WRAPPER_TYPES = [
@@ -43,10 +52,16 @@ module GraphqlRails
43
52
  GraphQL::InputObjectType
44
53
  ].freeze
45
54
 
55
+ PARSEABLE_RAW_GRAPHQL_TYPES = [
56
+ GraphQL::Schema::Object,
57
+ GraphQL::Schema::Scalar,
58
+ GraphQL::Schema::Enum
59
+ ].freeze
60
+
46
61
  RAW_GRAPHQL_TYPES = (WRAPPER_TYPES + GRAPHQL_BASE_TYPES).freeze
47
62
 
48
63
  def unwrapped_scalar_type
49
- TYPE_MAPPING[nullable_inner_name.downcase.downcase]
64
+ TYPE_MAPPING[nullable_inner_name.downcase]
50
65
  end
51
66
 
52
67
  def raw_graphql_type?
@@ -58,25 +73,46 @@ module GraphqlRails
58
73
  end
59
74
 
60
75
  def core_scalar_type?
61
- unwrapped_scalar_type.in?(TYPE_MAPPING.values)
76
+ unwrapped_scalar_type.present?
62
77
  end
63
78
 
64
79
  def graphql_model
65
- type_class = \
66
- if unparsed_type.is_a?(Class) && unparsed_type < GraphqlRails::Model
67
- unparsed_type
68
- else
69
- nullable_inner_name.safe_constantize
70
- end
71
-
72
- return if type_class.nil?
73
- return unless type_class < GraphqlRails::Model
80
+ extract_type_class_if { |type| graphql_model?(type) }
81
+ end
74
82
 
75
- type_class
83
+ def graphql_type_object
84
+ type_object = extract_type_class_if { |type| graphql_type_object?(type) }
85
+ type_object || graphql_model&.graphql&.graphql_type
76
86
  end
77
87
 
78
88
  protected
79
89
 
90
+ def extract_type_class_if
91
+ return unparsed_type if yield(unparsed_type)
92
+
93
+ type_class = nullable_inner_name.safe_constantize
94
+ return type_class if yield(type_class)
95
+
96
+ nil
97
+ end
98
+
99
+ def graphql_model?(type_class)
100
+ type_class.is_a?(Class) && type_class < GraphqlRails::Model
101
+ end
102
+
103
+ def graphql_type_object?(type_class)
104
+ return false unless type_class.is_a?(Class)
105
+
106
+ PARSEABLE_RAW_GRAPHQL_TYPES.any? { |parent_type| type_class < parent_type }
107
+ end
108
+
109
+ def applicable_graphql_type?(type)
110
+ return false unless type.is_a?(Class)
111
+ return true if type < GraphqlRails::Model
112
+
113
+ false
114
+ end
115
+
80
116
  def unwrap_type(type)
81
117
  unwrappable = type
82
118
  unwrappable = unwrappable.of_type while wrapped_type?(unwrappable)
@@ -51,7 +51,9 @@ module GraphqlRails
51
51
  def paginated_type_arg
52
52
  return graphql_model.graphql.connection_type if graphql_model
53
53
 
54
- raise NotSupportedFeature, 'pagination is only supported for models which include GraphqlRails::Model'
54
+ error_message = "Unable to paginate #{unparsed_type.inspect}. " \
55
+ 'Pagination is only supported for models which include GraphqlRails::Model'
56
+ raise NotSupportedFeature, error_message
55
57
  end
56
58
 
57
59
  def list_type_arg
@@ -107,14 +109,7 @@ module GraphqlRails
107
109
  end
108
110
 
109
111
  def type_by_name
110
- unwrapped_scalar_type || unwrapped_model_type || raise_not_supported_type_error
111
- end
112
-
113
- def unwrapped_model_type
114
- type_class = graphql_model
115
- return unless type_class
116
-
117
- type_class.graphql.graphql_type
112
+ unwrapped_scalar_type || graphql_type_object || raise_not_supported_type_error
118
113
  end
119
114
  end
120
115
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlRails
4
+ # Allows defining methods chained way
5
+ module ChainableOptions
6
+ NOT_SET = Object.new
7
+
8
+ # nodoc
9
+ module ClassMethods
10
+ def chainable_option(option_name, default: nil)
11
+ define_method(option_name) do |value = NOT_SET|
12
+ get_or_set_chainable_option(option_name, value, default: default)
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ end
20
+
21
+ def initialize_copy(other)
22
+ super
23
+ @chainable_option = other.instance_variable_get(:@chainable_option).dup
24
+ end
25
+
26
+ def with(**options)
27
+ options.each do |method_name, args|
28
+ send_args = [method_name]
29
+ send_args << args if method(method_name).parameters.present?
30
+ public_send(*send_args)
31
+ end
32
+ self
33
+ end
34
+
35
+ private
36
+
37
+ def fetch_chainable_option(option_name, *default, &block)
38
+ @chainable_option.fetch(option_name.to_sym, *default, &block)
39
+ end
40
+
41
+ def get_or_set_chainable_option(option_name, value = NOT_SET, default: nil)
42
+ @chainable_option ||= {}
43
+ return fetch_chainable_option(option_name, default) if value == NOT_SET
44
+
45
+ @chainable_option[option_name.to_sym] = value
46
+ self
47
+ end
48
+ end
49
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'graphql_rails/controller/request'
4
+ require 'graphql_rails/types/argument_type'
4
5
 
5
6
  module GraphqlRails
6
7
  class Controller
@@ -8,6 +9,8 @@ module GraphqlRails
8
9
  # Resolver which includes controller specific methods.
9
10
  # Used to simplify resolver build for each controller action
10
11
  class ControllerActionResolver < GraphQL::Schema::Resolver
12
+ argument_class(GraphqlRails::Types::ArgumentType)
13
+
11
14
  def self.controller(controller_class = nil)
12
15
  @controller = controller_class if controller_class
13
16
  @controller
@@ -5,7 +5,7 @@ module GraphqlRails
5
5
  # wrapps 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, to: :relation
8
+ delegate :limit_value, :offset_value, :count, :size, :empty?, to: :relation
9
9
 
10
10
  def self.decorates?(object)
11
11
  (defined?(ActiveRecord) && object.is_a?(ActiveRecord::Relation)) ||
@@ -24,7 +24,7 @@ module GraphqlRails
24
24
  end
25
25
  end
26
26
 
27
- %i[first second last].each do |method_name|
27
+ %i[first second last find find_by].each do |method_name|
28
28
  define_method method_name do |*args, &block|
29
29
  decoratable_object_method(method_name, *args, &block)
30
30
  end
@@ -3,9 +3,14 @@
3
3
  module GraphqlRails
4
4
  # contains configuration options related with inputs
5
5
  module InputConfigurable
6
- def permit(*no_type_attributes, **typed_attributes)
7
- no_type_attributes.each { |attribute| permit_input(attribute) }
8
- typed_attributes.each { |attribute, type| permit_input(attribute, type: type) }
6
+ def permit(*args)
7
+ args.each do |arg|
8
+ if arg.is_a? Hash
9
+ arg.each { |attribute, type| permit_input(attribute, type: type) }
10
+ else
11
+ permit_input(arg)
12
+ end
13
+ end
9
14
  self
10
15
  end
11
16
 
@@ -37,11 +42,8 @@ module GraphqlRails
37
42
  end
38
43
 
39
44
  def build_input_attribute(name, options: {}, **other_options)
40
- Attributes::InputAttribute.new(
41
- name.to_s,
42
- options: input_attribute_options.merge(options),
43
- **other_options
44
- )
45
+ input_options = input_attribute_options.merge(options)
46
+ Attributes::InputAttribute.new(name.to_s, config: self).with(options: input_options, **other_options)
45
47
  end
46
48
  end
47
49
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'graphql_rails/types/argument_type'
4
+ require 'graphql_rails/concerns/service'
5
+
3
6
  module GraphqlRails
4
7
  module Model
5
8
  # stores information about model specific config, like attributes and types
6
9
  class BuildGraphqlInputType
7
- require 'graphql_rails/concerns/service'
8
-
9
10
  include ::GraphqlRails::Service
10
11
 
11
12
  def initialize(name:, description: nil, attributes:)
@@ -20,6 +21,7 @@ module GraphqlRails
20
21
  type_attributes = attributes
21
22
 
22
23
  Class.new(GraphQL::Schema::InputObject) do
24
+ argument_class(GraphqlRails::Types::ArgumentType)
23
25
  graphql_name(type_name)
24
26
  description(type_description)
25
27
 
@@ -2,25 +2,47 @@
2
2
 
3
3
  module GraphqlRails
4
4
  module Model
5
- # contains methods which are shared between various configurations
6
- # expects `default_name` to be defined
5
+ # Contains methods which are shared between various configurations.
6
+ #
7
+ # Expects `default_name` to be defined.
8
+ # Expects `build_attribute(attr_name)` method to be defined.
7
9
  module Configurable
10
+ require 'active_support/concern'
11
+ require 'graphql_rails/concerns/chainable_options'
12
+
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ include GraphqlRails::ChainableOptions
17
+
18
+ chainable_option :description
19
+ end
20
+
21
+ def initialize_copy(other)
22
+ super
23
+ @type_name = nil
24
+ @attributes = other.attributes.transform_values(&:dup)
25
+ end
26
+
8
27
  def attributes
9
28
  @attributes ||= {}
10
29
  end
11
30
 
12
- def name(graphql_name = nil)
13
- @name = graphql_name if graphql_name
14
- @name || default_name
31
+ def name(*args)
32
+ get_or_set_chainable_option(:name, *args) || default_name
15
33
  end
16
34
 
17
35
  def type_name
18
36
  @type_name ||= "#{name.camelize}Type#{SecureRandom.hex}"
19
37
  end
20
38
 
21
- def description(new_description = nil)
22
- @description = new_description if new_description
23
- @description
39
+ def attribute(attribute_name, **attribute_options)
40
+ key = attribute_name.to_s
41
+
42
+ attributes[key] ||= build_attribute(attribute_name).tap do |new_attribute|
43
+ new_attribute.with(**attribute_options) unless attribute_options.empty?
44
+ yield(new_attribute) if block_given?
45
+ end
24
46
  end
25
47
  end
26
48
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'graphql_rails/attributes'
4
4
  require 'graphql_rails/model/find_or_build_graphql_type'
5
- require 'graphql_rails/model/build_enum_type'
6
5
  require 'graphql_rails/model/input'
7
6
  require 'graphql_rails/model/configurable'
8
7
  require 'graphql_rails/model/build_connection_type'
@@ -11,6 +10,7 @@ module GraphqlRails
11
10
  module Model
12
11
  # stores information about model specific config, like attributes and types
13
12
  class Configuration
13
+ include ChainableOptions
14
14
  include Configurable
15
15
 
16
16
  def initialize(model_class)
@@ -22,22 +22,14 @@ module GraphqlRails
22
22
  @connection_type = nil
23
23
  @graphql_type = nil
24
24
  @input = other.instance_variable_get(:@input)&.transform_values(&:dup)
25
- @attributes = other.instance_variable_get(:@attributes)&.transform_values(&:dup)
26
25
  end
27
26
 
28
27
  def attribute(attribute_name, **attribute_options)
29
28
  key = attribute_name.to_s
30
29
 
31
- attributes[key] ||= Attributes::Attribute.new(attribute_name)
32
-
33
- attributes[key].tap do |attribute|
34
- attribute_options.each do |method_name, args|
35
- send_args = [method_name]
36
- send_args << args if attribute.method(method_name).parameters.present?
37
- attribute.public_send(*send_args)
38
- end
39
-
40
- yield(attribute) if block_given?
30
+ attributes[key] ||= build_attribute(attribute_name).tap do |new_attribute|
31
+ new_attribute.with(**attribute_options)
32
+ yield(new_attribute) if block_given?
41
33
  end
42
34
  end
43
35
 
@@ -68,13 +60,35 @@ module GraphqlRails
68
60
  @connection_type ||= BuildConnectionType.call(graphql_type)
69
61
  end
70
62
 
63
+ def with_ensured_fields!
64
+ return self if @graphql_type.blank?
65
+
66
+ reset_graphql_type if attributes.any? && graphql_type.fields.length != attributes.length
67
+
68
+ self
69
+ end
70
+
71
71
  private
72
72
 
73
73
  attr_reader :model_class
74
74
 
75
+ def build_attribute(attribute_name)
76
+ Attributes::Attribute.new(attribute_name)
77
+ end
78
+
75
79
  def default_name
76
80
  @default_name ||= model_class.name.split('::').last
77
81
  end
82
+
83
+ def reset_graphql_type
84
+ @graphql_type = FindOrBuildGraphqlType.call(
85
+ name: name,
86
+ description: description,
87
+ attributes: attributes,
88
+ type_name: type_name,
89
+ force_define_attributes: true
90
+ )
91
+ end
78
92
  end
79
93
  end
80
94
  end
@@ -10,20 +10,21 @@ module GraphqlRails
10
10
 
11
11
  include ::GraphqlRails::Service
12
12
 
13
- def initialize(name:, description:, attributes:, type_name:)
13
+ def initialize(name:, description:, attributes:, type_name:, force_define_attributes: false)
14
14
  @name = name
15
15
  @description = description
16
16
  @attributes = attributes
17
17
  @type_name = type_name
18
+ @force_define_attributes = force_define_attributes
18
19
  end
19
20
 
20
21
  def call
21
- klass.tap { add_fields_to_graphql_type if new_class? }
22
+ klass.tap { add_fields_to_graphql_type if new_class? || force_define_attributes }
22
23
  end
23
24
 
24
25
  private
25
26
 
26
- attr_reader :name, :description, :attributes, :type_name
27
+ attr_reader :name, :description, :attributes, :type_name, :force_define_attributes
27
28
 
28
29
  delegate :klass, :new_class?, to: :type_class_finder
29
30
 
@@ -36,29 +37,30 @@ module GraphqlRails
36
37
  end
37
38
 
38
39
  def add_fields_to_graphql_type
39
- AddFieldsToGraphqlType.call(klass: klass, attributes: attributes.values.select(&:scalar_type?))
40
+ scalar_attributes, dynamic_attributes = attributes.values.partition(&:scalar_type?)
40
41
 
41
- attributes.values.reject(&:scalar_type?).tap do |dynamic_attributes|
42
- find_or_build_dynamic_graphql_types(dynamic_attributes) do |name, description, attributes, type_name|
43
- self.class.call(
44
- name: name, description: description,
45
- attributes: attributes, type_name: type_name
46
- )
47
- end
48
- AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
49
- end
42
+ AddFieldsToGraphqlType.call(klass: klass, attributes: scalar_attributes)
43
+ dynamic_attributes.each { |attribute| find_or_build_dynamic_type(attribute) }
44
+ AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
50
45
  end
51
46
 
52
- def find_or_build_dynamic_graphql_types(dynamic_attributes)
53
- dynamic_attributes.each do |attribute|
54
- yield(
55
- attribute.graphql_model.graphql.name,
56
- attribute.graphql_model.graphql.description,
57
- attribute.graphql_model.graphql.attributes,
58
- attribute.graphql_model.graphql.type_name
59
- )
47
+ def find_or_build_dynamic_type(attribute)
48
+ graphql_model = attribute.graphql_model
49
+ if graphql_model
50
+ find_or_build_graphql_model_type(graphql_model)
51
+ else
52
+ AddFieldsToGraphqlType.call(klass: klass, attributes: [attribute])
60
53
  end
61
54
  end
55
+
56
+ def find_or_build_graphql_model_type(graphql_model)
57
+ self.class.call(
58
+ name: graphql_model.graphql.name,
59
+ description: graphql_model.graphql.description,
60
+ attributes: graphql_model.graphql.attributes,
61
+ type_name: graphql_model.graphql.type_name
62
+ )
63
+ end
62
64
  end
63
65
  end
64
66
  end
@@ -5,6 +5,7 @@ module GraphqlRails
5
5
  # Initializes class to define graphql type and fields.
6
6
  class FindOrBuildGraphqlTypeClass
7
7
  require 'graphql_rails/concerns/service'
8
+ require 'graphql_rails/types/object_type'
8
9
 
9
10
  include ::GraphqlRails::Service
10
11
 
@@ -32,7 +33,7 @@ module GraphqlRails
32
33
  graphql_type_name = name
33
34
  graphql_type_description = description
34
35
 
35
- graphql_type_klass = Class.new(GraphQL::Schema::Object) do
36
+ graphql_type_klass = Class.new(GraphqlRails::Types::ObjectType) do
36
37
  graphql_name(graphql_type_name)
37
38
  description(graphql_type_description)
38
39
  end
@@ -1,58 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql_rails/model/build_graphql_input_type'
4
- require 'graphql_rails/model/configurable'
5
-
6
3
  module GraphqlRails
7
4
  module Model
8
5
  # stores information about model input specific config, like attributes and types
9
6
  class Input
7
+ require 'graphql_rails/concerns/chainable_options'
8
+ require 'graphql_rails/model/configurable'
9
+ require 'graphql_rails/model/build_graphql_input_type'
10
+
10
11
  include Configurable
11
12
 
13
+ chainable_option :enum
14
+
12
15
  def initialize(model_class, input_name_suffix)
13
16
  @model_class = model_class
14
17
  @input_name_suffix = input_name_suffix
15
18
  end
16
19
 
17
- def initialize_copy(other)
18
- super
19
- @attributes = other.instance_variable_get(:@attributes)&.transform_values(&:dup)
20
- end
21
-
22
20
  def graphql_input_type
23
21
  @graphql_input_type ||= BuildGraphqlInputType.call(
24
22
  name: name, description: description, attributes: attributes
25
23
  )
26
24
  end
27
25
 
28
- def attribute(attribute_name, type: nil, enum: nil, **attribute_options)
29
- input_type = attribute_type(attribute_name, type: type, enum: enum, **attribute_options)
30
-
31
- attributes[attribute_name.to_s] = Attributes::InputAttribute.new(
32
- attribute_name, type: input_type, **attribute_options
33
- )
34
- end
35
-
36
26
  private
37
27
 
38
28
  attr_reader :input_name_suffix, :model_class
39
29
 
30
+ def build_attribute(attribute_name)
31
+ Attributes::InputAttribute.new(attribute_name, config: self)
32
+ end
33
+
40
34
  def default_name
41
35
  @default_name ||= begin
42
36
  suffix = input_name_suffix ? input_name_suffix.to_s.camelize : ''
43
37
  "#{model_class.name.split('::').last}#{suffix}Input"
44
38
  end
45
39
  end
46
-
47
- def attribute_type(attribute_name, type:, enum:, description: nil, **_other)
48
- return type unless enum
49
-
50
- BuildEnumType.call(
51
- "#{name}_#{attribute_name}_enum",
52
- allowed_values: enum,
53
- description: description
54
- )
55
- end
56
40
  end
57
41
  end
58
42
  end
@@ -28,7 +28,7 @@ module GraphqlRails
28
28
 
29
29
  def graphql
30
30
  @graphql ||= Model::Configuration.new(self)
31
- yield(@graphql) if block_given?
31
+ @graphql.tap { |it| yield(it) }.with_ensured_fields! if block_given?
32
32
  @graphql
33
33
  end
34
34
  end