What is the proper way to use Graphql JSON Scalar in Rails? - json

I have a type that looks like this:
module Types
class LeadType < Types::BaseObject
graphql_name 'Lead'
description 'A lead data query selection'
field :first_name, String, null: true
field :last_name, String, null: true
field :email, String, null: true
field :gender, String, null: true
field :errors, [String], null: true
field :success, String, null: true
field :lead, Types::LeadType, null: true
field :home_data, GraphQL::Types::JSON, null: false
end
end
Note how I have field :home_data, GraphQL::Types::JSON, null: false
Now, when pulling my query data, it's a raw JSON like so:
{
"success"=>true,
"lead"=>
{
"home"=>
{
"1"=>
{
"roof"=>"GRAVEL",
"garage"=>"Yes",
"dead_bolt"=>"No",
"effective"=>"2022-08-25",
"sprinkler"=>"No"
}
},
"first_name"=>"John",
"last_name"=>"Doe",
"email"=>"john#doe.com",
"phone"=>"5599999777",
"gender"=>"Male"
}
}
Now I am able to query my data without the field:home_data, GraphQL::Types::JSON
But when I add the homeData to playground I have this error:
Now, I need the field :home_data, GraphQL::Types::JSON, null: false to display the:
"home"=>
{
"1"=>
{
"roof"=>"GRAVEL",
"garage"=>"Yes",
"dead_bolt"=>"No",
"effective"=>"2022-08-25",
"sprinkler"=>"No"
}
}
How I am able to achieve this using GraphQL::Types::JSON?

null: false means the field is non-nullable. This means that the field will never be nil. If the implementation returns nil, GraphQL-Ruby will return an error to the client
So if your request contains homeData field - your data must contain home_data JSON. But it doesn't. You have home key, not home_data

Related

Is there a possibility that null is inserted when add_column with default option, and without null:false

When I migrate file to add column to existing data,
class AddAdminToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :admin, :boolean, default: false
end
end
Is there a possibility to the value null to admin column?
If I add null: false option like this,
class AddAdminToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :admin, :boolean, default: false, null: false
end
end
I can understand that admin column never contains null.
However If I add column with default option and without null: false option, I would like to know the possibility that admin contains null.
The Database is MySQL.
Thank you.
I tried with SQLite, but I think it will be applied same for MySQL.
If you use default option and without null: false option, it is possible that admin can contain null:
If you use both default and null option, it is clearly that it is not possible to contain null:

Passing json attribute on vue form field

I'm working a project that has Rails API for the back-end and Vue(Vuetify) for the front-end. There is a nice way of building a form using the <v-form></v-form>
tag, but I'm having an issue implementing a field within my form that has a field for JSON. I can easily have one for a string with:
<v-text-field
v-model="host"
label="Host"
solo-inverted
/>
I have an attribute participants, which is a nested array (json) that takes name and email. Been trying to find a way to have my vue form that can take an array.
Here is my database schema:
create_table "shows", force: :cascade do |t|
t.string "host", null: false
t.string "location", null: false
t.text "message"
t.json "participants", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
Tried to find a field for JSON object on a v-form, but can't find anything in the official docs.
There's no built-in Vuetify form field that automatically displays an object. In this case, you have to explicitly bind each object property to a form field/label.
For example, consider participants to be this object:
{
id: 'P1',
label: 'Famous Mathematicians',
names: [
{
first: 'Alan',
last: 'Turing'
},
{
first: 'Isaac',
last: 'Newton'
}
]
}
You could use Vue's string interpolation for participants.label and v-for to map participants.names like this:
<v-form>
<h3>{{ participants.label }}</h3>
<v-col v-for="name of participants.names">
<v-text-field v-model="name.first" label="First name" />
<v-text-field v-model="name.last" label="Last name" />
</v-col>
</v-form>

How to Modify a Map in Elixir

I've created a JSON api using Elixir and the Phoenix
I have an endpoint for a create action in my controller that takes json data which looks like this:
[{"opens_detail"=>
[{"ua"=>"Linux/Ubuntu/Chrome/Chrome 28.0.1500.53",
"ip"=>"55.55.55.55",
"ts"=>1365190001,
"location"=>"Georgia, US"}],
"template"=>"example-template",
"metadata"=>{"user_id"=>"123", "website"=>"www.example.com"},
"clicks"=>42,
"ts"=>1365190000,
"state"=>"sent",
"clicks_detail"=>
[{"ua"=>"Linux/Ubuntu/Chrome/Chrome 28.0.1500.53",
"ip"=>"55.55.55.55",
"ts"=>1365190001,
"url"=>"http://www.example.com",
"location"=>"Georgia, US"}],
"email"=>"recipient.email#example.com",
"subject"=>"example subject",
"sender"=>"sender#example.com",
"_id"=>"abc123abc123abc123abc123",
"tags"=>["password-reset"],
"opens"=>42}]
My goal is to take this json and create a new one from it where some keys and values are renamed to match my schema below:
in web/models/messages.ex
...
schema "messages" do
field :sender, :string
field :uniq_id, :string # equal to '_id' in the payload
field :ts, :utc_datetime
field :template, :string
field :subject, :string
field :email, :string
field :tags, {:array, :string}
field :opens, :integer
field :opens_ip, :string # equal to nested 'ip' value in 'open_details'
field :opens_location, :string # equal to nested 'location' value in 'open_details'
field :clicks, :integer
field :clicks_ip, :string # equal to nested 'ip' value in 'click_details'
field :clicks_location, :string # equal to nested 'location' value in 'click_details'
field :status, :string # equal to the "state" in the payload
timestamps()
end
...
This is what I tried:
in web/controller/message_controller.ex:
def create(conn, payload) do
%{ payload |
"uniq_id" => payload["_id"],
"status" => payload["type"]
"open_ips" => Enum.at(payload["opens_detail"], 0)['ip'],
"open_location" => Enum.at(payload["opens_detail"], 0)['location'],
"click_ips" => Enum.at(payload["clicks_detail"], 0)['ip'],
"click_location" => Enum.at(payload["clicks_detail"], 0)['location'],
}
changeset = Message.changeset(%Message{}, payload)
...
end
but it quickly became clear that it wouldn't work also because I would still need to remove some keys.
I'm coming from Ruby/Python (Rails/Django) and don't want to start polluting my learning of functional programming, specifically elixir/phoenix, with my OO knowledge.
How would you solve this problem?
How would you solve this problem?
I would create a new map from scratch instead of updating the original map. You can use get_in to simplify the logic to access nested fields. Here's an example:
map = %{
uniq_id: get_in(payload, ["_id"]),
open_ips: get_in(payload, ["opens_detail", Access.at(0), "ip"]),
open_locations: get_in(payload, ["opens_detail", Access.at(0), "location"]),
}
If you want to pick a subset of fields from the original map, you can use Map.merge and Map.take:
Map.merge(Map.take(payload, [:sender, ...]), %{uniq_id: ...})
But if it's only a couple of fields I'd rather write them out manually.

How to return json using mongoid

I have a model:
class Client
include Mongoid::Document
field :name, type: String
field :age, type: Integer
index({ name: 1 }, { unique: true })
def self.list
self.all.as_json
end
end
When I call Client.list I get the following:
[{"client"=>{"_id"=>{"$oid"=>"58e91ccb9509d36cbaa8c79b"}, "name"=>"mark", "age"=>30}}]
What I am after is:
[{"_id"=>{"$oid"=>"58e91ccb9509d36cbaa8c79b"}, "name"=>"mark", "age"=>30}]
Which version of mongoid are you using ?
Check the documentation at:
https://docs.mongodb.com/ruby-driver/master/tutorials/6.1.0/mongoid-installation/
You can disable the include_root_in_json to remove the model name of the output json.
Can you try this solution?

Mysql store boolean that reads to true or false

I'd like to create a column which will contain boolean values, I don't want to use TINYINT(0) and store 0 for false and 1 for true, instead i'd like to store "true" or "false" values but not as VARCHAR values.
I'm doing this because I'm using Extjs, and I'm dynamically creating comboboxes, I need those boolean values to use as parameters like so :
function createComboBox(editable) {
var combo = new Ext.form.ComboBox({
typeAhead: true,
mode: 'local',
forceSelection: true,
triggerAction: 'all',
emptyText: 'Select item...',
selectOnFocus: true,
//...other settings
editable: editable // true or false
});
return combo;
};
And editable would be "true" or "false" (without quotes).
Should I just use a varchar column and remove the quotes in Extjs? Is there a better way?
You could use ENUM('true', 'false') as the column data type.
Use an int and cast it to a boolean (but it is probably not really needed):
var boolValue = !!intValue;