hq-graphql 2.1.12 → 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -9
  3. data/lib/hq/graphql.rb +17 -8
  4. data/lib/hq/graphql/association_loader.rb +1 -0
  5. data/lib/hq/graphql/comparator.rb +22 -21
  6. data/lib/hq/graphql/enum/filter_operation.rb +15 -0
  7. data/lib/hq/graphql/enum/sort_by.rb +8 -4
  8. data/lib/hq/graphql/enum/sort_order.rb +8 -4
  9. data/lib/hq/graphql/ext.rb +8 -0
  10. data/lib/hq/graphql/ext/active_record_extensions.rb +148 -0
  11. data/lib/hq/graphql/ext/enum_extensions.rb +81 -0
  12. data/lib/hq/graphql/ext/input_object_extensions.rb +110 -0
  13. data/lib/hq/graphql/ext/mutation_extensions.rb +24 -0
  14. data/lib/hq/graphql/ext/object_extensions.rb +122 -0
  15. data/lib/hq/graphql/ext/schema_extensions.rb +50 -0
  16. data/lib/hq/graphql/field.rb +1 -1
  17. data/lib/hq/graphql/filter_operations.rb +59 -0
  18. data/lib/hq/graphql/filters.rb +150 -0
  19. data/lib/hq/graphql/paginated_association_loader.rb +1 -0
  20. data/lib/hq/graphql/record_loader.rb +1 -0
  21. data/lib/hq/graphql/resource.rb +86 -15
  22. data/lib/hq/graphql/resource/auto_mutation.rb +8 -5
  23. data/lib/hq/graphql/root_mutation.rb +1 -1
  24. data/lib/hq/graphql/root_query.rb +3 -3
  25. data/lib/hq/graphql/scalars.rb +0 -2
  26. data/lib/hq/graphql/types.rb +1 -2
  27. data/lib/hq/graphql/types/uuid.rb +3 -5
  28. data/lib/hq/graphql/util.rb +13 -0
  29. data/lib/hq/graphql/version.rb +1 -1
  30. metadata +28 -38
  31. data/lib/hq/graphql/active_record_extensions.rb +0 -143
  32. data/lib/hq/graphql/enum.rb +0 -78
  33. data/lib/hq/graphql/input_object.rb +0 -104
  34. data/lib/hq/graphql/mutation.rb +0 -15
  35. data/lib/hq/graphql/object.rb +0 -120
  36. data/lib/hq/graphql/schema.rb +0 -22
  37. data/lib/hq/graphql/types/object.rb +0 -35
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HQ
4
+ module GraphQL
5
+ module Util
6
+ UUID_FORMAT = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/
7
+
8
+ def self.validate_uuid(value)
9
+ !value || !!value.to_s.match(UUID_FORMAT)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module HQ
4
4
  module GraphQL
5
- VERSION = "2.1.12"
5
+ VERSION = "2.2.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hq-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.12
4
+ version: 2.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Jones
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-19 00:00:00.000000000 Z
11
+ date: 2021-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.9.6
33
+ version: '1.12'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.9.6
40
+ version: '1.12'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: graphql-batch
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.6'
61
+ version: '1.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.6'
68
+ version: '1.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pg
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.1'
83
- - !ruby/object:Gem::Dependency
84
- name: sprockets
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "<"
88
- - !ruby/object:Gem::Version
89
- version: 4.0.0
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "<"
95
- - !ruby/object:Gem::Version
96
- version: 4.0.0
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: byebug
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -182,30 +168,30 @@ dependencies:
182
168
  name: rspec-rails
183
169
  requirement: !ruby/object:Gem::Requirement
184
170
  requirements:
185
- - - ">="
171
+ - - "~>"
186
172
  - !ruby/object:Gem::Version
187
- version: 4.0.0beta2
173
+ version: '4.0'
188
174
  type: :development
189
175
  prerelease: false
190
176
  version_requirements: !ruby/object:Gem::Requirement
191
177
  requirements:
192
- - - ">="
178
+ - - "~>"
193
179
  - !ruby/object:Gem::Version
194
- version: 4.0.0beta2
180
+ version: '4.0'
195
181
  - !ruby/object:Gem::Dependency
196
182
  name: rubocop
197
183
  requirement: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - "~>"
200
186
  - !ruby/object:Gem::Version
201
- version: '0.7'
187
+ version: '1.8'
202
188
  type: :development
203
189
  prerelease: false
204
190
  version_requirements: !ruby/object:Gem::Requirement
205
191
  requirements:
206
192
  - - "~>"
207
193
  - !ruby/object:Gem::Version
208
- version: '0.7'
194
+ version: '1.8'
209
195
  - !ruby/object:Gem::Dependency
210
196
  name: rubocop-performance
211
197
  requirement: !ruby/object:Gem::Requirement
@@ -246,22 +232,27 @@ files:
246
232
  - Rakefile
247
233
  - lib/hq-graphql.rb
248
234
  - lib/hq/graphql.rb
249
- - lib/hq/graphql/active_record_extensions.rb
250
235
  - lib/hq/graphql/association_loader.rb
251
236
  - lib/hq/graphql/comparator.rb
252
237
  - lib/hq/graphql/config.rb
253
238
  - lib/hq/graphql/engine.rb
254
- - lib/hq/graphql/enum.rb
239
+ - lib/hq/graphql/enum/filter_operation.rb
255
240
  - lib/hq/graphql/enum/sort_by.rb
256
241
  - lib/hq/graphql/enum/sort_order.rb
242
+ - lib/hq/graphql/ext.rb
243
+ - lib/hq/graphql/ext/active_record_extensions.rb
244
+ - lib/hq/graphql/ext/enum_extensions.rb
245
+ - lib/hq/graphql/ext/input_object_extensions.rb
246
+ - lib/hq/graphql/ext/mutation_extensions.rb
247
+ - lib/hq/graphql/ext/object_extensions.rb
248
+ - lib/hq/graphql/ext/schema_extensions.rb
257
249
  - lib/hq/graphql/field.rb
258
250
  - lib/hq/graphql/field_extension/association_loader_extension.rb
259
251
  - lib/hq/graphql/field_extension/paginated_arguments.rb
260
252
  - lib/hq/graphql/field_extension/paginated_loader.rb
261
- - lib/hq/graphql/input_object.rb
253
+ - lib/hq/graphql/filter_operations.rb
254
+ - lib/hq/graphql/filters.rb
262
255
  - lib/hq/graphql/inputs.rb
263
- - lib/hq/graphql/mutation.rb
264
- - lib/hq/graphql/object.rb
265
256
  - lib/hq/graphql/object_association.rb
266
257
  - lib/hq/graphql/paginated_association_loader.rb
267
258
  - lib/hq/graphql/record_loader.rb
@@ -270,22 +261,21 @@ files:
270
261
  - lib/hq/graphql/root_mutation.rb
271
262
  - lib/hq/graphql/root_query.rb
272
263
  - lib/hq/graphql/scalars.rb
273
- - lib/hq/graphql/schema.rb
274
264
  - lib/hq/graphql/types.rb
275
- - lib/hq/graphql/types/object.rb
276
265
  - lib/hq/graphql/types/uuid.rb
266
+ - lib/hq/graphql/util.rb
277
267
  - lib/hq/graphql/version.rb
278
268
  homepage: https://github.com/OneHQ/hq-graphql
279
269
  licenses:
280
270
  - MIT
281
271
  metadata: {}
282
- post_install_message:
272
+ post_install_message:
283
273
  rdoc_options: []
284
274
  require_paths:
285
275
  - lib
286
276
  required_ruby_version: !ruby/object:Gem::Requirement
287
277
  requirements:
288
- - - "~>"
278
+ - - ">="
289
279
  - !ruby/object:Gem::Version
290
280
  version: '2.6'
291
281
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -294,8 +284,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
284
  - !ruby/object:Gem::Version
295
285
  version: '0'
296
286
  requirements: []
297
- rubygems_version: 3.0.3
298
- signing_key:
287
+ rubygems_version: 3.2.3
288
+ signing_key:
299
289
  specification_version: 4
300
290
  summary: OneHQ GraphQL Library
301
291
  test_files: []
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module HQ
4
- module GraphQL
5
- module ActiveRecordExtensions
6
- class Error < StandardError
7
- MISSING_MODEL_MSG = "Your GraphQL object must be connected to a model: `::HQ::GraphQL::Object.with_model 'User'`"
8
- MISSING_ATTR_MSG = "Can't find attr %{model}.%{attr}'`"
9
- MISSING_ASSOC_MSG = "Can't find association %{model}.%{assoc}'`"
10
- end
11
-
12
- def self.included(klass)
13
- klass.extend(ClassMethods)
14
- end
15
-
16
- module ClassMethods
17
- attr_accessor :model_name,
18
- :authorize_action,
19
- :auto_load_attributes,
20
- :auto_load_associations,
21
- :auto_load_enums
22
-
23
- def lazy_load(&block)
24
- @lazy_load ||= []
25
- @lazy_load << block if block
26
- @lazy_load
27
- end
28
-
29
- def lazy_load!
30
- lazy_load.each(&:call)
31
- @lazy_load = []
32
- end
33
-
34
- def model_columns
35
- model_columns =
36
- if auto_load_attributes
37
- model_klass.columns
38
- else
39
- added_attributes.map { |attr| column_from_model(attr) }
40
- end
41
-
42
- # validate removed_attributes exist
43
- removed_attributes.each { |attr| column_from_model(attr) }
44
-
45
- model_columns.reject { |c| removed_attributes.include?(c.name.to_sym) }.sort_by(&:name)
46
- end
47
-
48
- def model_associations
49
- model_associations = []
50
- enums = model_klass.reflect_on_all_associations.select { |a| is_enum?(a) }
51
- associatons = model_klass.reflect_on_all_associations - enums
52
-
53
- if auto_load_enums
54
- model_associations.concat(enums)
55
- end
56
-
57
- if auto_load_associations
58
- model_associations.concat(associatons)
59
- end
60
-
61
- model_associations.concat(added_associations.map { |association| association_from_model(association) }).uniq
62
-
63
- # validate removed_associations exist
64
- removed_associations.each { |association| association_from_model(association) }
65
-
66
- model_associations.reject { |a| removed_associations.include?(a.name.to_sym) }.sort_by(&:name)
67
- end
68
-
69
- private
70
-
71
- def add_attributes(*attrs)
72
- validate_model!
73
- added_attributes.concat attrs.map(&:to_sym)
74
- end
75
- alias_method :add_attribute, :add_attributes
76
- alias_method :add_attrs, :add_attributes
77
- alias_method :add_attr, :add_attributes
78
-
79
- def remove_attributes(*attrs)
80
- validate_model!
81
- removed_attributes.concat attrs.map(&:to_sym)
82
- end
83
- alias_method :remove_attribute, :remove_attributes
84
- alias_method :remove_attrs, :remove_attributes
85
- alias_method :remove_attr, :remove_attributes
86
-
87
- def add_associations(*associations)
88
- validate_model!
89
- added_associations.concat associations.map(&:to_sym)
90
- end
91
- alias_method :add_association, :add_associations
92
-
93
- def remove_associations(*associations)
94
- validate_model!
95
- removed_associations.concat associations.map(&:to_sym)
96
- end
97
- alias_method :remove_association, :remove_associations
98
-
99
- def model_klass
100
- @model_klass ||= model_name.constantize
101
- end
102
-
103
- def column_from_model(attr)
104
- model_klass.columns_hash[attr.to_s] || raise(Error, Error::MISSING_ATTR_MSG % { model: model_name, attr: attr })
105
- end
106
-
107
- def association_from_model(association)
108
- model_klass.reflect_on_association(association) || raise(Error, Error::MISSING_ASSOC_MSG % { model: model_name, assoc: association })
109
- end
110
-
111
- def added_attributes
112
- @added_attributes ||= []
113
- end
114
-
115
- def removed_attributes
116
- @removed_attributes ||= []
117
- end
118
-
119
- def added_associations
120
- @added_associations ||= []
121
- end
122
-
123
- def removed_associations
124
- @removed_associations ||= []
125
- end
126
-
127
- def camelize(name)
128
- name.to_s.camelize(:lower)
129
- end
130
-
131
- def is_enum?(association)
132
- ::HQ::GraphQL.enums.include?(association.klass)
133
- end
134
-
135
- def validate_model!
136
- lazy_load do
137
- model_name || raise(Error, Error::MISSING_MODEL_MSG)
138
- end
139
- end
140
- end
141
- end
142
- end
143
- end
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hq/graphql/types"
4
-
5
- module HQ::GraphQL
6
- class Enum < ::GraphQL::Schema::Enum
7
- ## Auto generate enums from the database using ActiveRecord
8
- # This comes in handy when we have constants that we want represented as enums.
9
- #
10
- # == Example
11
- # Let's assume we're saving data into a user types table
12
- # # select * from user_types;
13
- # id | name
14
- # --- +-------------
15
- # 1 | Admin
16
- # 2 | Support User
17
- # (2 rows)
18
- #
19
- # ```ruby
20
- # class Enums::UserType < ::HQ::GraphQL::Enum
21
- # with_model
22
- # end
23
- # ```
24
- #
25
- # Creates the following enum:
26
- # ```graphql
27
- # enum UserType {
28
- # Admin
29
- # SupportUser
30
- # }
31
- # ```
32
- def self.with_model(
33
- klass = default_model_name.safe_constantize,
34
- prefix: nil,
35
- register: true,
36
- scope: nil,
37
- strip: /(^[^_a-zA-Z])|([^_a-zA-Z0-9]*)/,
38
- value_method: :name
39
- )
40
- raise ArgumentError.new(<<~ERROR) if !klass
41
- `::HQ::GraphQL::Enum.with_model {...}' had trouble automatically inferring the class name.
42
- Avoid this by manually passing in the class name: `::HQ::GraphQL::Enum.with_model(#{default_model_name}) {...}`
43
- ERROR
44
-
45
- if register
46
- ::HQ::GraphQL.enums << klass
47
- ::HQ::GraphQL::Types.register(klass, self)
48
- end
49
-
50
- lazy_load do
51
- records = scope ? klass.instance_exec(&scope) : klass.all
52
- records.each do |record|
53
- value "#{prefix}#{record.send(value_method).gsub(strip, "")}", value: record
54
- end
55
- end
56
- end
57
-
58
- def self.lazy_load(&block)
59
- @lazy_load ||= []
60
- @lazy_load << block if block
61
- @lazy_load
62
- end
63
-
64
- def self.lazy_load!
65
- lazy_load.map(&:call)
66
- @lazy_load = []
67
- end
68
-
69
- def self.to_graphql
70
- lazy_load!
71
- super
72
- end
73
-
74
- def self.default_model_name
75
- to_s.sub(/^((::)?\w+)::/, "")
76
- end
77
- end
78
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hq/graphql/active_record_extensions"
4
- require "hq/graphql/inputs"
5
- require "hq/graphql/types"
6
-
7
- module HQ
8
- module GraphQL
9
- class InputObject < ::GraphQL::Schema::InputObject
10
- include Scalars
11
- include ::HQ::GraphQL::ActiveRecordExtensions
12
-
13
- # Recursively format attributes so that they are compatible with `accepts_nested_attributes_for`
14
- def format_nested_attributes
15
- self.each.inject({}) do |formatted_attrs, (key, value) |
16
- if self.class.nested_attributes.include?(key.to_s)
17
- formatted_value =
18
- if value.is_a?(Array)
19
- value.map(&:format_nested_attributes)
20
- elsif value
21
- value.format_nested_attributes
22
- end
23
-
24
- formatted_attrs[:"#{key}_attributes"] = formatted_value if formatted_value
25
- elsif key.to_s == "x"
26
- formatted_attrs[:X] = value
27
- else
28
- formatted_attrs[key] = value
29
- end
30
- formatted_attrs
31
- end
32
- end
33
-
34
- #### Class Methods ####
35
- def self.with_model(model_name, attributes: true, associations: false, enums: true, excluded_inputs: [])
36
- self.model_name = model_name
37
- self.auto_load_attributes = attributes
38
- self.auto_load_associations = associations
39
- self.auto_load_enums = enums
40
-
41
- lazy_load do
42
- excluded_inputs += ::HQ::GraphQL.excluded_inputs
43
-
44
- model_columns.each do |column|
45
- argument_from_column(column) unless excluded_inputs.include?(column.name.to_sym)
46
- end
47
-
48
- model_associations.each do |association|
49
- argument_from_association(association) unless excluded_inputs.include?(association.name.to_sym)
50
- end
51
-
52
- argument :X, String, required: false
53
- end
54
- end
55
-
56
- def self.nested_attributes
57
- @nested_attributes ||= Set.new
58
- end
59
-
60
- def self.to_graphql
61
- lazy_load!
62
- super
63
- end
64
-
65
- class << self
66
- private
67
-
68
- def argument_from_association(association)
69
- is_enum = is_enum?(association)
70
- input_or_type = is_enum ? ::HQ::GraphQL::Types[association.klass] : ::HQ::GraphQL::Inputs[association.klass]
71
- name = association.name
72
- return if argument_exists?(name)
73
-
74
- case association.macro
75
- when :has_many
76
- argument name, [input_or_type], required: false
77
- else
78
- argument name, input_or_type, required: false
79
- end
80
-
81
- return if is_enum
82
-
83
- if !model_klass.nested_attributes_options.key?(name.to_sym)
84
- model_klass.accepts_nested_attributes_for name, allow_destroy: true
85
- end
86
-
87
- nested_attributes << name.to_s
88
- rescue ::HQ::GraphQL::Inputs::Error
89
- nil
90
- end
91
-
92
- def argument_from_column(column)
93
- name = column.name
94
- return if argument_exists?(name)
95
- argument name, ::HQ::GraphQL::Types.type_from_column(column), required: false
96
- end
97
-
98
- def argument_exists?(name)
99
- !!arguments[camelize(name)]
100
- end
101
- end
102
- end
103
- end
104
- end