graphiti 1.2.16 → 1.3.9

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +96 -0
  3. data/.standard.yml +4 -4
  4. data/Appraisals +23 -17
  5. data/CHANGELOG.md +7 -1
  6. data/Guardfile +5 -5
  7. data/deprecated_generators/graphiti/generator_mixin.rb +1 -0
  8. data/deprecated_generators/graphiti/resource_generator.rb +1 -1
  9. data/gemfiles/{rails_5.gemfile → rails_5_2.gemfile} +2 -2
  10. data/gemfiles/{rails_5_graphiti_rails.gemfile → rails_5_2_graphiti_rails.gemfile} +3 -4
  11. data/gemfiles/rails_6.gemfile +1 -1
  12. data/gemfiles/rails_6_graphiti_rails.gemfile +2 -3
  13. data/gemfiles/{rails_4.gemfile → rails_7.gemfile} +2 -2
  14. data/gemfiles/rails_7_graphiti_rails.gemfile +19 -0
  15. data/graphiti.gemspec +16 -16
  16. data/lib/graphiti/adapters/abstract.rb +20 -5
  17. data/lib/graphiti/adapters/active_record/belongs_to_sideload.rb +1 -1
  18. data/lib/graphiti/adapters/active_record/has_many_sideload.rb +1 -1
  19. data/lib/graphiti/adapters/active_record/has_one_sideload.rb +1 -1
  20. data/lib/graphiti/adapters/active_record/{inferrence.rb → inference.rb} +2 -2
  21. data/lib/graphiti/adapters/active_record/many_to_many_sideload.rb +19 -0
  22. data/lib/graphiti/adapters/active_record.rb +119 -74
  23. data/lib/graphiti/adapters/graphiti_api.rb +1 -1
  24. data/lib/graphiti/adapters/null.rb +1 -1
  25. data/lib/graphiti/adapters/persistence/associations.rb +78 -0
  26. data/lib/graphiti/configuration.rb +3 -1
  27. data/lib/graphiti/debugger.rb +12 -8
  28. data/lib/graphiti/delegates/pagination.rb +47 -13
  29. data/lib/graphiti/deserializer.rb +3 -3
  30. data/lib/graphiti/errors.rb +109 -15
  31. data/lib/graphiti/extensions/extra_attribute.rb +4 -4
  32. data/lib/graphiti/extensions/temp_id.rb +1 -1
  33. data/lib/graphiti/filter_operators.rb +0 -1
  34. data/lib/graphiti/hash_renderer.rb +198 -21
  35. data/lib/graphiti/query.rb +105 -73
  36. data/lib/graphiti/railtie.rb +5 -5
  37. data/lib/graphiti/renderer.rb +19 -1
  38. data/lib/graphiti/request_validator.rb +10 -10
  39. data/lib/graphiti/request_validators/update_validator.rb +4 -5
  40. data/lib/graphiti/request_validators/validator.rb +38 -24
  41. data/lib/graphiti/resource/configuration.rb +35 -7
  42. data/lib/graphiti/resource/dsl.rb +34 -8
  43. data/lib/graphiti/resource/interface.rb +13 -3
  44. data/lib/graphiti/resource/links.rb +3 -3
  45. data/lib/graphiti/resource/persistence.rb +2 -1
  46. data/lib/graphiti/resource/polymorphism.rb +8 -2
  47. data/lib/graphiti/resource/remote.rb +2 -2
  48. data/lib/graphiti/resource/sideloading.rb +4 -4
  49. data/lib/graphiti/resource.rb +12 -1
  50. data/lib/graphiti/resource_proxy.rb +23 -3
  51. data/lib/graphiti/runner.rb +5 -5
  52. data/lib/graphiti/schema.rb +36 -11
  53. data/lib/graphiti/schema_diff.rb +44 -4
  54. data/lib/graphiti/scope.rb +8 -10
  55. data/lib/graphiti/scoping/base.rb +3 -3
  56. data/lib/graphiti/scoping/filter.rb +36 -15
  57. data/lib/graphiti/scoping/filter_group_validator.rb +78 -0
  58. data/lib/graphiti/scoping/paginate.rb +47 -3
  59. data/lib/graphiti/scoping/sort.rb +5 -7
  60. data/lib/graphiti/serializer.rb +49 -7
  61. data/lib/graphiti/sideload/belongs_to.rb +1 -1
  62. data/lib/graphiti/sideload/has_many.rb +19 -1
  63. data/lib/graphiti/sideload/many_to_many.rb +11 -4
  64. data/lib/graphiti/sideload/polymorphic_belongs_to.rb +3 -4
  65. data/lib/graphiti/sideload.rb +47 -23
  66. data/lib/graphiti/stats/dsl.rb +0 -1
  67. data/lib/graphiti/stats/payload.rb +12 -9
  68. data/lib/graphiti/types.rb +15 -15
  69. data/lib/graphiti/util/attribute_check.rb +1 -1
  70. data/lib/graphiti/util/class.rb +6 -0
  71. data/lib/graphiti/util/link.rb +10 -2
  72. data/lib/graphiti/util/persistence.rb +21 -78
  73. data/lib/graphiti/util/relationship_payload.rb +4 -4
  74. data/lib/graphiti/util/remote_params.rb +9 -4
  75. data/lib/graphiti/util/remote_serializer.rb +1 -0
  76. data/lib/graphiti/util/serializer_attributes.rb +41 -11
  77. data/lib/graphiti/util/simple_errors.rb +4 -4
  78. data/lib/graphiti/util/transaction_hooks_recorder.rb +1 -1
  79. data/lib/graphiti/version.rb +1 -1
  80. data/lib/graphiti.rb +6 -3
  81. metadata +46 -37
  82. data/.travis.yml +0 -59
@@ -15,10 +15,10 @@ module Graphiti
15
15
  # }
16
16
  class Payload
17
17
  def initialize(resource, query, scope, data)
18
- @resource = resource
19
- @query = query
20
- @scope = scope
21
- @data = data
18
+ @resource = resource
19
+ @query = query
20
+ @scope = scope
21
+ @data = data
22
22
  end
23
23
 
24
24
  # Generate the payload for +{ meta: { stats: { ... } } }+
@@ -31,16 +31,19 @@ module Graphiti
31
31
  stats[name] = {}
32
32
 
33
33
  each_calculation(name, calculation) do |calc, function|
34
- args = [@scope, name]
35
- args << @resource.context if function.arity >= 3
36
- args << @data if function.arity == 4
37
-
38
- stats[name][calc] = function.call(*args)
34
+ stats[name][calc] = calculate_stat(name, function)
39
35
  end
40
36
  end
41
37
  end
42
38
  end
43
39
 
40
+ def calculate_stat(name, function)
41
+ args = [@scope, name]
42
+ args << @resource.context if function.arity >= 3
43
+ args << @data if function.arity == 4
44
+ function.call(*args)
45
+ end
46
+
44
47
  private
45
48
 
46
49
  def each_calculation(name, calculations)
@@ -93,14 +93,14 @@ module Graphiti
93
93
  read: Dry::Types["coercible.string"],
94
94
  write: Dry::Types["coercible.integer"],
95
95
  kind: "scalar",
96
- description: "Base Type. Query/persist as integer, render as string.",
96
+ description: "Base Type. Query/persist as integer, render as string."
97
97
  },
98
98
  uuid: {
99
99
  params: Dry::Types["coercible.string"],
100
100
  read: Dry::Types["coercible.string"],
101
101
  write: Dry::Types["coercible.string"],
102
102
  kind: "scalar",
103
- description: "Base Type. Like a normal string, but by default only eq/!eq and case-sensitive.",
103
+ description: "Base Type. Like a normal string, but by default only eq/!eq and case-sensitive."
104
104
  },
105
105
  string_enum: {
106
106
  canonical_name: :enum,
@@ -108,7 +108,7 @@ module Graphiti
108
108
  read: Dry::Types["coercible.string"],
109
109
  write: Dry::Types["coercible.string"],
110
110
  kind: "scalar",
111
- description: "String enum type. Like a normal string, but only eq/!eq and case-sensitive. Limited to only the allowed values.",
111
+ description: "String enum type. Like a normal string, but only eq/!eq and case-sensitive. Limited to only the allowed values."
112
112
  },
113
113
  integer_enum: {
114
114
  canonical_name: :enum,
@@ -116,71 +116,71 @@ module Graphiti
116
116
  read: Dry::Types["coercible.integer"],
117
117
  write: Dry::Types["coercible.integer"],
118
118
  kind: "scalar",
119
- description: "Integer enum type. Like a normal integer, but only eq/!eq filters. Limited to only the allowed values.",
119
+ description: "Integer enum type. Like a normal integer, but only eq/!eq filters. Limited to only the allowed values."
120
120
  },
121
121
  string: {
122
122
  params: Dry::Types["coercible.string"],
123
123
  read: Dry::Types["coercible.string"],
124
124
  write: Dry::Types["coercible.string"],
125
125
  kind: "scalar",
126
- description: "Base Type.",
126
+ description: "Base Type."
127
127
  },
128
128
  integer: {
129
129
  params: PresentInteger,
130
130
  read: Integer,
131
131
  write: Integer,
132
132
  kind: "scalar",
133
- description: "Base Type.",
133
+ description: "Base Type."
134
134
  },
135
135
  big_decimal: {
136
136
  params: ParamDecimal,
137
137
  read: Dry::Types["json.decimal"],
138
138
  write: Dry::Types["json.decimal"],
139
139
  kind: "scalar",
140
- description: "Base Type.",
140
+ description: "Base Type."
141
141
  },
142
142
  float: {
143
143
  params: Dry::Types["coercible.float"],
144
144
  read: Float,
145
145
  write: Float,
146
146
  kind: "scalar",
147
- description: "Base Type.",
147
+ description: "Base Type."
148
148
  },
149
149
  boolean: {
150
150
  params: PresentBool,
151
151
  read: Bool,
152
152
  write: Bool,
153
153
  kind: "scalar",
154
- description: "Base Type.",
154
+ description: "Base Type."
155
155
  },
156
156
  date: {
157
157
  params: PresentDate,
158
158
  read: Date,
159
159
  write: Date,
160
160
  kind: "scalar",
161
- description: "Base Type.",
161
+ description: "Base Type."
162
162
  },
163
163
  datetime: {
164
164
  params: PresentParamsDateTime,
165
165
  read: ReadDateTime,
166
166
  write: WriteDateTime,
167
167
  kind: "scalar",
168
- description: "Base Type.",
168
+ description: "Base Type."
169
169
  },
170
170
  hash: {
171
171
  params: PresentParamsHash,
172
172
  read: Dry::Types["strict.hash"],
173
173
  write: Dry::Types["strict.hash"],
174
174
  kind: "record",
175
- description: "Base Type.",
175
+ description: "Base Type."
176
176
  },
177
177
  array: {
178
178
  params: Dry::Types["strict.array"],
179
179
  read: Dry::Types["strict.array"],
180
180
  write: Dry::Types["strict.array"],
181
181
  kind: "array",
182
- description: "Base Type.",
183
- },
182
+ description: "Base Type."
183
+ }
184
184
  }
185
185
 
186
186
  hash.each_pair do |k, v|
@@ -198,7 +198,7 @@ module Graphiti
198
198
  test: Dry::Types["strict.array"].of(map[:test]),
199
199
  write: Dry::Types["strict.array"].of(map[:write]),
200
200
  kind: "array",
201
- description: "Base Type.",
201
+ description: "Base Type."
202
202
  }
203
203
  end
204
204
  hash.merge!(arrays)
@@ -44,7 +44,7 @@ module Graphiti
44
44
  Graphiti::Errors::UnknownAttribute
45
45
 
46
46
  if raise_error?(opts[:exists])
47
- raise error_class.new(resource, name, flag, opts)
47
+ raise error_class.new(resource, name, flag, **opts)
48
48
  else
49
49
  false
50
50
  end
@@ -20,6 +20,12 @@ module Graphiti
20
20
  split = namespace.split("::")
21
21
  split[0, split.length - 1].join("::")
22
22
  end
23
+
24
+ def self.graphql_type_name(name)
25
+ name.gsub("Resource", "")
26
+ .gsub("::", "") # remove modules
27
+ .gsub(".", "__") # remove remote resource .
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -60,10 +60,14 @@ module Graphiti
60
60
  def params
61
61
  @params ||= {}.tap do |params|
62
62
  if @sideload.type != :belongs_to || @sideload.remote?
63
- params[:filter] = @sideload.base_filter([@model])
63
+ params[:filter] = @sideload.link_filter([@model])
64
64
  end
65
65
 
66
- @sideload.params_proc&.call(params, [@model])
66
+ if (extra_fields = @sideload.link_extra_fields)
67
+ params[:extra_fields] ||= extra_fields
68
+ end
69
+
70
+ @sideload.params_proc&.call(params, [@model], context)
67
71
  end
68
72
  end
69
73
 
@@ -75,6 +79,10 @@ module Graphiti
75
79
  end
76
80
  path
77
81
  end
82
+
83
+ def context
84
+ Graphiti.context[:object]
85
+ end
78
86
  end
79
87
  end
80
88
  end
@@ -8,12 +8,13 @@ class Graphiti::Util::Persistence
8
8
  # @param [Model] caller_model The persisted parent object in the request graph
9
9
  # @param [Symbol] foreign_key Attribute assigned by parent object in graph
10
10
  def initialize(resource, meta, attributes, relationships, caller_model, foreign_key = nil)
11
- @resource = resource
12
- @meta = meta
13
- @attributes = attributes
11
+ @resource = resource
12
+ @meta = meta
13
+ @attributes = attributes
14
14
  @relationships = relationships
15
- @caller_model = caller_model
16
- @foreign_key = foreign_key
15
+ @caller_model = caller_model
16
+ @foreign_key = foreign_key
17
+ @adapter = @resource.adapter
17
18
 
18
19
  # Find the correct child resource for a given jsonapi type
19
20
  if (meta_type = @meta[:type].try(:to_sym))
@@ -43,18 +44,16 @@ class Graphiti::Util::Persistence
43
44
  #
44
45
  # @return a model instance
45
46
  def run
46
- parents = process_belongs_to(@relationships)
47
- update_foreign_key_for_parents(parents)
47
+ attributes = @adapter.persistence_attributes(self, @attributes)
48
48
 
49
- persisted = persist_object(@meta[:method], @attributes)
49
+ parents = @adapter.process_belongs_to(self, attributes)
50
+ persisted = persist_object(@meta[:method], attributes)
50
51
  @resource.decorate_record(persisted)
51
52
  assign_temp_id(persisted, @meta[:temp_id])
52
53
 
53
54
  associate_parents(persisted, parents)
54
55
 
55
- children = process_has_many(@relationships, persisted) { |x|
56
- update_foreign_key(persisted, x[:attributes], x)
57
- }
56
+ children = @adapter.process_has_many(self, persisted)
58
57
 
59
58
  associate_children(persisted, children) unless @meta[:method] == :destroy
60
59
 
@@ -69,43 +68,21 @@ class Graphiti::Util::Persistence
69
68
  persisted
70
69
  end
71
70
 
72
- private
73
-
74
- def add_hook(prc, lifecycle_event)
75
- ::Graphiti::Util::TransactionHooksRecorder.add(prc, lifecycle_event)
76
- end
77
-
78
- # The child's attributes should be modified to nil-out the
79
- # foreign_key when the parent is being destroyed or disassociated
80
- #
81
- # This is not the case for HABTM, whose "foreign key" is a join table
82
- def update_foreign_key(parent_object, attrs, x)
83
- return if x[:sideload].type == :many_to_many
71
+ def iterate(only: [], except: [])
72
+ opts = {
73
+ resource: @resource,
74
+ relationships: @relationships
75
+ }.merge(only: only, except: except)
84
76
 
85
- if [:destroy, :disassociate].include?(x[:meta][:method])
86
- if x[:sideload].polymorphic_has_one? || x[:sideload].polymorphic_has_many?
87
- attrs[:"#{x[:sideload].polymorphic_as}_type"] = nil
88
- end
89
- attrs[x[:foreign_key]] = nil
90
- update_foreign_type(attrs, x, null: true) if x[:is_polymorphic]
91
- else
92
- if x[:sideload].polymorphic_has_one? || x[:sideload].polymorphic_has_many?
93
- attrs[:"#{x[:sideload].polymorphic_as}_type"] = parent_object.class.name
94
- end
95
- attrs[x[:foreign_key]] = parent_object.send(x[:primary_key])
96
- update_foreign_type(attrs, x) if x[:is_polymorphic]
77
+ Graphiti::Util::RelationshipPayload.iterate(**opts) do |x|
78
+ yield x
97
79
  end
98
80
  end
99
81
 
100
- def update_foreign_type(attrs, x, null: false)
101
- grouping_field = x[:sideload].parent.grouper.field_name
102
- attrs[grouping_field] = null ? nil : x[:sideload].group_name
103
- end
82
+ private
104
83
 
105
- def update_foreign_key_for_parents(parents)
106
- parents.each do |x|
107
- update_foreign_key(x[:object], @attributes, x)
108
- end
84
+ def add_hook(prc, lifecycle_event)
85
+ ::Graphiti::Util::TransactionHooksRecorder.add(prc, lifecycle_event)
109
86
  end
110
87
 
111
88
  def associate_parents(object, parents)
@@ -161,29 +138,6 @@ class Graphiti::Util::Persistence
161
138
  end
162
139
  end
163
140
 
164
- def process_has_many(relationships, caller_model)
165
- [].tap do |processed|
166
- iterate(except: [:polymorphic_belongs_to, :belongs_to]) do |x|
167
- yield x
168
-
169
- x[:object] = x[:resource]
170
- .persist_with_relationships(x[:meta], x[:attributes], x[:relationships], caller_model, x[:foreign_key])
171
-
172
- processed << x
173
- end
174
- end
175
- end
176
-
177
- def process_belongs_to(relationships)
178
- [].tap do |processed|
179
- iterate(only: [:polymorphic_belongs_to, :belongs_to]) do |x|
180
- x[:object] = x[:resource]
181
- .persist_with_relationships(x[:meta], x[:attributes], x[:relationships])
182
- processed << x
183
- end
184
- end
185
- end
186
-
187
141
  def post_process(caller_model, processed)
188
142
  groups = processed.group_by { |x| x[:meta][:method] }
189
143
  groups.each_pair do |method, group|
@@ -199,24 +153,13 @@ class Graphiti::Util::Persistence
199
153
  object.instance_variable_set(:@_jsonapi_temp_id, temp_id)
200
154
  end
201
155
 
202
- def iterate(only: [], except: [])
203
- opts = {
204
- resource: @resource,
205
- relationships: @relationships,
206
- }.merge(only: only, except: except)
207
-
208
- Graphiti::Util::RelationshipPayload.iterate(opts) do |x|
209
- yield x
210
- end
211
- end
212
-
213
156
  def metadata
214
157
  {
215
158
  method: @meta[:method],
216
159
  temp_id: @meta[:temp_id],
217
160
  caller_model: @caller_model,
218
161
  attributes: @attributes,
219
- relationships: @relationships,
162
+ relationships: @relationships
220
163
  }
221
164
  end
222
165
 
@@ -14,9 +14,9 @@ module Graphiti
14
14
 
15
15
  def initialize(resource, payload, only: [], except: [])
16
16
  @resource = resource
17
- @payload = payload
18
- @only = only
19
- @except = except
17
+ @payload = payload
18
+ @only = only
19
+ @except = except
20
20
  end
21
21
 
22
22
  def iterate
@@ -67,7 +67,7 @@ module Graphiti
67
67
  foreign_key: sideload.foreign_key,
68
68
  attributes: relationship_payload[:attributes],
69
69
  meta: relationship_payload[:meta],
70
- relationships: relationship_payload[:relationships],
70
+ relationships: relationship_payload[:relationships]
71
71
  }
72
72
  end
73
73
  end
@@ -2,13 +2,14 @@
2
2
  module Graphiti
3
3
  module Util
4
4
  class RemoteParams
5
- def self.generate(resource, query)
6
- new(resource, query).generate
5
+ def self.generate(resource, query, foreign_key)
6
+ new(resource, query, foreign_key).generate
7
7
  end
8
8
 
9
- def initialize(resource, query)
9
+ def initialize(resource, query, foreign_key)
10
10
  @resource = resource
11
11
  @query = query
12
+ @foreign_key = foreign_key
12
13
  @sorts = []
13
14
  @filters = {}
14
15
  @fields = {}
@@ -97,7 +98,11 @@ module Graphiti
97
98
  return unless fields
98
99
 
99
100
  fields.each_pair do |type, attrs|
100
- @fields[type] = attrs.join(",")
101
+ all_attrs = attrs
102
+ if @foreign_key
103
+ all_attrs |= [@foreign_key]
104
+ end
105
+ @fields[type] = all_attrs.join(",")
101
106
  end
102
107
  end
103
108
 
@@ -44,6 +44,7 @@ module Graphiti
44
44
  model.delete_field(:_relationships)
45
45
  # If this isn't set, Array(resources) will return []
46
46
  # This is important, because jsonapi-serializable makes this call
47
+ # To see the test failure, remote resource position > department
47
48
  model.instance_variable_set(:@__graphiti_resource, 1)
48
49
  model.instance_variable_set(:@__graphiti_serializer, serializer)
49
50
  end
@@ -12,26 +12,48 @@ module Graphiti
12
12
  def apply
13
13
  return unless readable?
14
14
 
15
+ remove_guard if previously_guarded?
16
+
15
17
  if @name == :id
16
18
  @serializer.id(&proc)
17
- elsif @attr[:proc]
18
- @serializer.send(_method, @name, serializer_options, &proc)
19
- elsif @serializer.attribute_blocks[@name].nil?
19
+ elsif @attr[:proc] ||
20
+ !previously_applied? ||
21
+ previously_applied_via_resource?
20
22
  @serializer.send(_method, @name, serializer_options, &proc)
21
- else
22
- unless @serializer.send(applied_method).include?(@name)
23
- inner = @serializer.attribute_blocks.delete(@name)
24
- wrapped = wrap_proc(inner)
25
- @serializer.send(_method, @name, serializer_options, &wrapped)
26
- end
23
+ else # Previously applied via explicit serializer, so wrap it
24
+ inner = @serializer.attribute_blocks.delete(@name)
25
+ wrapped = wrap_proc(inner)
26
+ @serializer.send(_method, @name, serializer_options, &wrapped)
27
27
  end
28
28
 
29
29
  existing = @serializer.send(applied_method)
30
30
  @serializer.send(:"#{applied_method}=", [@name] | existing)
31
+
32
+ @serializer.meta do
33
+ if !!@resource.try(:cursor_paginatable?) && !Graphiti.context[:graphql]
34
+ {cursor: cursor}
35
+ end
36
+ end
31
37
  end
32
38
 
33
39
  private
34
40
 
41
+ def previously_applied?
42
+ @serializer.attribute_blocks[@name].present?
43
+ end
44
+
45
+ def previously_applied_via_resource?
46
+ @serializer.send(applied_method).include?(@name)
47
+ end
48
+
49
+ def previously_guarded?
50
+ @serializer.field_condition_blocks[@name]
51
+ end
52
+
53
+ def remove_guard
54
+ @serializer.field_condition_blocks.delete(@name)
55
+ end
56
+
35
57
  def applied_method
36
58
  if extra?
37
59
  :extra_attributes_applied_via_resource
@@ -55,14 +77,22 @@ module Graphiti
55
77
  def guard
56
78
  method_name = @attr[:readable]
57
79
  instance = @resource.new
80
+ attribute = @name.to_s
81
+ resource_class = @resource
58
82
 
59
83
  -> {
60
84
  method = instance.method(method_name)
61
- if method.arity.zero?
85
+ result = if method.arity.zero?
62
86
  instance.instance_eval(&method_name)
63
- else
87
+ elsif method.arity == 1
64
88
  instance.instance_exec(@object, &method)
89
+ else
90
+ instance.instance_exec(@object, attribute, &method)
91
+ end
92
+ if Graphiti.context[:graphql] && !result
93
+ raise ::Graphiti::Errors::UnreadableAttribute.new(resource_class, attribute)
65
94
  end
95
+ result
66
96
  }
67
97
  end
68
98
 
@@ -33,7 +33,7 @@ module Graphiti
33
33
  def size
34
34
  values.flatten.size
35
35
  end
36
- alias count size
36
+ alias_method :count, :size
37
37
 
38
38
  def values
39
39
  messages.values.reject(&:empty?)
@@ -48,12 +48,12 @@ module Graphiti
48
48
  def empty?
49
49
  size.zero?
50
50
  end
51
- alias blank? empty?
51
+ alias_method :blank?, :empty?
52
52
 
53
53
  def add(attribute, code, message: nil)
54
54
  message ||= "is #{code.to_s.humanize.downcase}"
55
55
 
56
- details[attribute.to_sym] << {error: code}
56
+ details[attribute.to_sym] << {error: code}
57
57
  messages[attribute.to_sym] << message
58
58
  end
59
59
 
@@ -64,7 +64,7 @@ module Graphiti
64
64
  def full_messages
65
65
  map { |attribute, message| full_message(attribute, message) }
66
66
  end
67
- alias to_a full_messages
67
+ alias_method :to_a, :full_messages
68
68
 
69
69
  def full_messages_for(attribute)
70
70
  attribute = attribute.to_sym
@@ -65,7 +65,7 @@ module Graphiti
65
65
  Thread.current[:_graphiti_hooks] = {
66
66
  after_graph_persist: [],
67
67
  before_commit: [],
68
- after_commit: [],
68
+ after_commit: []
69
69
  }
70
70
  end
71
71
 
@@ -1,3 +1,3 @@
1
1
  module Graphiti
2
- VERSION = "1.2.16"
2
+ VERSION = "1.3.9"
3
3
  end
data/lib/graphiti.rb CHANGED
@@ -6,6 +6,7 @@ require "active_support/core_ext/class/attribute"
6
6
  require "active_support/core_ext/hash/conversions" # to_xml
7
7
  require "active_support/concern"
8
8
  require "active_support/time"
9
+ require "active_support/deprecation"
9
10
 
10
11
  require "dry-types"
11
12
  require "graphiti_errors"
@@ -13,7 +14,7 @@ require "graphiti_errors"
13
14
  require "jsonapi/serializable"
14
15
 
15
16
  module Graphiti
16
- DEPRECATOR = ActiveSupport::Deprecation.new('2.0', 'Graphiti')
17
+ DEPRECATOR = ActiveSupport::Deprecation.new("2.0", "Graphiti")
17
18
 
18
19
  # @api private
19
20
  def self.context
@@ -33,9 +34,9 @@ module Graphiti
33
34
  ensure
34
35
  self.context = prior
35
36
 
36
- resources.each { |resource_class|
37
+ resources.each do |resource_class|
37
38
  resource_class.sideloads.values.each(&:clear_resources)
38
- }
39
+ end
39
40
  end
40
41
 
41
42
  def self.config
@@ -141,6 +142,7 @@ require "graphiti/scoping/sort"
141
142
  require "graphiti/scoping/paginate"
142
143
  require "graphiti/scoping/extra_attributes"
143
144
  require "graphiti/scoping/filterable"
145
+ require "graphiti/scoping/filter_group_validator"
144
146
  require "graphiti/scoping/default_filter"
145
147
  require "graphiti/scoping/filter"
146
148
  require "graphiti/stats/dsl"
@@ -206,6 +208,7 @@ module InstanceVariableOverride
206
208
  values
207
209
  end
208
210
  end
211
+
209
212
  class Object
210
213
  prepend InstanceVariableOverride
211
214
  end