how to add object references to mongoid document - ruby

I am writing an application for my football club, and as part of this I decided to try out MongoDB in a Grape API non-rails.
So I have the following classes
Team & Coach
I am trying to define the relationship between both but cannot get this to work.
class Team
include Mongoid::Document
field :name, type: String
has_one :coach
end
initially the coach filed will be null and therefor when I add a team the only filed I pass in is name this I then see represented in MongoDB like so
{
"_id" : ObjectId("59090e04cf2bee0c0a16a22f"),
"name" : "team A"
}
then when I come to add the coach I get a 201 returned from the API no errors but the coach is missing from MongoDB please someone tell me what I am doing wrong it's driving me insane

Related

How to customize response using Grape API

I am working in Grape API for a project and I have the below scenario. I have 2 tables from where I need to fetch the response. Initial requirement was, I have an entity called "job" where I have to show id and name. So I have exposed the id and name as below.
module XYZPublicApi
module V1
class Job < Grape::Entity
with_options(expose_nil: true) do
expose :id,
expose :name
end
But, after changed requirement,
In response I have to show id and name of job and another field from another object "config" - configDetails (string type)
So the response will be as example
id: id123
name : job124
configDetails: configdetails123
What I have done in this changed requirement, I have made another class in entities/v1
class Config < Grape::Entity
with_options(expose_nil: true) do
expose :configDetails
end
and modified the class Job as below-
class Job < Grape::Entity
with_options(expose_nil: true) do
expose :id,
expose :name
expose :configDetails using XYZPublicAPI::V1::Config
end
But in response I am seeing -
id: id123
name : job124
configDetails: null
Could someone please let me know what am I missing?

temporarily replace content of has_many relationship

when my model is in a particular state, I need to render it with hiding some specific data.
my model knows the data I need to hide through a has_many relationship.
my idea is to retrieve the model, replace the content of the has_many relationship with a dummy, non persisted object, and then render it, without saving the model.
So that when rendering the data shown will be from the dummy object.
here's my code:
the model:
class Car < ActiveRecord::Base
....
has_many :owners
....
end
in the controller:
#car.owners = [ Owner.new(name: "", phone: "") ] if hide_owner?
it actually attempts to do the update on the DB and fails with this error:
*** ActiveRecord::RecordNotSaved Exception: Failed to replace owners because one or more of the new records could not be saved.
It feels like this would be easier if you were accessing a Decorator class instead of the model directly.
Then in the decorator you could define:
def owners
if hide_owner?
[ Owner.new(name: "", phone: "") ]
else
object.owners
end
end
... where object is the instance of Car.
Maybe look at the Draper gem or others.

How to update Saleor's Graphql responses with newly added DB table fields?

First, Saleor with GraphQL is fantastic. Just love it.
The products we are selling have additional metadata we need to get from Graphql. Out of the box, the Graphql queries work fine, such as:
{
product (id: "UHJvZHVjdDo3Mg==") {
id
name
description
}
}
What I need to do is expose data from my products table with additional columns, such as productInfo1, productInfo2, and productInfo3. This part is easy of course.
However, I am struggling with how to update the Saleor Graphql so I can run a query like the following:
{
product (id: "UHJvZHVjdDo3Mg==") {
id
name
description {
productInfo1
productInfo2
productInfo3
}
}
}
I have been through the Saleor docs, Stack Overflow, and a variety of blogs... I've attempted some logical approaches myself, without any success.
I'm eager to start working on these types of updates for our needs here. Any suggestions or links to "how to" locations would be greatly appreciated!
If you'd like to add subfields to description there is a couple of things you have to do:
Create new description object type which contains the subfields you want, e.g.:
class ProductDescription(graphene.ObjectType):
productInfo1 = graphene.String()
productInfo2 = graphene.String()
productInfo3 = graphene.String()
Set the description field with the new type under Product type:
class Product(CountableDjangoObjectType):
...
description = graphene.Field(ProductDescription)
Add resolver for description under Product type:
def resolve_description(self, info):
return ProductDescription(
productInfo1=self.description,
productInfo2='Some additional info',
productInfo3='Some more additional info',
)
Saleor's GraphQL API is based on the Graphene framework. You can find more about resolvers and object types here: https://docs.graphene-python.org/en/latest/types/objecttypes/#resolvers.

Mongoid find by embedded document

I have the following embedded structure
class CbAuthor
include Mongoid::Document
embeds_many: cb_bylines
field :name, type: String
end
class CbByline
include Mongoid::Document
embedded_in :cb_author
has_many :cb_articles
field :byline, type: String
end
class CbArticle
include Mongoid::Document
belongs_to :cb_byline
end
This is because there are many bylines or pseudonyms the authors publish under and that is will be attached to their analytics reports. So when I have a byline, how do I find the author? This will be necessary because They will have dashboards that should list all the articles they wrote under all their respective bylines.
I tried CbAuthor.cb_bylines but that gives me a no method error. or CbAuthor.where(cb_bylines["byline"]: bylineInQuestion) but that also gives errors.
Essentially the goal is to have one author name to find all his bylines and the articles associated with those bylines
embeds_many :cb_bylines is just a fancy way of saying "add an array of hashes called cb_bylines" (at least as far as storage is concerned). That means that your CbAuthors look like this inside MongoDB:
{
_id: '...',
name: '...',
cb_bylines: [
{ _id: '...', byline: '...' },
...
]
}
MongoDB will unroll the array for simple queries for you so you can simply look for 'cb_bylines.byline' as though you were querying a hash inside the collection:
authors_by_lined_as_pancakes = CbAuthor.where('cb_bylines.byline' => 'Pancakes McGee')
or if you know there is just one:
pancakes_mcgee = CbAuthor.find_by('cb_bylines.byline' => 'Pancakes McGee')
Don't be afraid to bypass Rails and Mongoid to look at what your data really looks like inside MongoDB.

How to access Users in Mongo db console

I'm using Mongoid for Ruby. I have queried in my Mongo database before, but forget how it works with Mongo. I have a user model like so:
class User
include Mongoid::Document
field :email, type String
field :crypted_password, type String
...
end
How would I grab all the users or a specific user in my console? Thanks to anyone who can help
use *database
This returns a specific user:
db.getUser("*user")
This returns all users
db.getUsers()
If your class is called User then the underlying MongoDB collection will be users. So you'd say things like:
> db.users.find() // All users
> db.users.find({ field: value }) // Users that match certain conditions
> db.users.findOne({ _id: ObjectId('...') }) // Find one user with a specific id
...
See the find and findOne documentation for further details.

Resources