How to return json using mongoid - json

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?

Related

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

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

Nested JSON to Ruby class (with validation)

I have the following JSON:
{
"ordernumber":"216300001000",
"datecreated":"2016-11-08T14:23:06.631Z",
"shippingmethod":"Delivery",
...
"customer":{
"firstname":"Victoria",
"lastname":"Validator"
},
"products":[
{
"sku":"ABC1",
"price":"9.99"
},
...
]
}
With the corresponding Ruby classes including validators:
class Task
include ActiveModel::Model
include ActiveModel::Serializers::JSON
validates ..., presence: true
...
end
class Product
include ActiveModel::Model
include ActiveModel::Serializers::JSON
validates ..., presence: true
...
end
class Customer
include ActiveModel::Model
include ActiveModel::Serializers::JSON
validates ..., presence: true
...
end
What I want to do is serialise the JSON to a Ruby class. The problem is that the Task class get's initialised correctly. But the nested classes like Customer and Product remain hashes. (A Task has one Customer and multiple Products)
Example:
json = %Q{{ "ordernumber":"216300001000", "datecreated":"2016-11-08T14:23:06.631Z", "shippingmethod":"Delivery", "customer":{ "firstname":"Victoria", "lastname":"Validator" }, "products":[ { "sku":"ABC1", "price":"9.99" } ] }}
task = Task.new()
task.from_json(json)
task.class
# => Task
task.products[0].class
# => Hash
How do I do this using ActiveModel and also validate the nested JSON? (I'm not using Rails)
As far as I know, ActiveModel::Model brings validations and other handy stuff, but it does not bring tools to handle association problems like this one. You have to implement his behavior yourself.
First of all, I'd use the builtin initialization system that ActiveModel::Model provides. Then I'd define products= and customer= to take the attributes and initialize instances of the proper classes. And call the validations of the associated records.
class Task
include ActiveModel::Model
attr_reader :products, :customer
# ...
validate :associated_records_are_valid
def products=(ary)
#products = ary.map(&Product.method(:new))
end
def customer=(attrs)
#customer = Customer.new(attrs)
end
private
def associated_records_are_valid
products.all?(&:valid?) && customer.valid?
end
end
attributes = JSON.parse(json_str)
task = Task.new(attributes)
Look at this topic: Is it possible to convert a JSON string to an object?. I am not in front of a computer right now to post a code, but I think that answer solves your problem.

rails: active model serializer looking for wrong serializer

When I call the the create method i get a nameError.
Failure/Error: post :create, { user: { email: 'charles#example.com',
NameError:
uninitialized constant API::V1::UsersController::UserV1Serializer
why is it adding that UsersController module to the class it is looking for? In my sessions controller I use the same exact render line and it doesn't complain. what is going on?
app/controllers/api/v1/users_controller.rb
class API::V1::UsersController < API::V1::BaseController
...
...
def create
user = User.new(user_params)
if user.save
sign_in :user, user, store: false
end
render json: user, serializer: UserV1Serializer, root: 'user'
end
app/serializers/api/v1/user_v1_serializer.rb
class API::V1::UserV1Serializer < ActiveModel::Serializer
attributes :id, :email
def attributes
hash = super
if scope == object
hash[:token] = object.authentication_token
end
hash
end
end
Instead of specifying UserV1Serializer, you need to specify the full namespaced class name API::V1::UserV1Serializer.
If you just specify the UserV1Serializer, its looking for the serializer class within current controller API::V1::UsersController::UserV1Serializer which is why you get an error as
uninitialized constant API::V1::UsersController::UserV1Serializer.
Use this instead:
render json: user, serializer: API::V1::UserV1Serializer, root: 'user'

Unique doesn't work on Node.js Sails.js "sails-mysql"

I've just started to get into the framework of Sails for Node. But it seems like I can't get the unique- requirements to work when adding for example users to the sails-mysql database. I can atm add unlimited number of new users with the same username and email.
From what I have read it should work, I did also try with sails-memory and there this exact code did work. Is it something I have missed out?
module.exports = {
attributes: {
username: {
type: 'string',
required: true,
unique: true
},
firstname: {
type: 'string',
required: true
},
lastname: {
type: 'string',
required: true
},
password: {
type: 'string',
required: true
},
birthdate: {
type: 'date',
required: true
},
email: {
type: 'email',
required: true,
unique: true
},
phonenumber: 'string',
// Create users full name automaticly
fullname: function(){
return this.firstname + ' ' + this.lastname;
}
}
};
As I mentioned above, this does work with the memory-storage. And now I have also tried with mongodb where it does work fins as well.
Got support from Sails.js on twitter: "it uses the db layer- suspect it's an issue with automigrations. Would you try in a new MySQL db?"
This answer did work, a new db and everything was just working :)
Just to add to this, since sails uses auto-migrations, if you initially start the server and your model does not have an attribute as unique, the table is built without the unique (index) switch. If you then change an existing attribute in the model to unique, the table will not be rebuilt the subsequent times you start the server.
One remedy during development is to set migrations in your model to drop like this:
module.exports = {
migrate: 'drop' // drops all your tables and then re-create them Note: You loose underlying.
attributes: {
...
}
};
That way, the db would be rebuilt each time you start the server. This would of course drop any existing data as well.

Rails JSON using RABL, showing parent attribute?

I have the following RABL file in my Rails 3.2 application:
collection #results.limit(5)
attributes :date, :client_id
child :client do
attributes :Surname
end
child :animal do
attributes :AnimalName
end
I would like to add the name of the user that the result belongs to. Everything I have read in the RABL documentation seem to suggest that only child and node are available.
How could I get a parents attribute within the above code? Just doing the following returns NULL, obviously!
child :animal do
attributes :AnimalName
end
Is this possible?
Current JSON output:
{
date: "2013-06-25T19:36:11+01:00",
client_id: 88172,
client: {
Surname: "Strange"
},
animal: {
AnimalName: "Ria"
}
},
Desired output:
{
date: "2013-06-25T19:36:11+01:00",
client_id: 882372,
client: {
Surname: "Summer"
},
animal: {
AnimalName: "Ria"
},
user: {
UserName: "Danny"
}
},
You can add a custom node that adds in the user data:
collection #results.limit(5)
attributes :date, :client_id
node :user do |report|
partial('users/show', :object => report.user)
end
This is assuming that you want the whole user/show template.
If you just want the name key/value:
node :user do |report|
{ :name => report.user.name }
end