graphql-activerecord 0.12.1 → 0.12.2

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