How do I accept field arguments for a nested query in Graphql Ruby? - graphql

I'm getting this error in GraphQl (Apollo JS/ Graphql Ruby):
Error Error: GraphQL error: Field 'pagination' doesn't accept argument 'pagination' GraphQL error: Variable $pagination is declared by Clients but not used. Reload the page and try again.
I have this query:
query Clients($pagination: PaginationInput) {
clients {
data {
....Fragment
}
pagination(pagination: $pagination) {
....Fragment
}
}
}
And I have this as my input type:
class PaginatedClientsType < Types::BaseObject
field :data, ...
field :pagination, PaginationType ... do
argument :pagination, PaginationInput, required: false
end
end
And this in my query_type.rb file:
field :clients, ::Types::Paginated::ClientsType, null: false do
argument :pagination, PaginationInput, required: false
end
def clients(pagination:)
...
end
// and i've added to no avail:
field :pagination ... do
argument :pagination, PaginationInput, required: false
end
def pagination(pagination:)
...
end
Any ideas on how I can pass the argument to something other than this top level client?
I've read docs here but can't figure it out.
Thanks!

Related

how to return both error and data in graphql

There are user and notes fields.
If the notes field exceeds the limit, I want to get an error with the data
But I don't know what to do. (Currently only an error is returned.)
Is it possible to return both the error and the data?
as it
errors = {xx}
to be
data = {user: { notes: []}}
errors = {xx}
my code is as follows
app/graphql/types/object_types/user.rb
module Types
module ObjectTypes
class User < Types::ObjectTypes::BaseObject
graphql_name 'User'
implements GraphQL::Types::Relay::Node
field :notes, [Types::ObjectTypes::Note], null: true do
description ''
argument :date_from, GraphQL::Types::ISO8601Date, required: true
argument :date_to, GraphQL::Types::ISO8601Date, required: true
end
def notes(date_from:, date_to:)
object.notes.date_between(date_from, date_to).tap { |array| raise AppError if array.size > 1000 }
end

How to add element on graphql return fields

Im a newbie in Ruby and GraphQL
Currently i have such Mutations module
module Mutations
class ProductCreate < BaseMutation
# TODO: define return fields
# field :post, Types::PostType, null: false
type Types::ProductType
# TODO: define arguments
argument :title, String, required: true
argument :vendor, String, required: false
argument :store, ID, required: true
# TODO: define resolve method
def resolve(title:, vendor:, store:)
Product.create!(title: title, vendor: vendor, store: store)
end
end
end
and when i call
mutation {
productCreate(input: {store:"61d6f33a58c4dc4e8a1a0536", title: "Sweet new product", vendor: "JadedPixel"})
{
_id
}
}
Result is
{
"data": {
"productCreate": {
"_id": "61de591c58c4dcb08dffafa9"
}
}
}
I would like to add additional paramenter to query and also get additional paramenter in result
So, my question is
What should i change in code
mutation {
productCreate(input: {title: "Sweet new product", productType: "Snowboard", vendor: "JadedPixel"}) {
product {
id
}
}
}
to get result like this
{
"productCreate": {
"product": {
"id": "1071559610"
}
}
}
I found solutions
Just need to change code like this
module Mutations
class ProductCreate < BaseMutation
field :product, Types::ProductType, null: true
# TODO: define arguments
argument :title, String, required: true
argument :vendor, String, required: false
argument :store, ID, required: true
# TODO: define resolve method
def resolve(title:, vendor:, store:)
record = Product.create!(title: title, vendor: vendor, store: store)
{ product: record }
end
end
end
source of an example
https://www.keypup.io/blog/graphql-the-rails-way-part-2-writing-standard-and-custom-mutations

passing arguments in graphQL queries

I'm just starting to learn GraphQL and I'm currently trying to create a clone of twitter. In the code below, is there a way I can pass the 81 from the id argument (e.g. user(id: 81)) automatically to the userId argument (e.g. tweets(userId: 81))?
I've copied my code below
{
user(id: 81) {
username
email
tweets(userId: 81) {
content
}
}
}
user_type.rb
module Types
class UserType < Types::BaseObject
field :username, String, null: false
field :email, String, null: false
field :bio, String, null: true
field :tweets, [Types::TweetType], null: true do
argument :user_id, ID, required: true
end
def tweets(user_id:)
Tweet.where(user_id: user_id)
end
end
end
tweet_type.rb
module Types
class TweetType < Types::BaseObject
field :id, ID, null: false
field :content, String, null: false
field :userId, ID, null: false
field :createdAt, GraphQL::Types::ISO8601DateTime, null: false
field :user, Types::UserType, null: false
end
end
query_type.rb
module Types
class QueryType < Types::BaseObject
field :tweets,
[Types::TweetType],
null: false,
description: "Returns a list of all tweets"
field :user,
Types::UserType,
null: false,
description: "Returns a list of all users" do
argument :id, ID, required: true
end
def tweets
Tweet.all
end
def user(id:)
User.find(id)
end
end
end
GraphQL has a first-class way to factor dynamic values out of the query, and pass them as a separate dictionary (variables). You would use syntax similar to that below, and can read more about it here.
query User($id: Int) {
user(id: $id) {
username
email
tweets(userId: $id) {
content
}
}
}

How to do POST request to Grape REST API using params block compatible with Swagger

I am using grape to build a REST API, I am having some trouble with params options.
This is how I do a POST request:
# Curl Request
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"title":"hello","body":"world"}'
# {"error":"article is missing"}
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"article":{title":"hello","body":"world"}}'
# {"error":"article is invalid"}
As you can see if I omit article it fails article missing, If i put article and it fails article invalid.
This is the code, I am using grape-entity.
# Entity
module API
module Entities
class Article < Grape::Entity
expose :title, documentation: { type: 'string', desc: 'Title' }
expose :body, documentation: { type: 'string', desc: 'Body' }
end
end
end
# API
desc "Create an article"
params do
requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end
post '/articles' do
puts params
article = Article.create(params(:title, :body))
represent(article, env)
end
# Add Swagger Docs
add_swagger_documentation mount_path: 'api/doc',
api_version: 'v1',
markdown: GrapeSwagger::Markdown::KramdownAdapter,
hide_documentation_path: true,
base_path: Application.config.base_path,
models: [API::Entities::Article]
Specifically the problem is caused by params block, it requires an :article of type API:Entities::Article.
Also note that, I am using add-swagger-documentation, and this code
produces correct swagger documentation, so the solution have to be
fully compatible with swagger. What is the correct usage of params
block without offending the swagger.
I'm not sure what you're trying to accomplish here. I guess you want to change your post method in a way that it accepts a JSON like this:
{ attribute1: value, attribute2: value }
instead of
{ article: { attribute1: value, attribute2: value } }
In this case, you have to change your params block to something like this
params do
requires :attribute1, type: String, documentation: { eg: "aklsdfj" }
requires :attribute2, type: String, documentation: { eg: "aklsdfj" }
end
instead of
params do
requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end
The params block above is expecting a JSON containing an article attribute composed by every attribute defined in the entity API::Entities::Article.
In fact, Grape doesn't accept entity objects as a type for a parameter.

tire terms filter not working

I'm trying to achieve a "scope-like" function with tire/elasticsearch. Why is this not working, even when i have entries with status "Test1" or "Test2"? The results are always empty.
collection = #model.search(:page => page, :per_page => per_page) do |s|
s.query {all}
s.filter :terms, :status => ["Test1", "Test2"]
s.sort {by :"#{column}", "#{direction}"}
end
The method works fine without the filter. Is something wrong with the filter method?! I've checked the tire doku....it should work.
Thanks! :)
Your issue is most probably being caused by using the default mappings for the status field, which would tokenize it -- downcase, split into words, etc.
Compare these two:
http://localhost:9200/myindex/_analyze?text=Text1&analyzer=standard
http://localhost:9200/myindex/_analyze?text=Text1&analyzer=keyword
The solution in your case is to use the keyword analyzer (or set the field to not_analyzed) in your mapping. When the field would not be an “enum” type of data, you could use the multi-field feature.
A working Ruby version would look like this:
require 'tire'
Tire.index('myindex') do
delete
create mappings: {
document: {
properties: {
status: { type: 'string', analyzer: 'keyword' }
}
}
}
store status: 'Test1'
store status: 'Test2'
refresh
end
search = Tire.search 'myindex' do
query do
filtered do
query { all }
filter :terms, status: ['Test1']
end
end
end
puts search.results.to_a.inspect
Note: It's rarely possible -- this case being an exception -- to offer reasonable advice when no index mappings, example data, etc. are provided.

Resources