hq-graphql 2.1.9 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +34 -9
- data/lib/hq/graphql.rb +21 -8
- data/lib/hq/graphql/association_loader.rb +1 -0
- data/lib/hq/graphql/comparator.rb +22 -21
- data/lib/hq/graphql/config.rb +1 -0
- data/lib/hq/graphql/enum/sort_by.rb +8 -4
- data/lib/hq/graphql/enum/sort_order.rb +8 -4
- data/lib/hq/graphql/ext.rb +8 -0
- data/lib/hq/graphql/ext/active_record_extensions.rb +148 -0
- data/lib/hq/graphql/ext/enum_extensions.rb +81 -0
- data/lib/hq/graphql/ext/input_object_extensions.rb +110 -0
- data/lib/hq/graphql/ext/mutation_extensions.rb +24 -0
- data/lib/hq/graphql/ext/object_extensions.rb +122 -0
- data/lib/hq/graphql/ext/schema_extensions.rb +50 -0
- data/lib/hq/graphql/field.rb +1 -1
- data/lib/hq/graphql/paginated_association_loader.rb +1 -0
- data/lib/hq/graphql/record_loader.rb +1 -0
- data/lib/hq/graphql/resource.rb +45 -14
- data/lib/hq/graphql/resource/auto_mutation.rb +8 -5
- data/lib/hq/graphql/root_mutation.rb +1 -1
- data/lib/hq/graphql/root_query.rb +3 -3
- data/lib/hq/graphql/scalars.rb +0 -2
- data/lib/hq/graphql/types.rb +1 -2
- data/lib/hq/graphql/version.rb +1 -1
- metadata +24 -38
- data/lib/hq/graphql/active_record_extensions.rb +0 -139
- data/lib/hq/graphql/enum.rb +0 -78
- data/lib/hq/graphql/input_object.rb +0 -95
- data/lib/hq/graphql/mutation.rb +0 -15
- data/lib/hq/graphql/object.rb +0 -116
- data/lib/hq/graphql/schema.rb +0 -22
- data/lib/hq/graphql/types/object.rb +0 -35
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hq/graphql/types"
|
4
|
+
|
5
|
+
module HQ::GraphQL
|
6
|
+
module Ext
|
7
|
+
module EnumExtensions
|
8
|
+
## Auto generate enums from the database using ActiveRecord
|
9
|
+
# This comes in handy when we have constants that we want represented as enums.
|
10
|
+
#
|
11
|
+
# == Example
|
12
|
+
# Let's assume we're saving data into a user types table
|
13
|
+
# # select * from user_types;
|
14
|
+
# id | name
|
15
|
+
# --- +-------------
|
16
|
+
# 1 | Admin
|
17
|
+
# 2 | Support User
|
18
|
+
# (2 rows)
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# class Enums::UserType < ::HQ::GraphQL::Enum
|
22
|
+
# with_model
|
23
|
+
# end
|
24
|
+
# ```
|
25
|
+
#
|
26
|
+
# Creates the following enum:
|
27
|
+
# ```graphql
|
28
|
+
# enum UserType {
|
29
|
+
# Admin
|
30
|
+
# SupportUser
|
31
|
+
# }
|
32
|
+
# ```
|
33
|
+
def with_model(
|
34
|
+
klass = default_model_name.safe_constantize,
|
35
|
+
prefix: nil,
|
36
|
+
register: true,
|
37
|
+
scope: nil,
|
38
|
+
strip: /(^[^_a-zA-Z])|([^_a-zA-Z0-9]*)/,
|
39
|
+
value_method: :name
|
40
|
+
)
|
41
|
+
raise ArgumentError.new(<<~ERROR) if !klass
|
42
|
+
`::HQ::GraphQL::Enum.with_model {...}' had trouble automatically inferring the class name.
|
43
|
+
Avoid this by manually passing in the class name: `::HQ::GraphQL::Enum.with_model(#{default_model_name}) {...}`
|
44
|
+
ERROR
|
45
|
+
|
46
|
+
if register
|
47
|
+
::HQ::GraphQL.enums << klass
|
48
|
+
::HQ::GraphQL::Types.register(klass, self)
|
49
|
+
end
|
50
|
+
|
51
|
+
lazy_load do
|
52
|
+
records = scope ? klass.instance_exec(&scope) : klass.all
|
53
|
+
records.each do |record|
|
54
|
+
value "#{prefix}#{record.send(value_method).gsub(strip, "")}", value: record
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def lazy_load(&block)
|
60
|
+
@lazy_load ||= []
|
61
|
+
if block
|
62
|
+
::HQ::GraphQL.lazy_load(self)
|
63
|
+
@lazy_load << block
|
64
|
+
end
|
65
|
+
@lazy_load
|
66
|
+
end
|
67
|
+
|
68
|
+
def lazy_load!
|
69
|
+
lazy_load.shift.call while lazy_load.length > 0
|
70
|
+
@lazy_load = []
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_model_name
|
74
|
+
to_s.sub(/^((::)?\w+)::/, "")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
::GraphQL::Schema::Enum.extend ::HQ::GraphQL::Ext::EnumExtensions
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hq/graphql/ext/active_record_extensions"
|
4
|
+
require "hq/graphql/inputs"
|
5
|
+
require "hq/graphql/types"
|
6
|
+
|
7
|
+
module HQ
|
8
|
+
module GraphQL
|
9
|
+
module Ext
|
10
|
+
module InputObjectExtensions
|
11
|
+
def self.included(klass)
|
12
|
+
klass.include Scalars
|
13
|
+
klass.include InstanceMethods
|
14
|
+
klass.include ActiveRecordExtensions
|
15
|
+
klass.extend ActiveRecordExtensions
|
16
|
+
klass.extend ClassMethods
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
# Recursively format attributes so that they are compatible with `accepts_nested_attributes_for`
|
21
|
+
def format_nested_attributes
|
22
|
+
self.each.inject({}) do |formatted_attrs, (key, value) |
|
23
|
+
if self.class.nested_attributes.include?(key.to_s)
|
24
|
+
formatted_value =
|
25
|
+
if value.is_a?(Array)
|
26
|
+
value.map(&:format_nested_attributes)
|
27
|
+
elsif value
|
28
|
+
value.format_nested_attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
formatted_attrs[:"#{key}_attributes"] = formatted_value if formatted_value
|
32
|
+
elsif key.to_s == "x"
|
33
|
+
formatted_attrs[:X] = value
|
34
|
+
else
|
35
|
+
formatted_attrs[key] = value
|
36
|
+
end
|
37
|
+
formatted_attrs
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
#### Class Methods ####
|
44
|
+
def with_model(model_name, attributes: true, associations: false, enums: true, excluded_inputs: [])
|
45
|
+
self.model_name = model_name
|
46
|
+
self.auto_load_attributes = attributes
|
47
|
+
self.auto_load_associations = associations
|
48
|
+
self.auto_load_enums = enums
|
49
|
+
|
50
|
+
lazy_load do
|
51
|
+
excluded_inputs += ::HQ::GraphQL.excluded_inputs
|
52
|
+
|
53
|
+
model_columns.each do |column|
|
54
|
+
argument_from_column(column) unless excluded_inputs.include?(column.name.to_sym)
|
55
|
+
end
|
56
|
+
|
57
|
+
model_associations.each do |association|
|
58
|
+
argument_from_association(association) unless excluded_inputs.include?(association.name.to_sym)
|
59
|
+
end
|
60
|
+
|
61
|
+
argument :X, String, required: false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def nested_attributes
|
66
|
+
@nested_attributes ||= Set.new
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def argument_from_association(association)
|
72
|
+
is_enum = is_enum?(association)
|
73
|
+
input_or_type = is_enum ? ::HQ::GraphQL::Types[association.klass] : ::HQ::GraphQL::Inputs[association.klass]
|
74
|
+
name = association.name
|
75
|
+
return if argument_exists?(name)
|
76
|
+
|
77
|
+
case association.macro
|
78
|
+
when :has_many
|
79
|
+
argument name, [input_or_type], required: false
|
80
|
+
else
|
81
|
+
argument name, input_or_type, required: false
|
82
|
+
end
|
83
|
+
|
84
|
+
return if is_enum
|
85
|
+
|
86
|
+
if !model_klass.nested_attributes_options.key?(name.to_sym)
|
87
|
+
model_klass.accepts_nested_attributes_for name, allow_destroy: true
|
88
|
+
end
|
89
|
+
|
90
|
+
nested_attributes << name.to_s
|
91
|
+
rescue ::HQ::GraphQL::Inputs::Error
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def argument_from_column(column)
|
96
|
+
name = column.name
|
97
|
+
return if argument_exists?(name)
|
98
|
+
argument name, ::HQ::GraphQL::Types.type_from_column(column), required: false
|
99
|
+
end
|
100
|
+
|
101
|
+
def argument_exists?(name)
|
102
|
+
!!arguments[camelize(name)]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
::GraphQL::Schema::InputObject.include ::HQ::GraphQL::Ext::InputObjectExtensions
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HQ
|
4
|
+
module GraphQL
|
5
|
+
module Ext
|
6
|
+
module MutationExtensions
|
7
|
+
def self.included(klass)
|
8
|
+
klass.include Scalars
|
9
|
+
klass.include ActiveRecordExtensions
|
10
|
+
klass.singleton_class.prepend PrependMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module PrependMethods
|
14
|
+
def generate_payload_type
|
15
|
+
lazy_load!
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
::GraphQL::Schema::Mutation.include ::HQ::GraphQL::Ext::MutationExtensions
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hq/graphql/ext/active_record_extensions"
|
4
|
+
require "hq/graphql/field"
|
5
|
+
require "hq/graphql/field_extension/association_loader_extension"
|
6
|
+
require "hq/graphql/field_extension/paginated_arguments"
|
7
|
+
require "hq/graphql/field_extension/paginated_loader"
|
8
|
+
require "hq/graphql/object_association"
|
9
|
+
require "hq/graphql/types"
|
10
|
+
|
11
|
+
module HQ
|
12
|
+
module GraphQL
|
13
|
+
module Ext
|
14
|
+
module ObjectExtensions
|
15
|
+
def self.included(klass)
|
16
|
+
klass.include Scalars
|
17
|
+
klass.include ActiveRecordExtensions
|
18
|
+
klass.extend ObjectAssociation
|
19
|
+
klass.singleton_class.prepend PrependMethods
|
20
|
+
klass.field_class Field
|
21
|
+
end
|
22
|
+
|
23
|
+
module PrependMethods
|
24
|
+
def authorize_action(action)
|
25
|
+
self.authorized_action = action
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorized?(object, context)
|
29
|
+
super && ::HQ::GraphQL.authorized?(authorized_action, object, context)
|
30
|
+
end
|
31
|
+
|
32
|
+
def with_model(model_name, attributes: true, associations: true, auto_nil: true, enums: true)
|
33
|
+
self.model_name = model_name
|
34
|
+
self.auto_load_attributes = attributes
|
35
|
+
self.auto_load_associations = associations
|
36
|
+
self.auto_load_enums = enums
|
37
|
+
|
38
|
+
lazy_load do
|
39
|
+
model_columns.each do |column|
|
40
|
+
field_from_column(column, auto_nil: auto_nil)
|
41
|
+
end
|
42
|
+
|
43
|
+
model_associations.each do |association|
|
44
|
+
next if resource_reflections[association.name.to_s]
|
45
|
+
field_from_association(association, auto_nil: auto_nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
resource_reflections.values.each do |resource_reflection|
|
49
|
+
reflection = resource_reflection.reflection(model_klass)
|
50
|
+
next unless reflection
|
51
|
+
field_from_association(reflection, auto_nil: auto_nil, internal_association: true, &resource_reflection.block)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
attr_writer :authorized_action
|
58
|
+
|
59
|
+
def authorized_action
|
60
|
+
@authorized_action ||= :read
|
61
|
+
end
|
62
|
+
|
63
|
+
def field_from_association(association, auto_nil:, internal_association: false, &block)
|
64
|
+
association_klass = association.klass
|
65
|
+
name = association.name.to_s
|
66
|
+
return if field_exists?(name)
|
67
|
+
|
68
|
+
klass = model_klass
|
69
|
+
type = Types[association_klass]
|
70
|
+
|
71
|
+
case association.macro
|
72
|
+
when :has_many
|
73
|
+
field name, [type], null: false, klass: model_name do
|
74
|
+
if ::HQ::GraphQL.use_experimental_associations?
|
75
|
+
extension FieldExtension::PaginatedArguments, klass: association_klass
|
76
|
+
extension FieldExtension::PaginatedLoader, klass: klass, association: name, internal_association: internal_association
|
77
|
+
else
|
78
|
+
extension FieldExtension::AssociationLoaderExtension, klass: klass
|
79
|
+
end
|
80
|
+
instance_eval(&block) if block
|
81
|
+
end
|
82
|
+
when :has_one
|
83
|
+
field name, type, null: !auto_nil || !has_presence_validation?(association), klass: model_name do
|
84
|
+
extension FieldExtension::AssociationLoaderExtension, klass: klass
|
85
|
+
end
|
86
|
+
else
|
87
|
+
field name, type, null: !auto_nil || !association_required?(association), klass: model_name do
|
88
|
+
extension FieldExtension::AssociationLoaderExtension, klass: klass
|
89
|
+
end
|
90
|
+
end
|
91
|
+
rescue Types::Error
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def field_from_column(column, auto_nil:)
|
96
|
+
name = column.name
|
97
|
+
return if field_exists?(name)
|
98
|
+
|
99
|
+
field name, Types.type_from_column(column), null: !auto_nil || column.null
|
100
|
+
end
|
101
|
+
|
102
|
+
def field_exists?(name)
|
103
|
+
!!fields[camelize(name)]
|
104
|
+
end
|
105
|
+
|
106
|
+
def association_required?(association)
|
107
|
+
!association.options[:optional] || has_presence_validation?(association)
|
108
|
+
end
|
109
|
+
|
110
|
+
def has_presence_validation?(association)
|
111
|
+
model_klass.validators.any? do |validation|
|
112
|
+
next unless validation.class == ActiveRecord::Validations::PresenceValidator && !(validation.options.include?(:if) || validation.options.include?(:unless))
|
113
|
+
validation.attributes.any? { |a| a.to_s == association.name.to_s }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
::GraphQL::Schema::Object.include ::HQ::GraphQL::Ext::ObjectExtensions
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HQ
|
4
|
+
module GraphQL
|
5
|
+
module Ext
|
6
|
+
module SchemaExtensions
|
7
|
+
def self.prepended(klass)
|
8
|
+
klass.alias_method :add_type_and_traverse_without_types, :add_type_and_traverse
|
9
|
+
klass.alias_method :add_type_and_traverse, :add_type_and_traverse_with_types
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(*args, **options)
|
13
|
+
load_types!
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump_directory(directory = Rails.root.join("app/graphql"))
|
18
|
+
@dump_directory ||= directory
|
19
|
+
end
|
20
|
+
|
21
|
+
def dump_filename(filename = "#{self.name.underscore}.graphql")
|
22
|
+
@dump_filename ||= filename
|
23
|
+
end
|
24
|
+
|
25
|
+
def dump
|
26
|
+
load_types!
|
27
|
+
::FileUtils.mkdir_p(dump_directory)
|
28
|
+
::File.open(::File.join(dump_directory, dump_filename), "w") { |file| file.write(self.to_definition) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_types!
|
32
|
+
::HQ::GraphQL.load_types!
|
33
|
+
return if @add_type_and_traverse_with_types.blank?
|
34
|
+
while (args, options = @add_type_and_traverse_with_types.shift)
|
35
|
+
add_type_and_traverse_without_types(*args, **options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Defer adding types until first schema execution
|
40
|
+
# https://github.com/rmosolgo/graphql-ruby/blob/345ebb2e3833909963067d81e0e8378717b5bdbf/lib/graphql/schema.rb#L1792
|
41
|
+
def add_type_and_traverse_with_types(*args, **options)
|
42
|
+
@add_type_and_traverse_with_types ||= []
|
43
|
+
@add_type_and_traverse_with_types.push([args, options])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
::GraphQL::Schema.singleton_class.prepend ::HQ::GraphQL::Ext::SchemaExtensions
|
data/lib/hq/graphql/field.rb
CHANGED
@@ -17,6 +17,7 @@ module HQ
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def initialize(model, association_name, internal_association: false, limit: nil, offset: nil, scope: nil, sort_by: nil, sort_order: nil)
|
20
|
+
super()
|
20
21
|
@model = model
|
21
22
|
@association_name = association_name
|
22
23
|
@internal_association = internal_association
|
data/lib/hq/graphql/resource.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "hq/graphql/ext/input_object_extensions"
|
4
|
+
require "hq/graphql/ext/object_extensions"
|
3
5
|
require "hq/graphql/enum/sort_by"
|
4
6
|
require "hq/graphql/field_extension/paginated_arguments"
|
5
|
-
require "hq/graphql/input_object"
|
6
|
-
require "hq/graphql/object"
|
7
7
|
require "hq/graphql/resource/auto_mutation"
|
8
8
|
require "hq/graphql/scalars"
|
9
9
|
|
@@ -60,18 +60,21 @@ module HQ
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def nil_query_object
|
63
|
-
@nil_query_object ||= build_graphql_object(name: "#{graphql_name}Copy", auto_nil: false)
|
63
|
+
@nil_query_object ||= const_set(:NilQuery, build_graphql_object(name: "#{graphql_name}Copy", auto_nil: false))
|
64
64
|
end
|
65
65
|
|
66
66
|
def query_object
|
67
67
|
@query_object ||= begin
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
qo =
|
69
|
+
if @query_object_options
|
70
|
+
options, block = @query_object_options
|
71
|
+
@query_object_options = nil
|
72
|
+
build_graphql_object(**options, &block)
|
73
|
+
else
|
74
|
+
build_graphql_object
|
75
|
+
end
|
76
|
+
remove_const(:Query) if const_defined?(:Query, false)
|
77
|
+
const_set(:Query, qo)
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
@@ -79,6 +82,20 @@ module HQ
|
|
79
82
|
@sort_fields_enum || ::HQ::GraphQL::Enum::SortBy
|
80
83
|
end
|
81
84
|
|
85
|
+
def const_missing(constant_name)
|
86
|
+
constant_name = constant_name.to_sym
|
87
|
+
case constant_name
|
88
|
+
when :Query
|
89
|
+
query_object
|
90
|
+
when :NilQuery
|
91
|
+
nil_query_object
|
92
|
+
when :Input
|
93
|
+
input_klass
|
94
|
+
else
|
95
|
+
super
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
82
99
|
protected
|
83
100
|
|
84
101
|
def default_scope(&block)
|
@@ -108,14 +125,22 @@ module HQ
|
|
108
125
|
self.sort_fields_enum = fields
|
109
126
|
end
|
110
127
|
|
128
|
+
def excluded_inputs(*fields)
|
129
|
+
@excluded_inputs = fields
|
130
|
+
end
|
131
|
+
|
111
132
|
def def_root(field_name, is_array: false, null: true, &block)
|
112
133
|
resource = self
|
113
134
|
resolver = -> {
|
114
|
-
Class.new(::GraphQL::Schema::Resolver) do
|
135
|
+
klass = Class.new(::GraphQL::Schema::Resolver) do
|
115
136
|
type = is_array ? [resource.query_object] : resource.query_object
|
116
137
|
type type, null: null
|
117
138
|
class_eval(&block) if block
|
118
139
|
end
|
140
|
+
|
141
|
+
constant_name = "#{field_name.to_s.classify}Resolver"
|
142
|
+
resource.send(:remove_const, constant_name) if resource.const_defined?(constant_name, false)
|
143
|
+
resource.const_set(constant_name, klass)
|
119
144
|
}
|
120
145
|
::HQ::GraphQL.root_queries << {
|
121
146
|
field_name: field_name, resolver: resolver, model_name: model_name
|
@@ -168,7 +193,7 @@ module HQ
|
|
168
193
|
def build_graphql_object(name: graphql_name, **options, &block)
|
169
194
|
scoped_graphql_name = name
|
170
195
|
scoped_model_name = model_name
|
171
|
-
object_class = @query_class || ::HQ::GraphQL.default_object_class || ::
|
196
|
+
object_class = @query_class || ::HQ::GraphQL.default_object_class || ::GraphQL::Schema::Object
|
172
197
|
Class.new(object_class) do
|
173
198
|
graphql_name scoped_graphql_name
|
174
199
|
|
@@ -181,18 +206,24 @@ module HQ
|
|
181
206
|
def build_input_object(**options, &block)
|
182
207
|
scoped_graphql_name = graphql_name
|
183
208
|
scoped_model_name = model_name
|
184
|
-
|
209
|
+
scoped_excluded_inputs = @excluded_inputs || []
|
210
|
+
|
211
|
+
input_klass = Class.new(::GraphQL::Schema::InputObject) do
|
185
212
|
graphql_name "#{scoped_graphql_name}Input"
|
186
213
|
|
187
|
-
with_model scoped_model_name, **options
|
214
|
+
with_model scoped_model_name, excluded_inputs: scoped_excluded_inputs, **options
|
188
215
|
|
189
216
|
class_eval(&block) if block
|
190
217
|
end
|
218
|
+
|
219
|
+
remove_const(:Input) if const_defined?(:Input, false)
|
220
|
+
const_set(:Input, input_klass)
|
191
221
|
end
|
192
222
|
|
193
223
|
def sort_fields_enum=(fields)
|
194
224
|
@sort_fields_enum ||= Class.new(::HQ::GraphQL::Enum::SortBy).tap do |c|
|
195
225
|
c.graphql_name "#{graphql_name}Sort"
|
226
|
+
const_set(:Sort, c)
|
196
227
|
end
|
197
228
|
|
198
229
|
Array(fields).each do |field|
|