2016-08-01 10 views
0

Ich versuche, eine Relay-Mutation zu codieren, die serverseitige Validierung ermöglicht. So wie ein Datensatz mit diesem Namen bereits existiert.Relay Mutation mit serverseitige Validierung

Unten ist meine GraphQL-Mutation.

/* @flow weak */ 
import {mutationWithClientMutationId,offsetToCursor} from "graphql-relay"; 
import {GraphQLString, GraphQLList, GraphQLNonNull} from "graphql"; 
import NominationConnection from '../NominationsConnection'; 
import ViewerType from '../../../types/ViewerType'; 
import Helper from '../../../helper/helper'; 
import Nomination from '../../../model/Nomination'; 


const mongo = require('mongodb'); 

/** 
* mutationWithClientMutationId() 
* 
* This helper function helps us create Relay-compliant GraphQL mutations it takes an object with the following params 
* { name: "", inputField: { }, outputFields: {}, mutateAndGetPayload: function({}) } 
* 
*/ 
export default mutationWithClientMutationId({ 

    // Name of the Mutation 
    name: "Nomination_Add", 

    // Describes the fields that should be used when invoking the mutation 
    inputFields: { 
    name: { 
     type: new GraphQLNonNull(GraphQLString) 
    }, 
    description: { 
     type: new GraphQLNonNull(GraphQLString) 
    }, 
    books: { 
     type: new GraphQLList(GraphQLString) 
    } 

    }, 

    // response that will be sent back when the mutation is complete 
    outputFields: { 
    NominationsEdge: { 
     type: NominationConnection.edgeType, 
     resolve: ({local_id}, { ...args }, context, { rootValue: objectManager }) => 
     { 
     //RT: local_id is the object that was inserted into DB.; 
     let nomination = local_id[0]; 
     console.log("nomination: ", nomination); 
     if(nomination.Errors.length > 0){ 

      return objectManager.getListBy('Nomination', nomination, {}, {}) 
       .then((arr) => { 

       return ({ 
        cursor: null, 
        node: nomination, 
       }) 
       }) 
     }else { 

      let an_Object; 
      return objectManager.getOneByParam('Nomination', nomination, {_id: nomination.id}) 
       .then((retrieved_Object) => { 


       an_Object = retrieved_Object; 

       }) 

       .then(() => objectManager.getListBy('Nomination', an_Object, {}, {}, objectManager.getViewerUserId())) 
       .then((arr) => { 


       return ({ 
        cursor: Helper.cursorForObjectInConnection(arr, an_Object, "id"), 
        node: an_Object, 
       }) 
       }) 
       ; 
     } 
     } 
    }, 

    Viewer: { 
     type: ViewerType, 
     resolve: (parent, args, context, {rootValue: objectManager}) => objectManager.getOneById('User', objectManager.getViewerUserId()) 
    } 
    }, 

    mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => { 
    if(!books){ 
     books = []; 
    } 

    return objectManager.add('Nomination', { 
     name, 
     description, 
     books 
    }, {name: name}).then((local_id) => ({local_id})); 
    } 
}); 

Unten ist meine Relais-Mutation.

/* @flow weak */ 

import Relay from 'react-relay'; 

export default class Nomination_addMutation extends Relay.Mutation { 
    // static fragments = { 
    // Viewer:() => Relay.QL` 
    //  fragment on Viewer { 
    //  id, 
    //  } 
    // `, 
    // }; 
    getMutation() { 

    return Relay.QL`mutation{Nomination_Add}`; 
    } 
    getFatQuery() { 


    return Relay.QL` 
     fragment on Nomination_AddPayload { 
     NominationsEdge, 
     Viewer { 
     Nominations(first:500){ 
     edges{ 
      node{ 
      id, 
      Name, 
      Description 
      } 
      } 
     } 
     } 
     } 
    `; 
    } 
    getConfigs() { 

    return [{ 
     type: 'RANGE_ADD', 
     parentName: 'Viewer', 
     parentID: this.props.Viewer.id, 
     connectionName: 'Nominations', 
     edgeName: 'NominationsEdge', 
     rangeBehaviors: { 
     // When the ships connection is not under the influence 
     // of any call, append the ship to the end of the connection 
     '': 'append', 
     // Prepend the ship, wherever the connection is sorted by age 
     // 'orderby(newest)': 'prepend', 
     }, 
    }]; 
    } 
    getVariables() { 

    return { 

     name: this.props.name, 
     description: this.props.description, 
     books: this.props.books, 
    }; 
    } 
    getOptimisticResponse() { 


    return { 
     Nomination: { 

     name: this.props.name, 
     description: this.props.description, 
     books: this.props.books, 

    }, 
     Viewer: { 
     id: this.props.Viewer.id, 
    }, 
    }; 
    } 
} 

Hier ist, wie ich darauf anrufe.

Mein Antwortobjekt hat nur die Viewer.id und clientmuationID nichts anderes. Wenn ich diese Mutation über graphql anrufe, sieht das so aus.

mutation{ 
    Nomination_Add(input:{name:"test", description:"test", clientMutationId:"2"}){ 
    NominationsEdge{ 
    node{ 
     Name, 
     Description, 
    Errors { 
     Message 
    } 
     Books{ 
     Title 
     } 
    } 
    } 
    } 

} 

mit einer Antwort davon.

Wie kann ich meine Server Validierung Fehlermeldungen zurück zum Client über Relais zu schreiben Logik gegen?

auch versucht, dies als meine Fett Abfrage

return Relay.QL` 
     fragment on Nomination_AddPayload { 
     NominationsEdge { 
     node{ 
      Errors { 
       Message 
      } 
      } 
     }, 
     Viewer { 
     Nominations(first:500){ 
     edges{ 
      node{ 
      id, 
      Name, 
      Description 
      } 
      } 
     } 
     } 
     } 
    `; 

Antwort wie folgt aussieht:

{,…} 
data 
: 
{Nomination_Add: {clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}}} 
Nomination_Add 
: 
{clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}} 
Viewer 
: 
{id: "00000000-0000-0000-0000-000000000000"} 
id 
: 
"00000000-0000-0000-0000-000000000000" 
clientMutationId 
: 
"0" 
+0

'Viewer: {id: "00000000-0000-0000-0000-000000000000"}' <- Können Sie überprüfen, ob Sie Ihrem Viewer-Objekt 'id' zugewiesen haben (nicht dem GraphQL-Typ, sondern dem Objekt, mit dem der GraphQL-Typ verknüpft ist)? –

+0

Ja, wir weisen dies gerade zu, solange die App noch erstellt wird. – jackncoke

+0

Was erhalten Sie, wenn Sie die folgende Abfrage in graphiql interface ausführen? 'Abfrage xyz { -Viewer { id, Nominierungen (zuerst: 1) { Kanten { Knoten { id, Name Beschreibung } } } } }' –

Antwort

0

Sie erhalten keine serverseitige Prüf-Fehlermeldungen, weil Sie nicht Relay gesagt haben, dass Sie will diese. Werfen Sie einen Blick auf Ihre GraphiQL-Mutation und die Fettabfrage Ihrer Relais-Mutation. Sie haben Errors in ersterem enthalten, aber nicht in letzterem.

Fügen Sie Errors in Ihrer Staffel Mutation (Nomination_addMutation) Fett Abfrage wie folgt:

fragment on Nomination_AddPayload { 
    NominationsEdge { 
     node { 
     Errors { 
      Message 
     } 
     } 
    }, 
    Viewer { 
    Nominations(first:500){ 
     edges{ 
     node{ 
      id, 
      Name, 
      Description 
     } 
     } 
    } 
    } 
} 
+0

Vielen Dank für Ihre Antwort . Ich hatte es auch versucht. Das Problem, auf das ich stoße, ist immer noch das gleiche. Rück Relay.QL' 'Fragment auf Nomination_AddPayload { NominationsEdge { Knoten { Errors { Nachricht } } }, { Viewers Nominierungs (zuerst: 500) { Kanten { Knoten { id, Name, Beschreibung } } } } } ';' gibt die gleiche Antwort – jackncoke

+0

Sie setzen 'Errors' Feld innerhalb' node' Feld in 'NominationsEdge'. Deshalb haben Sie nicht die erwartete Antwort erhalten. In meiner Antwort befindet sich das Feld "Errors" direkt in "NominationsEdge". –

+0

Vielen Dank für Ihre Hilfe! Ich habe das absichtlich gemacht, weil so mein Schema definiert ist. Fehler lebt auf NominationType. Soll es bewegt werden? – jackncoke

0

ich einen Fehler auf mutateAndGetPayload werfen kann: Dies wird als eine Fehlermeldung an den onFailure Rückruf der Mutation mit der versendet Fehlermeldung, was ich werfe.

mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => { 
    if(!books){ 
     books = []; 
    } 

    return objectManager.add('Nomination', { 
     name, 
     description, 
     books 
    }, {name: name}).then((nominations) => { 

     //RT: readability 
    let nomination = nominations[0]; 

     //RT: if Mongo id is not assigned. 
     // No records where created. 
     if(nomination.id == null) 
      throw nomination.Errors[0].Message; 

     return ({nomination} 

    )}); 
    } 

Dies scheint nicht der richtige Weg, dies zu tun. Hat jemand bessere Beispiele gesehen?

Edit: Code aufgeräumt und beschlossen, dies basierend auf diesen Beispielen zu tun. Scheint nicht richtig.

https://medium.com/@fcpgate/i-think-what-eslam-mentioned-is-more-on-the-right-track-cdd07519bf97#.na73ulbxj (Lesen Sie Kommentare.)

https://facebook.github.io/relay/docs/api-reference-relay-store.html

http://stackoverflow.duapp.com/questions/37044914/how-to-tackle-server-side-input-validation-using-relay?rq=1

https://github.com/facebook/relay/issues/696

+0

Durch Fehler zu werfen, können Sie höchstens einen Validierungsfehler auf der Client-Seite erhalten. Dies ist die einzige Einschränkung, wie ich sehe. –

+0

Es scheint, dass Sie zunächst (in Ihrem queston), gefolgt Art von dem gleichen Ansatz wie in [diesem Artikel] (https://medium.com/@tarkus/validation-and-user-errors-in-graphql-mutations-39ca79cd00bf# .e4p4rfw8x), was eigentlich ein sehr guter Ansatz ist. –

+0

Ja, ich genoss diesen Artikel und meine graphql Mutationen funktionieren genau so. Es wird empfohlen, die Mutationen so zu benutzen, wie ich es tue, ist mein Problem! – jackncoke