How can i pass input parameter to nested object in Graphene? - python-3.x

I'm not sure what is the best way to pass variable inside nested type, hope someone already faced the same case and can help.
Code example is:
class UserType(ObjectType):
firstname = String(required=True)
def resolve_firstname(parent, info):
user = get_user_by_id()
return user.firstname
class UserResult(Union):
class Meta:
types = [UserType, ErrorError, ]
class Query(ObjectType):
user = Field(
UserResult,
user_id=String(required=True)
)
async def resolve_user(parent, info, user_id):
result = UserType()
# or return error from Union
return result
And graphQL query looks:
query{
user(user_id: "uuid_here") {
... on UserType {
data
}
... on SomeError {
message
}
}
}
I'm using Union to provide info about returning types in schema.
I have access to user_id in resolve_user, but i need this value in UserType's * resolve_firstname*. In this case i need way pass this variable.
What are ways to do so?
I can modify UserType and add user_id near firstname = String(required=True) and pass user_id this way - UserType(user_id=user_id). But in this case user_id will be available in schema.
Is it correct to use __init__ method in graphene's custom type? In this case i'll be able use variable and hide it from graphql's schema.

Related

How to get gql return type of resolver from within resolver?

EDIT: Maybe a simpler question - Is there any way of accessing __typename in a resolver? like this php question https://github.com/webonyx/graphql-php/discussions/1087
I am trying to prevent manually defining the type arg of fieldWasRequested below. Can I reliably get this string from within the resolver? This would be the same as the resolvers __typename value. I found a way that kinda gets close but is ultimately too brittle.
I am using parseResolveInfo from graphql-parse-resolve-info to check if a field was requested in a resolver. In order to do this, I need to access the type name of the resolver. Currently I am manually setting this and getting the name by looking at the graphql schema file.
import { parseResolveInfo } from 'graphql-parse-resolve-info'
export const fieldWasRequested = (field: string, type: string, info: GraphQLResolveInfo) => {
const parsedInfo = parseResolveInfo(info)
const fields = parsedInfo?.fieldsByTypeName?.[type] ?? {}
return field in fields
}
export const thing1: Resolvers['thing1'] = async (parent, args, ctx, info): Promise<Thing1[]> => {
const fieldWasRequested = fieldWasRequested('field1', 'Thing1', info)
// continued ...
}
I see there is info.returnType, which is this GraphQLOutputType. This is a unioin of many types, all of which seem to have a toString method.
Logging info.returnType.toString() returns [Thing1]. This is an array of Thing1. But for other resolvers it could be Thing2, [Thing3!]!, etc. It's just not feasible to parse from this. Is there a better way?

I get an error about not finding a matching constructor but the signatures match

class SharedWorld {
def db = Db(sql)
def help = Help(db)
}
class Db {
Sql sql
Db(def sql) {
this.sql = sql
}
}
class Help {
Help(){}
Db db
Help(Db db) {
this.db = db
}
}
I have this structure and for some reason when I compile my groovy I get an error that it can't find a matching constructor for Help(Db). Any ideas why? The signature obviously matches
You've got a few issues with your code.
First, class declarations don't take parameters or need parentheses immediately after the class name. Try making a constructor for SharedWorld inside the curly braces. In addition, you need to use the new keyword to instantiate classes (although there is a #Newify annotation to support the syntax you're using). Example:
class SharedWorld {
def db
def help
SharedWorld(sql) {
db = new Db(sql)
help = new Help(db)
}
}

How to get the primary key attribute name of a model? (waterline ORM)

Some of my models do not have id as their primary key, and I need to know the name of the primary key of a given model but I couldn't find a way of doing this. I searched in the waterline docs and source, but all what I found in the their source is that they are using the attributes object definition which is stored in a unaccessible variable in the lib scope.
The "cleaner" way I found to do it for now is like this:
// file: api/libs/model.js
module.exports = {
//...
primaryKeyName: function (modelName) {
var key, attr, pk,
def = require('../models/' + modelName).attributes;
for (var key in def.attributes) {
attr = def.attributes[key];
if (attr && attr.primaryKey) {
pk = key;
break;
}
}
return pk || 'id';
},
//...
};
but I feel this is a bit tricky and I am wondering if there wouldn't be a better solution with some hidden/undocumented helper function or method on the model or model instance (ie record)...
Ah! I should inspect the model class from the console and I'd have my answer.
Anyway, whoever would be looking for the same info, here it is:
SomeModel.primaryKey; // => 'id' or whatever it is
And voila, as simple!
There are a bunch of utilities that can help you with this. Check out sails blueprint files and specifically the actionUtils.js file
api\node_modules\sails\lib\hooks\blueprints

Collect closure in groovy

I am new to functional programming paradigm and hoping to learn the concepts using groovy. I have a json text containing a list of several person objects like the following:
{
"persons":[
{
"id":1234,
"lastname":"Smith",
"firstname":"John"
},
{
"id":1235,
"lastname":"Lee",
"firstname":"Tommy"
}
]
}
What I am trying to do store them in list or array of Person groovy class like the following:
class Person {
def id
String lastname
String firstname
}
I would like to do this using a closure. I tried something like:
def personsListJson= new JsonSlurper().parseText(personJsonText) //personJsonText is raw json string
persons = personsListJson.collect{
new Person(
id:it.id, firstname:it.firstname, lastname:it.lastname)
}
This didn't work. Does collect operations supposed to behave this way? If so then how do I write it?
Try
personsListJson.persons.collect {
new Person( id:it.id, firstname:it.firstname, lastname:it.lastname )
}
And as there is a 1:1 mapping between the json and the constructor parameters, you can simplify that to:
personsListJson.persons.collect {
new Person( it )
}
But I'd keep the first method, as if the Json got an extra value in it (maybe out of your control) then the second method would break
You can try it-
List<JSON> personsListJson = JSON.parse(personJsonText);
persons = personsListJson.collect{
new Person(id:it.id, firstname:it.firstname, lastname:it.lastname)
}

how to retrieve nested properties in groovy

I'm wondering what is the best way to retrieve nested properties in Groovy, taking a given Object and arbitrary "property" String. I would like to something like this:
someGroovyObject.getProperty("property1.property2")
I've had a hard time finding an example of others wanting to do this, so maybe I'm not understanding some basic Groovy concept. It seems like there must be some elegant way to do this.
As reference, there is a feature in Wicket that is exactly what I'm looking for, called the PropertyResolver:
http://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/lang/PropertyResolver.html
Any hints would be appreciated!
I don't know if Groovy has a built-in way to do this, but here are 2 solutions. Run this code in the Groovy Console to test it.
def getProperty(object, String property) {
property.tokenize('.').inject object, {obj, prop ->
obj[prop]
}
}
// Define some classes to use in the test
class Name {
String first
String second
}
class Person {
Name name
}
// Create an object to use in the test
Person person = new Person(name: new Name(first: 'Joe', second: 'Bloggs'))
// Run the test
assert 'Joe' == getProperty(person, 'name.first')
/////////////////////////////////////////
// Alternative Implementation
/////////////////////////////////////////
def evalProperty(object, String property) {
Eval.x(object, 'x.' + property)
}
// Test the alternative implementation
assert 'Bloggs' == evalProperty(person, 'name.second')
Groovy Beans let you access fields directly. You do not have to define getter/setter methods. They get generated for you. Whenever you access a bean property the getter/setter method is called internally. You can bypass this behavior by using the .# operator. See the following example:
class Person {
String name
Address address
List<Account> accounts = []
}
class Address {
String street
Integer zip
}
class Account {
String bankName
Long balance
}
def person = new Person(name: 'Richardson Heights', address: new Address(street: 'Baker Street', zip: 22222))
person.accounts << new Account(bankName: 'BOA', balance: 450)
person.accounts << new Account(bankName: 'CitiBank', balance: 300)
If you are not dealing with collections you can simply just call the field you want to access.
assert 'Richardson Heights' == person.name
assert 'Baker Street' == person.address.street
assert 22222 == person.address.zip
If you want to access a field within a collection you have to select the element:
assert 'BOA' == person.accounts[0].bankName
assert 300 == person.accounts[1].balance​​​​​​​​​
You can also use propertyMissing. This is what you might call Groovy's built-in method.
Declare this in your class:
def propertyMissing(String name) {
if (name.contains(".")) {
def (String propertyname, String subproperty) = name.tokenize(".")
if (this.hasProperty(propertyname) && this."$propertyname".hasProperty(subproperty)) {
return this."$propertyname"."$subproperty"
}
}
}
Then refer to your properties as desired:
def properties = "property1.property2"
assert someGroovyObject."$properties" == someValue
This is automatically recursive, and you don't have to explicitly call a method. This is only a getter, but you can define a second version with parameters to make a setter as well.
The downside is that, as far as I can tell, you can only define one version of propertyMissing, so you have to decide if dynamic path navigation is what you want to use it for.
See
https://stackoverflow.com/a/15632027/2015517
It uses ${} syntax that can be used as part of GString

Resources