graphql-activerecord 0.12.1 → 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47f8e83319aae9878a416eff9f3064a853b5da90
4
- data.tar.gz: 656cbb121487a505e7a2b6fe020276de5e0bae49
3
+ metadata.gz: 6c83f3a8016448bb97d1e15a2e4c3958ab631725
4
+ data.tar.gz: 0f4683f753d5a45a3b9c5d473cb3c2546dd833e7
5
5
  SHA512:
6
- metadata.gz: d86830043d4611c1dcd65e389df5de4b24e33eaa83cf1db4fb896b2d792e8526d413ee63cb2a7a31002866321e345b5e0b17d16f1b499119b28550c4d858c1c7
7
- data.tar.gz: f7a3021d4f63b117e5fe4f58e620a22256544396cbf5f9c980f1bcc41b12cefd5e143ddd9e859937bc3e1acaba36b7af70c00ec4e9bb7e66664e1e7e6153c9be
6
+ metadata.gz: f29777ba30b72b285a24fff31fc6e8354e7f85cef43d2355dc88b4e405e45284e044b1acc0a9cad0027e734b6eb93d00baed3129fa246649372656684549fd4e
7
+ data.tar.gz: 8add41735a53eb7ff17bb291a0f0c6f12a6e70dc2093515f2c8cf099fcdbb4702fcaaf2b081a211c98c54431fea87ba0123dceb22ce5114e468883514150aa05
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ # 0.12.2
4
+ In mutators, the gem now supports updating nested models, where the `find_by` option specifies an ID field. This works similarly
5
+ to input fields that accept ID values: it expects a global ID value to be provided, and uses your configured `model_from_id` proc
6
+ to get the model's database ID.
7
+
3
8
  # 0.12.1
4
9
  Updates the gemspec to support Rails 5
5
10
 
data/README.md CHANGED
@@ -374,8 +374,8 @@ nested :emergency_contacts, find_by: :priority, null_behavior: :set_null do
374
374
  end
375
375
  ```
376
376
 
377
- This causes the gem to automatically include `priority` as an input field. Unfortunately, the only field you _can't_ use is the
378
- `id` field, because the gem isn't smart enough to map global ID's to model ID's. (This will be supported eventually, though.)
377
+ This causes the gem to automatically include `priority` as an input field. You could also manually specify the
378
+ `priority` field if you wanted to override its name or type.
379
379
 
380
380
  Also, an important note is that the gem assumes that you are passing up _all_ of the associated models, and not just some of
381
381
  them. It will destroy extra models, or create missing models.
@@ -48,12 +48,15 @@ module GraphQL::Models
48
48
 
49
49
  detect_field_conflict(name)
50
50
 
51
- fields.push({
51
+ # Delete the field, if it's already in the map
52
+ fields.reject! { |fd| fd[:attribute] == attribute }
53
+
54
+ fields << {
52
55
  name: name,
53
56
  attribute: attribute,
54
57
  type: type,
55
58
  required: required,
56
- })
59
+ }
57
60
  end
58
61
 
59
62
  def proxy_to(association, &block)
@@ -51,7 +51,7 @@ module GraphQL::Models
51
51
  return [] if next_inputs.nil? && parent_map.leave_null_unchanged?
52
52
 
53
53
  changes = []
54
- matches = match_inputs_to_models(parent_model, child_map, next_inputs, changes)
54
+ matches = match_inputs_to_models(parent_model, child_map, next_inputs, changes, context)
55
55
 
56
56
  matches.each do |match|
57
57
  next if match[:child_model].nil? && match[:child_inputs].nil?
@@ -70,7 +70,7 @@ module GraphQL::Models
70
70
  changes
71
71
  end
72
72
 
73
- def self.match_inputs_to_models(model, child_map, next_inputs, changes)
73
+ def self.match_inputs_to_models(model, child_map, next_inputs, changes, context)
74
74
  if !child_map.has_many
75
75
  child_model = model.public_send(child_map.association)
76
76
 
@@ -104,7 +104,7 @@ module GraphQL::Models
104
104
  if find_by.empty?
105
105
  return match_inputs_by_position(model, child_map, next_inputs, changes, associated_models)
106
106
  else
107
- return match_inputs_by_fields(model, child_map, next_inputs, changes, associated_models, find_by)
107
+ return match_inputs_by_fields(model, child_map, next_inputs, changes, associated_models, find_by, context)
108
108
  end
109
109
  end
110
110
  end
@@ -134,7 +134,7 @@ module GraphQL::Models
134
134
  matches
135
135
  end
136
136
 
137
- def self.match_inputs_by_fields(_model, child_map, next_inputs, changes, associated_models, find_by)
137
+ def self.match_inputs_by_fields(_model, child_map, next_inputs, changes, associated_models, find_by, context)
138
138
  # Convert the find_by into the field definitions, so that we properly unmap aliased fields
139
139
  find_by_defs = find_by.map { |name| child_map.fields.detect { |f| f[:attribute].to_s == name.to_s } }
140
140
  name_to_attr = find_by_defs.map { |f| [f[:name], f[:attribute].to_s] }.to_h
@@ -145,8 +145,20 @@ module GraphQL::Models
145
145
  indexed_inputs = next_inputs.index_by { |ni| ni.to_h.slice(*name_to_attr.keys) }
146
146
 
147
147
  indexed_inputs = indexed_inputs.map do |key, inputs|
148
- key = key.map { |name, val| [name_to_attr[name], val] }.to_h
149
- [key, inputs]
148
+ attr_key = {}
149
+ key.each do |name, val|
150
+ # If the input is a Relay ID, convert it to the model's ordinary ID first. Note, this is
151
+ # less than optimal, because it has to fetch the model and then just get its id :(
152
+ field_def = find_by_defs.detect { |d| d[:name] == name }
153
+ if val && field_def[:type].unwrap == GraphQL::ID_TYPE
154
+ val = relay_id_to_model_id(val, context)
155
+ raise GraphQL::ExecutionError, "The value provided for #{field_def[:name]} does not refer to a valid model." unless val
156
+ end
157
+
158
+ attr_key[name_to_attr[name]] = val
159
+ end
160
+
161
+ [attr_key, inputs]
150
162
  end
151
163
 
152
164
  indexed_inputs = indexed_inputs.to_h
@@ -154,8 +166,6 @@ module GraphQL::Models
154
166
  # Match each model to its input. If there is no input for it, mark that the model should be destroyed.
155
167
  matches = []
156
168
 
157
- # TODO: Support for finding by an ID field, that needs to be untranslated from a Relay ID into a model ID
158
-
159
169
  indexed_models.each do |key_attrs, child_model|
160
170
  inputs = indexed_inputs[key_attrs]
161
171
 
@@ -204,13 +214,10 @@ module GraphQL::Models
204
214
  def self.apply_field_value(model, field_def, value, context, changes)
205
215
  # Special case: If this is an ID field, get the ID from the target model
206
216
  if value.present? && field_def[:type].unwrap == GraphQL::ID_TYPE
207
- target_model = GraphQL::Models.model_from_id.call(value, context)
208
-
209
- unless target_model
217
+ value = relay_id_to_model_id(value, context)
218
+ unless value
210
219
  raise GraphQL::ExecutionError, "The value provided for #{field_def[:name]} does not refer to a valid model."
211
220
  end
212
-
213
- value = target_model.id
214
221
  end
215
222
 
216
223
  unless model.public_send(field_def[:attribute]) == value
@@ -251,5 +258,10 @@ module GraphQL::Models
251
258
 
252
259
  values
253
260
  end
261
+
262
+ def self.relay_id_to_model_id(relay_id, context)
263
+ target_model = GraphQL::Models.model_from_id.call(relay_id, context)
264
+ target_model&.id
265
+ end
254
266
  end
255
267
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Models
4
- VERSION = "0.12.1"
4
+ VERSION = "0.12.2"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Foster
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-17 00:00:00.000000000 Z
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport