我正在遵循在https://www.howtographql.com/graphql-ruby/0-introduction/上构建GraphQL API的绝对出色的教程
我的API框架是Grape,而Mongoid是我的数据库框架,但由于它使用ActiveRecord,因此其工作原理与rails非常相似
在使API端点正常工作并在现有REST API上定义了一些模型之后,我意识到我无法在子记录(数组)上编写方法和过滤器。我的感觉是,如果我在function
类的cost_codes
字段中添加JOBDATA::Types::JobType
参数,它将解析参数,但是由于加载顺序,这是不可能的。在解决此类问题的其他框架中,您可以将类包装为字符串,以便在加载应用程序后按需加载,但graphql不支持。
已更新:我可以使用require相对值解决加载问题,但是搜索类不再过滤父级的子级元素,而是调用JOBDATA::CostCode.all
并尝试加载整个集合
## this works on the parent, I have a custom method "orderBy"
{
allJobs(orderBy: ["jobNumber:asc"]) {
id,
createdAt,
updatedAt,
jobNumber,
description,
status,
costCodes { ## <-- by default returns the order of cost codes on the database
id,
createdAt,
updatedAt,
costCode,
description
}
}
}
我需要做什么
{
allJobs(orderBy: ["jobNumber:asc"]) {
id,
createdAt,
updatedAt,
jobNumber,
description,
status,
costCodes(orderBy: ["costCode:asc"]) {
id,
createdAt,
updatedAt,
costCode,
description
}
}
}
文件按以下顺序加载
module JOBDATA
## . . .
## GraphQL Files
Dir.glob('./graphql/types/*.rb') { |file| load file }
Dir.glob('./graphql/search_filters/*.rb') { |file| load file }
Dir.glob('./graphql/resolvers/*.rb') { |file| load file }
Dir.glob('./graphql/schemas/*.rb') { |file| load file }
end
首先加载的是'./graphql/types/cost_code_type.rb'
module JOBDATA
module Types
class CostCodeType < GraphQL::Introspection::BaseObject
field :id, GraphQL::Types::ID, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
field :cost_code, GraphQL::Types::String, null: false
field :description, GraphQL::Types::String, null: true
field :status, GraphQL::Types::String, null: false
end
end
end
第二'./graphql/types/job_type.rb'
module JOBDATA
module Types
class JobType < GraphQL::Introspection::BaseObject
field :id, GraphQL::Types::ID, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
field :job_number, GraphQL::Types::String, null: false
field :description, GraphQL::Types::String, null: true
field :status, GraphQL::Types::String, null: false
field :cost_codes, [JOBDATA::Types::CostCodeType], null: false
## this seems like it should work - but because of the required load order I
## I can force it using require relative, but rather than returning only the
## parents children it returns everything for that collection agnostic to the
## parent (its connected via has_many relationship on the parent)
# field :cost_codes, [JOBDATA::Types::CostCodeType], null: false, function: JOBDATA::SearchFilters::CostCode
end
end
end
第三'./graphql/search_filters/cost_code_search_filter.rb'
module JOBDATA
module SearchFilters
class CostCode
include SearchObject.module(:graphql)
scope { JOBDATA::CostCode.all }
type types[JOBDATA::Types::CostCodeType]
option :orderBy, type: types[types.String], with: :apply_order_by, default: ['cost_code:asc']
def apply_order_by(scope, value)
order_by = []
value.each do |field|
pair = field.split(':')
order_by.push([pair[0].underscore, pair[1].downcase])
end
scope.order_by(order_by)
end
end
end
end
第四'./graphql/search_filters/job_search_filter.rb'
module JOBDATA
module SearchFilters
class Job
include SearchObject.module(:graphql)
scope { JOBDATA::Job.all }
type types[JOBDATA::Types::JobType]
option :orderBy, type: types[types.String], with: :apply_order_by, default: ['job_number:asc']
def apply_order_by(scope, value)
order_by = []
value.each do |field|
pair = field.split(':')
order_by.push([pair[0].underscore, pair[1].downcase])
end
scope.order_by(order_by)
end
end
end
end