Union types support in Relay - relayjs

When you have defined field as an union of two types (in example machines contains Ships and Droid) then in Relay you can do something like that:
fragment on Faction# relay(plural: true) {
name,
machines {
... on Ship {
name
}
... on Droid {
name,
primaryFunction
}
}
}
so under machines prop your objects are correctly evaluated, but if you want to do that using fragments from external components:
fragment on Faction# relay(plural: true) {
name,
machines {
${StarWarsShip.getFragment('ship')}
${StarWarsDroid.getFragment('droid')}
}
}
then you end up with fragment definitions under machines. It looks like you are trapped and can't check which object is which type in machines array so you can't decide which component should be used.

There exists a __typename field with which you should be able to introspect the type of each record:
Query
fragment on Faction #relay(plural: true) {
name,
machines {
__typename # <-- add this
${StarWarsShip.getFragment('ship')}
${StarWarsDroid.getFragment('droid')}
}
}
App code
this.props.faction.machines.map(machine =>
machine.__typename === 'Droid'
? <Droid droid={machine} />
: <Ship ship={machine} />
);

Related

Mock data generation for storybook

I am trying to generate mock data using relay for storybook.
My query is
const QUERY_LIST = graphql`
query modelControllerAllUsersQuery #relay_test_operation {
allUsers {
pageInfo {
hasNextPage
}
edges {
node {
id
firstName
lastName
}
}
}
}
`
and provided RelayEnvironmentProvider as a decorator to the story. I'm trying to return some default values to my query using custom mock resolvers.
const customMockResolvers = {
...mockResolvers,
allUsers:() => ({
pageInfo:{
hasNextPage:false,
},
edges:[
{
node:{
id :'id',
firstName:'fname',
lastName :'lname',
},
},
],
}),
};
and calling it as
(operation) => MockPayloadGenerator.generate(operation, customMockResolvers)
I don't seem to be able to get the default values returned.
Currently, it is returning
{"allUsers":{"pageInfo":{"hasNextPage":false},"edges":[{"node":{"id":"<UserNode-mock-id-1>","firstName":"<mock-value-for-field-\"firstName\">","lastName":"<mock-value-for-field-\"lastName\">"}}]}}
What am I doing wrong?
When using the #relay-test-operation, the keys within your customMockResolvers object must match the type name of the fields, which can be different from the field names themselves.
For example, you could have the following in your schema:
type Foo {
id: ID!
name: String!
}
and the following query:
query FooQuery #relay_test_operation {
foo {
id
name
}
}
Then the customMockResolvers object would look like this:
const customMockResolvers = {
Foo: () => ({
id: "fooId",
name: "fooName"
})
}
Notice that I'm passing in Foo as the key instead of foo.
You can check your schema and see what the the type name of allUsers is. I suspect it would be something like AllUsers or allUsersConnection, or something similar.
Also, if you're interested in creating Storybook stories for Relay components, I created a NPM package just for that: https://www.npmjs.com/package/use-relay-mock-environment
It doesn't require adding the #relay-test-operation directive to your query, and instead relies only on resolving the String type (which is the default for all scalar properties). You can of course still add the #relay-test-operation directive and also extend the resolvers by providing customResolvers in the config.
You can also extend the the String resolver as well, by providing extendStringResolver in the config.
Feel free to review the source code here if you want to implement something similar: https://github.com/richardguerre/use-relay-mock-environment.
Note: it's still in its early days, so some things might change, but would love some feedback!

Passing Enum as variable to Relay Qraphql query

subscription userSubscription($filter: UserSubscriptionFilter!) {
User(filter: $filter) {
mutation
node {
name
addresses {
id
pincode
}
}
}}
in this subscription query i need to pass filter variable with value
const subscriptionConfig = {
subscription: updateQPListSubscription,
variables: {filter:{mutation_in: ["CREATED"]}},
However CREATED is an enum, how do i pass it as filter variable
If i hard-code in query itself then its working .... for example below query is working
subscription userSubscription {
User(filter: {mutation_in: [CREATED] node:{name_contains:"ankit"}}) {
mutation
node {
name
addresses {
id
pincode
}
}
}}
i want to pass the whole filter variable dynamically using the variables field when setting up the subscription
In graphcool playground also it does not work, however it accept the query variable i passed

Is it possible to access property value inside creatCriteria?

I have three domain classes as follows :
Case {
...
Reserve reserve
...
}
Reserve {
...
Amount amount
...
}
Amount {
...
Double value
String currency
...
}
I have a createcriteria as follows
List<Case> cases = []
cases = Case.createCriteria().list( ) {
/* I want to access currency of each case here */
}
Is it possible to access value of Currency for each Case inside the createCriteria? I am new to grails and I tried looking for documentation for this but couldn't find any.
like #cfrick commented:
def cases = Case.createCriteria().list {
reserve {
amount {
eq('currency', 'EUR')
}
}
}
You can use sqlRestriction() to write native sql query inside createCriteria.
More info here

Purpose of #relay(pattern:true)

New expression #relay(pattern: true) was introduced in change log for relay.js 0.5.
But can't figure out from description nor tests what exactly it does and when I should use it when writing fatQueries.
Some example would be very helpful.
Consider a GraphQL query like the following:
viewer {
friends(first: 10) {
totalCount
edges { node { name } }
pageInfo { hasNextPage }
}
}
When defining a fat query for a Relay mutation, to include the name of a field without specifying any of its subfields tells Relay that any subfield of that field could change as a result of that mutation.
Unfortunately, to omit connection arguments such as find, first, and last on the friends field will cause a validation error on the connection-argument-dependent fields edges and pageInfo:
getFatQuery() {
return Relay.QL`
fragment on AddFriendMutationPayload {
viewer {
friends { edges, pageInfo } # Will throw the validation error below
}
}
`;
}
// Uncaught Error: GraphQL validation/transform error ``You supplied the `pageInfo`
// field on a connection named `friends`, but you did not supply an argument necessary
// to do so. Use either the `find`, `first`, or `last` argument.`` in file
// `/path/to/MyMutation.js`.
You can use the #relay(pattern: true) directive to indicate that want to use the fat query to pattern match against the tracked query, instead of to use it as a fully-fledged query.
getFatQuery() {
return Relay.QL`
fragment on AddFriendMutationPayload #relay(pattern: true) {
viewer {
friends { edges, pageInfo } # Valid!
}
}
`;
}
For more information about mutations see: https://facebook.github.io/relay/docs/guides-mutations.html#content

Problem with GRAILS select - trying to insert a number for a field that appears as text in dropdown list

Here is the domain class I have defined:
package mypackage
public enum UFModeType {
I(0),
O(1),
R(3)
Integer mode
public UserFileModeType(Integer mode) {
this.mode = mode;
}
static list() {
[I, O, R]
}
}
This is a property of another domain Parent where it is as follows:
package mypackage
class Parent {
String name
... ... ...
UFModeType uFMode
static mapping = {
table 'parent_table_with_ufMode_col_as_number'
version false
tablePerHierarchy false
id generator:'sequence', params:[sequence:'myseq']
columns {
id column:'parentid'
uFMode column: 'UFMODE'
}
}
static constraints = {
userFileMode(nullable: true)
}
}
The gsp call for this looks like this:
g:select name="uFMode" from="${mypackage.UFModeType?.list()}" value="${parentInstance?.uFMode?.name()}" /
I have tried a lot of variants of the above in the gsp call but I am getting error that the db insert fails saying the entry of ufmode is invalid number, thus this is not being passed as a number. I printed the params in the controllers save and it shows this:
Params in save=[uFMode:I ...
I am sure I may be missing some minor thing in syntax, but I have tried a lot of things without much success, so any inputs will be greatly appreciated.
Thanks!
Try changing
value="${parentInstance?.uFMode?.name()}
to
value="${parentInstance?.uFMode?.mode()}
From the definition of UFModeType you give you do not have a name attribute.

Resources