Why doesn't my registration mutation work with the role field? - phoenix-framework

Why doesn't my registration mutation work with the role field?
I written the following code but can't figure out why my role enum doesn't work with my mutation.
I uploaded my code to github Github code.
The registration mutation works:
mutation{
registerUser(input:{email:"a#a.com", password:"a#a.com", role:"user",passwordConfirmation:"a#a.com"}){
email
}
}
But when i try my login mutation it fails:
mutation{
loginUser(input:{email:"a#a.com", password:"a#a.com", role:"user"}){
token
user{
email
}
}
}
And I get this error::
"# KeyError at POST /api/graphiql\n\nException:\n\n
** (KeyError) key :role not found in: %{email: \"a#a.com\", password: \"a#a.com\"}\n

So what i was doing wrong was answered for me on the elixirforum by #benwilson512.
The following assumption of mine that I can use field(:role, :user_input) to get the input type form my user_input was incorrect.
If I want to pass down the role to my mutation the best way is to use field(:role, non_null(:string)) and treated as a string.
But still i am not sure what is the best way to deal with this, although this solves the problem I was having.
So thanks everyone that looked over my question.

Also if you want to restrict the role to the enum values then the following should work:
field(:role, :type :role) and then the enum for the role with the values.
This answer was offered by #kokolegorille on elixirforum.
That solves the problem

Related

Is it possible a schema type that gets the value of one property of already defined schema type

I have a schema that looks like this.
exports.typeDefs = gql`
type User {
userid: ID!
name: String
}
type Post {
post_id: ID!
post_category: String!
post_type: String!
post_hashtag: String
user: User
}
`;
Now post have the field named "post_hashtag".
I want to define another schema type and get that post_hashtag property for all the nodes in post type.
of post.
I tried the below type hashtag and put a cipher query on that.
type hashtag{
post_hashtag: String
#cypher[statement: "MATCH (n:Test_Temp) RETURN n.post_hashtag"]
}
But it returns only the one first found hashtag and save it on hashtag node. This is not what I want. I want all the hashtags that are available in any post_hashtag node.
Example: If I query
query{
hashtag{
post_hashtag
}
}
This should give all the hashtags that are available in any of the post node but instead it return only one hashtag.
I've been trying this since few days. going through different solutions but none worked.
Any suggestions Please.
I've figured out the problem. Actually, we just need to use the collect method of neo4j to return an array of hashtags and save it in the hashtag node. And it will save all the hashtags on the node and we can retrieve them later.
First, change the schema a little bit like this.
type hashtag{
post_hashtag: [String]
#cypher[statement: "MATCH (n:Test_Temp) RETURN
n.post_hashtag"]
}
Notice: I've changed the post_hashtag type and made it an array of strings.
Then just the cipher query will change by the one down below.
MATCH (n:Test_Temp) RETURN collect(n.post_hashtag)
And it is done.

Is it possible to add a layer of grouping under query in graphql? [duplicate]

All docs and tutorials usually show simple examples of mutations that look like this:
extend type Mutation {
edit(postId: String): String
}
But this way the edit method has to be unique across all entities, which to me seems like not a very robust way to write things. I would like to describe mutation similar to how we describe Queries, something like this:
type PostMutation {
edit(postId: String): String
}
extend type Mutation {
post: PostMutation
}
This seems to be a valid schema (it compiles and I can see it reflected in the generated graph-i-ql docs). But I can't find a way to make resolvers work with this schema.
Is this a supported case for GraphQL?
It's possible but generally not a good idea because:
It breaks the spec. From section 6.3.1:
Because the resolution of fields other than top‐level mutation fields must always be side effect‐free and idempotent, the execution order must not affect the result, and hence the server has the freedom to execute the field entries in whatever order it deems optimal.
In other words, only fields on the mutation root type should have side effects like CRUD operations.
Having the mutations at the root makes sense conceptually. Whatever action you're doing (liking a post, verifying an email, submitting an order, etc.) doesn't rely on GraphQL having to resolve additional fields before the action is taken. This is unlike when you're actually querying data. For example, to get comments on a post, we may have to resolve a user field, then a posts field and then finally the comments field for each post. At each "level", the field's contents are dependent on the value the parent field resolved to. This normally is not the case with mutations.
Under the hood, mutations are resolved sequentially. This is contrary to normal field resolution which happens in parallel. That means, for example, the firstName and lastName of a User type are resolved at the same time. However, if your operation type is mutation, the root fields will all be resolved one at a time. So in a query like this:
mutation SomeOperationName {
createUser
editUser
deleteUser
}
Each mutation will happen one at a time, in the order that they appear in the document. However, this only works for the root and only when the operation is a mutation, so these three fields will resolve in parallel:
mutation SomeOperationName {
user {
create
edit
delete
}
}
If you still want to do it, despite the above, this is how you do it when using makeExecutableSchema, which is what Apollo uses under the hood:
const resolvers = {
Mutation: {
post: () => ({}), // return an empty object,
},
PostMutation: {
edit: () => editPost(),
},
// Other types here
}
Your schema defined PostMutation as an object type, so GraphQL is expecting that field to return an object. If you omit the resolver for post, it will return null, which means none of the resolvers for the returning type (PostMutation) will be fired. That also means, we can also write:
mutation {
post
}
which does nothing but is still a valid query. Which is yet another reason to avoid this sort of schema structure.
Absolutely disagree with Daniel!
This is an amazing approach which helps to frontenders fastly understand what operations have one or another resource/model. And do not list loooong lists of mutations.
Calling multiple mutations in one request is common antipattern. For such cases better to create one complex mutation.
But even if you need to do such operation with several mutations you may use aliases:
await graphql({
schema,
source: `
mutation {
op1: article { like(id: 1) }
op2: article { like(id: 2) }
op3: article { unlike(id: 3) }
op4: article { like(id: 4) }
}
`,
});
expect(serialResults).toEqual([
'like 1 executed with timeout 100ms',
'like 2 executed with timeout 100ms',
'unlike 3 executed with timeout 5ms',
'like 4 executed with timeout 100ms',
]);
See the following test case: https://github.com/nodkz/conf-talks/blob/master/articles/graphql/schema-design/tests/mutations-test.js
Methods like/unlike are async with timeouts and works sequentially

GraphQL: Mutation inside Query Object [duplicate]

All docs and tutorials usually show simple examples of mutations that look like this:
extend type Mutation {
edit(postId: String): String
}
But this way the edit method has to be unique across all entities, which to me seems like not a very robust way to write things. I would like to describe mutation similar to how we describe Queries, something like this:
type PostMutation {
edit(postId: String): String
}
extend type Mutation {
post: PostMutation
}
This seems to be a valid schema (it compiles and I can see it reflected in the generated graph-i-ql docs). But I can't find a way to make resolvers work with this schema.
Is this a supported case for GraphQL?
It's possible but generally not a good idea because:
It breaks the spec. From section 6.3.1:
Because the resolution of fields other than top‐level mutation fields must always be side effect‐free and idempotent, the execution order must not affect the result, and hence the server has the freedom to execute the field entries in whatever order it deems optimal.
In other words, only fields on the mutation root type should have side effects like CRUD operations.
Having the mutations at the root makes sense conceptually. Whatever action you're doing (liking a post, verifying an email, submitting an order, etc.) doesn't rely on GraphQL having to resolve additional fields before the action is taken. This is unlike when you're actually querying data. For example, to get comments on a post, we may have to resolve a user field, then a posts field and then finally the comments field for each post. At each "level", the field's contents are dependent on the value the parent field resolved to. This normally is not the case with mutations.
Under the hood, mutations are resolved sequentially. This is contrary to normal field resolution which happens in parallel. That means, for example, the firstName and lastName of a User type are resolved at the same time. However, if your operation type is mutation, the root fields will all be resolved one at a time. So in a query like this:
mutation SomeOperationName {
createUser
editUser
deleteUser
}
Each mutation will happen one at a time, in the order that they appear in the document. However, this only works for the root and only when the operation is a mutation, so these three fields will resolve in parallel:
mutation SomeOperationName {
user {
create
edit
delete
}
}
If you still want to do it, despite the above, this is how you do it when using makeExecutableSchema, which is what Apollo uses under the hood:
const resolvers = {
Mutation: {
post: () => ({}), // return an empty object,
},
PostMutation: {
edit: () => editPost(),
},
// Other types here
}
Your schema defined PostMutation as an object type, so GraphQL is expecting that field to return an object. If you omit the resolver for post, it will return null, which means none of the resolvers for the returning type (PostMutation) will be fired. That also means, we can also write:
mutation {
post
}
which does nothing but is still a valid query. Which is yet another reason to avoid this sort of schema structure.
Absolutely disagree with Daniel!
This is an amazing approach which helps to frontenders fastly understand what operations have one or another resource/model. And do not list loooong lists of mutations.
Calling multiple mutations in one request is common antipattern. For such cases better to create one complex mutation.
But even if you need to do such operation with several mutations you may use aliases:
await graphql({
schema,
source: `
mutation {
op1: article { like(id: 1) }
op2: article { like(id: 2) }
op3: article { unlike(id: 3) }
op4: article { like(id: 4) }
}
`,
});
expect(serialResults).toEqual([
'like 1 executed with timeout 100ms',
'like 2 executed with timeout 100ms',
'unlike 3 executed with timeout 5ms',
'like 4 executed with timeout 100ms',
]);
See the following test case: https://github.com/nodkz/conf-talks/blob/master/articles/graphql/schema-design/tests/mutations-test.js
Methods like/unlike are async with timeouts and works sequentially

Documenting GraphQL short-hand model

How does one document the model, using GraphQL shorthand notation?
type User {
name: String
}
Say I want to add a description for the type/attribute above.
Descriptions come in the form of comments:
# Someone who uses something
type User {
# How we refer to the user
name: String
}
Those should be added as descriptions to the schema generated from this notation.

Custom validation of Play 2.0 form (scala)

I'm writing a little hobby app. Now, in my application I want people to have a userId (just like mine is niklassaers here on stack overflow), and if it is already taken, I want the user to get an error so he can select another.
Here follows my Signup object, it gives me an error at the line "mapping(": "missing arguments for method mapping in object Forms; follow this method with `_' if you want to treat it as a partially applied function"
object Signup extends Controller {
val userForm: Form[UserProfile] = Form(
mapping(
"userId" -> nonEmptyText,
"passwordHash" -> nonEmptyText,
"email" -> email
) verifying (
"ThisIsATest", { case(userId, passwordHash, email) => true }
// "UserID already taken", { DBService.exists(UserProfile.getClass().getName(), userId) }
)(UserProfile.apply)(UserProfile.unapply))
def index = Action {
Ok(views.html.signup(userForm))
}
def register = Action { implicit request =>
userForm.bindFromRequest.fold(
errors => BadRequest(views.html.signup(errors)),
user => Redirect(routes.Profile.index))
}
}
As you can see, I've replaced my lookup service with a test verification that simply returns true, to make the example less complex. For completeness, this is my UserDetail case class:
case class UserProfile(
userId : String,
email: String,
passwordHash: String)
I'm a Scala newbie and Play newbie, so I'm sorry if this is a very trivial question. But:
What am I doing wrong since I get this error?
Is this the right way of adding my own validation?
Follow-up question: I redirect if it goes well, but how should I redirect to a page referencing the just verified form?
Cheers
Nik
Finally got around this: verifying isn't something that comes after mapping, it is something that comes at the constraint. So it should be
"userId" -> nonEmptyText.verifying( "UserID already taken", userId => DBService.exists(UserProfile.getClass().getName().replace("$", ""), userId) == false ),
I hope this helps others that have the same problem :-)
A little late, but anyway..
You can do validation on the whole "form-backing object" instead of just a single field as you ended up with. This is similar to the first code you posted in your problem description. The problem is that your verifying block needs to be after the apply/unapply statements.
case class UserRegistration(username: String, password1: String, password2: String)
val loginForm = Form(
mapping(
"username" -> email,
"password1" -> text,
"password2" -> text
)
(UserRegistration.apply)(UserRegistration.unapply)
verifying ("Passwords must match", f => f.password1 == f.password2)
)
Even later, but anyway... :)
Using verifying on the entire "form backing object" doesn´t let you add errors to individual fields in the form. If you want to do that see Play! framework 2.0: Validate field in forms using other fields

Resources