Hi! How can I include JSONB attributes (using PostgreSQL) in my GraphQL Schema?
In my Rails app I usually access those column using store_accessor:
store_accessor :jsonb_column, :prop_a, :prop_b
Disclaimer: I'm new to GraphQL 馃檲
Thanks!
Does store_accessor make a method with the same name? If so, then you don't need anything special, just add a field, eg
field :prop_a, types.String # or types.Int, whatever type is in that field
@rmosolgo mmm good point, I should have omitted the store_accesor stuff, since what I'm looking for is to keep it as a nested record. For example:
# person_type.rb
module Graph
PersonType = GraphQL::ObjectType.define do
name 'Person'
description 'A person'
field :id, types.ID
field :medical_records do # this is the JSONB column
type MedicalRecordsType
resolve lambda { |obj, _args, _ctw|
obj.medical_records
}
end
end
end
# medical_records_type.rb
module Graph
MedicalRecordsType = GraphQL::ObjectType.define do
name 'MedicalRecords'
description 'A medical records'
field :diabetes, types.String
# ... other regular fields
end
end
If I try to run the following query:
query: {
person(id: 1) {
medical_records {
diabetes
}
}
}
I get the following Exception:
NoMethodError in Api::V1::GraphController#index
undefined method `diabetes' for #<Hash:0x007fe143e36878>
Oh I see!
By default, fields perform a method call. To resolve a field with [...], You can specify a key with hash_key:, eg,
field :diabetes, types.String, hash_key: :diabetes
# will find a value by doing `medical_records[:diabetes]`
A few more examples here: http://www.rubydoc.info/gems/graphql/GraphQL/Field
Does that work for you? Please reopen this if not!
@rmosolgo awesome! It worked like a charm for 1-level nested fields, but it stops working for deeply nested fields:
# medical_records_type.rb
module Graph
MedicalRecordsType = GraphQL::ObjectType.define do
name 'MedicalRecords'
description 'A medical records'
field :diabetes, types.String
# Option A
field :measurements, types[MeasurementsType], hash_key: :measurements
# Option B
field :measurements do
type MeasurementsType
resolve lambda { |obj, _args, _ctw|
obj['measurements']
}
end
end
end
# measurements_type.rb
module Graph
MeasurementsType = GraphQL::ObjectType.define do
name 'Measurements'
description 'A measurements'
field :weight, types.Integer
field :height, types.Integer
end
end
Can you help me understand what "stops working" means here? Is there runtime error?
@rmosolgo sorry, I sent the comment before finishing it (freaking CMD + Enter). I updated the code above 鈽濓笍
Basically the issue is with the resulting repsonse:
Option A will return: measurements: null
Option B will return: measurements: {weight: null, height: null}
...while the actual value in the JSONB record being: measurements: {weight: 100, height: 70}
Option A has
field :measurements, types[MeasurementsType]
which means that measurements returns a _list_ of MeasurementsType objects. Should it be
field :measurements, MeasurementsType
which means it returns an object of type MeasurementsType? (This would match Option B.)
@rmosolgo good catch, this was indeed a newbie mistake. Although neither results changed at all for some reason
Option A will return: measurements: null
Option B will return: measurements: {weight: null, height: null}
Oh right, the other difference is:
# Access a key named `:measurements` (symbol)
field :measurements, types[MeasurementsType], hash_key: :measurements
# Access a key named `"measurements"` (string)
field :measurements, types[MeasurementsType], hash_key: "measurements"
Does it work for you if you specify a string as the key (hash_key: "measurements")?
Judging by the docs, ActiveRecord::Store accepts _either_ strings or symbols, but I imagine that after the first key, it's up to you to choose the right kind of key. And if the storage is JSON, the keys are probably strings!
Any luck?
@rmosolgo yeah that did the trick!
thanks a lot for the help 馃樃 u're awesome!
Most helpful comment
Oh right, the other difference is:
Does it work for you if you specify a string as the key (
hash_key: "measurements")?Judging by the docs, ActiveRecord::Store accepts _either_ strings or symbols, but I imagine that after the first key, it's up to you to choose the right kind of key. And if the storage is JSON, the keys are probably strings!
Any luck?