hq-graphql 2.1.12 → 2.2.3

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 (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