PostgreSQL query and convert a column with Ruby serialized YAML to JSON - ruby

I am connecting to a PostgreSQL database, which connected to an old Rails app. It has a table versions and it has a column with Ruby serialized YAML. From Postico, I would like to do a SELECT query but convert a column with Ruby serialized YAML to JSON.
I tried looking around and found this gist but did not return as expected.
YAML column
--- !ruby/object:BillingInfo
gateway_identifier: blah
organisation: blah
billing_email: blah
reference: blah
phone: blah
country: blah
vat: blah
subscription: blah
expected query result
{
"--- !ruby/object":"BillingInfo",
"gateway_identifier": "blah ",
"organisation": "blah",
"billing_email": "blah",
"reference": "blah",
"phone": "blah",
"country": "blah",
"vat": "blah",
"subscription": "blah"
}
updates:
I tried the suggested from the comment by Gerard
SELECT jsonb_pretty(jsonb_build_object('YAML', data)) FROM versions;
but this returned
{
"YAML": "--- !ruby/object:BillingInfo\ngateway_identifier: blah \norganisation: blah\nbilling_email: blah\nreference: blah\nphone: blah\ncountry: blah\nvat: blah\nsubscription: blah"
}

Related

Can I restrict a mutation to update an object based on the object itself?

I have the following objects in my database:
[
{
"id": 1,
"name": "foo",
"objType": "A"
},
{
"id": 2,
"name": "bar",
"objType": "B"
}
]
And the following users:
[
{
"id": 3,
"name": "User A",
"role": "admin"
},
{
"id": 4,
"name": "User B",
"role": "client"
}
]
And I have a schema like:
enum ObjTypeEnum {
A
B
}
type MyObj {
id: Int
name: String
objType: ObjTypeEnum
}
type Mutation {
updateObj(id: Int!, name: String): MyObj
}
The user A can update any obj that he wants because he is an admin. However, the user B can only update an object only if this object is of type B.
That means:
If the user B tries to update the object 2, using the mutation updateObj(2, "new name"), this should be totally ok. However, if he tries to update the object 1, updateObj(1, "new name"), now this should return an error for this user.
My naïve solution for this is get the object in the resolver, check its type and, if is ok for the current user, then proceed with the update, otherwise throw an error. But I have the feeling I'm in the wrong direction and not using graphql properly...
Is it possible to do it using directives or something more generic, since the key that using to validate the update is an enum?

Using graphql playground to test Saleor productCreate, what's the correct syntax for adding a product description?

In the code example below, if I exclude the description field the product is created successfully. With the description field in place I get a GraphQL error.
The code:
productCreate(
input: {
category: "Q2F0ZWdvcnk6MQ==", # Category ID
name: "Delete Me!", # Product name
productType: "UHJvZHVjdFR5cGU6MQ==", # Product Type ID
chargeTaxes: true,
weight: "0.3", # in Kg
rating: 5,
description: {text:"some text"}, # nope
}
)
The error:
graphql.error.base.GraphQLError: Argument \"input\" has invalid value {category: \"Q2F0ZWdvcnk6MQ==\", name: \"Delete Me!\", productType: \"UHJvZHVjdFR5cGU6MQ==\", chargeTaxes: true, weight: \"0.3\", rating: 5, description: {text: \"some text\"}}.",
"In field \"description\": Expected type \"JSONString\", found {text: \"some text\"}."
It is a string, for rich text it is using https://editorjs.io/
You can inspect the network tab in the dashboard to learn how APIs are being used
JSON string means providing a JSON text converted to a string. This can be achieved by escaping quotation marks within the JSON.
For example, this JSON
{ "text": "some text" }
can be converted to String as below:
"{\"text\":\"sometext\"}"
As you notice that the text encapsulated inside quotation marks, to be a valid String.
You can use https://jsontostring.com/ for the conversion
Your final code should be like this:
mutation {
productCreate(
input: {
category: "Q2F0ZWdvcnk6MQ==" # Category ID
name: "Delete Me!" # Product name
productType: "UHJvZHVjdFR5cGU6MQ==" # Product Type ID
chargeTaxes: true
weight: "0.3" # in Kg
rating: 5
description: "{\"text\":\"sometext\"}" # nope
}
){
product{
id
}
}
}
Sorting out the description syntax wasn't straightforward. From my question here:
Saleor on Github
I got this answer:
{
"id": "UHJvZHVjdDo3Mg==",
"description": "{\"blocks\":[{\"type\":\"paragraph\",\"data\":{\"text\":\"New description\"}}]}"
}
which I then implemented like this:
query = gql(
"""
mutation (
$slug: String!,
$product_title: String!,
$description: JSONString!,
$weight_grams: WeightScalar!,
)
{
productCreate(
input:{
category: "Q2F0ZWdvcnk6NQ==",
name: $product_title,
productType: "UHJvZHVjdFR5cGU6MQ==",
slug: $slug,
description: $description,
weight: $weight_grams,
}
)
{
errors {
field
message
}
product {
id
name
productType {
id
}
slug
}
}
}
"""
)
params = {
"product_title": str(product_title),
"description": '{"blocks":[{"type":"paragraph","data":{"text":"'
+ str(product_title + " (" + csv_product_id + ")")
+ '"}}]}',
"slug": str(csv_sku_code),
"weight_grams": str(weight_grams),
}
result = client.execute(query, variable_values=params)
This works well for us.

Grape hash params with dynamic key names

Is it possible to specify grape parameters when keys are unknown (because they are identifiers, e.g. a name or an ID)
{
"pascal" => {"property_1" => 1234, "property_2" => 5678},
"another name" => {"property_1" => 1234, "property_2" => 5678}
}
So I want the params to be a Hash where they key is a String (preferrably validated with a regexp) and the value is yet another hash.
As #stefan and #Ideld pointed out: there is no way to do what I asked for and the recommended way is to use a format like:
[
{ "name": "pascal", "property_1": 1234, "property_2": 5678 },
{ "name": "another_name", "property_1": 1234, "property_2": 5678 }
]
instead.

how to leverage embedded resources in ReferenceArrayInput and ReferenceArrayField so it doesn't make extra calls

if my server responds with results like those:
row = {
id: value,
name: value,
height: value,
categories: [{id: "1", name: "name 1" },{id: "2", name: "name 2"},{id: "3", name: "name 3"},{id: "4", name: "name 4"}]
}
how can I use this information to populate my ReferenceArrayField ChipFields without requiring extra calls against /categories?filter={ids: [ ]} ?
We don't support this scenario currently. In AOR, categories should be a distinct resource and the resource you're showing should only references the categories ids.
If you do have a distinct resource for categories, then your restClient should cleanup the resource referencing categories and only includes their ids

Updating in MongoDB without first having to pull a Mongoid object?

When performing queries I can go through Mongoid:
product_obj = Product.where(
_id: "58f876f683c336eec88e9db5"
).first # => #<Product _id: 58f876f683c336eec88e9db5, created_at: nil, updated_at: nil, sku: "123", name: "Some text", ...)
​
or I can circumvent it:
product_hsh = Product.collection.find( {
_id: BSON::ObjectId.from_string("58f876f683c336eec88e9db5")
}, {
projection: {
_id: 1,
name: 1
}
} ).first # => {"_id"=>BSON::ObjectId('58f876f683c336eec88e9db5'), "name"=>"Some text"}
I prefer to circumvent, because it performs better; I can limit which fields to get in the response.
My problem, however, is how to further work with the returned product. The response is a hash, not an object, so if I have to update it I need to pull it through Mongoid anyway, and thereby the performance gains are gone:
Product.find(product_hsh["_id"]).update_attribute(:name, "Some other text")
My question is: how do I update without first having to pull a Mongoid object?
You don't need to pull/fetch at all. You can just send the $set commands directly:
Product.where(id: product_hsh["_id"]).update_all(name: "Some other text")

Resources