First simple API version with autogenerated GraphQL types

This commit is contained in:
Alberto Miedes Garcés
2016-11-08 17:40:13 +01:00
parent e7de5c3a7f
commit 277c784234
5 changed files with 125 additions and 8 deletions

View File

@@ -0,0 +1,26 @@
class ExposableField
attr_reader :name, :graphql_type
def initialize(column, options = {})
@name = column.name
@graphql_type = ExposableField.convert_type(column.type)
end
private
# Return a GraphQL type for 'database_type'
def self.convert_type(database_type)
case database_type
when :integer
GraphQL::INT_TYPE
when :boolean
GraphQL::BOOLEAN_TYPE
when :float
GraphQL::FLOAT_TYPE
when :double
GraphQL::FLOAT_TYPE
else
GraphQL::STRING_TYPE
end
end
end

View File

@@ -0,0 +1,31 @@
class ExposableModel
attr_reader :exposed_fields, :name, :description
def initialize(model_class, options = {})
@model_class = model_class
@filter_list = options[:filter_list] || []
@name = model_class.name
@description = model_class.model_name.human
@filter_strategy = options[:filter_strategy]
set_exposed_fields
end
private
# determine which model fields are exposed to the API
def set_exposed_fields
case @filter_strategy
when :whitelist
@exposed_fields = @model_class.columns.select do |column|
@filter_list.include? column.name
end
when :blacklist
@exposed_fields = @model_class.columns.select do |column|
!(@filter_list.include? column.name)
end
else
@exposed_fields = []
end
end
end

View File

@@ -3,7 +3,7 @@ QueryRoot = GraphQL::ObjectType.define do
description "The query root for this schema"
field :proposal do
type ProposalType
type TYPE_BUILDER.types[Proposal]
description "Find a Proposal by id"
argument :id, !types.ID
resolve -> (object, arguments, context) {
@@ -11,7 +11,8 @@ QueryRoot = GraphQL::ObjectType.define do
}
end
connection :proposals, ProposalType.connection_type do
field :proposals do
type types[TYPE_BUILDER.types[Proposal]]
description "Find all Proposals"
resolve -> (object, arguments, context) {
Proposal.all
@@ -19,7 +20,7 @@ QueryRoot = GraphQL::ObjectType.define do
end
field :debate do
type DebateType
type TYPE_BUILDER.types[Debate]
description "Find a Debate by id"
argument :id, !types.ID
resolve -> (object, arguments, context) {
@@ -27,7 +28,8 @@ QueryRoot = GraphQL::ObjectType.define do
}
end
connection :debates, DebateType.connection_type do
field :debates do
type types[TYPE_BUILDER.types[Debate]]
description "Find all Debates"
resolve -> (object, arguments, context) {
Debate.all
@@ -35,7 +37,7 @@ QueryRoot = GraphQL::ObjectType.define do
end
field :comment do
type CommentType
type TYPE_BUILDER.types[Comment]
description "Find a Comment by id"
argument :id, !types.ID
resolve -> (object, arguments, context) {
@@ -43,7 +45,8 @@ QueryRoot = GraphQL::ObjectType.define do
}
end
connection :comments, CommentType.connection_type do
field :comments do
type types[TYPE_BUILDER.types[Comment]]
description "Find all Comments"
resolve -> (object, arguments, context) {
Comment.all
@@ -51,7 +54,7 @@ QueryRoot = GraphQL::ObjectType.define do
end
field :user do
type UserType
type TYPE_BUILDER.types[User]
description "Find a User by id"
argument :id, !types.ID
resolve -> (object, arguments, context) {

57
app/graph/type_builder.rb Normal file
View File

@@ -0,0 +1,57 @@
class TypeBuilder
attr_reader :filter_strategy, :graphql_models
def initialize(graphql_models, options = {})
@graphql_models = graphql_models
@graphql_types = {}
# determine filter strategy for this field
if (options[:filter_strategy] == :blacklist)
@filter_strategy = :blacklist
else
@filter_strategy = :whitelist
end
create_all_types
end
def types
@graphql_types
end
private
def create_all_types
@graphql_models.keys.each do |model_class|
@graphql_types[model_class] = create_type(model_class)
end
end
def create_type(model_class)
type_builder = self
graphql_type = GraphQL::ObjectType.define do
em = ExposableModel.new(model_class, filter_strategy: type_builder.filter_strategy, filter_list: type_builder.graphql_models[model_class])
name(em.name)
description(em.description)
em.exposed_fields.each do |column|
ef = ExposableField.new(column)
field(ef.name, ef.graphql_type)
end
end
return graphql_type
end
end
graphql_models = {}
graphql_models.store(User, ['id', 'username'])
graphql_models.store(Proposal, ['id', 'title', 'description', 'author_id', 'created_at'])
graphql_models.store(Debate, ['id', 'title', 'description', 'author_id', 'created_at'])
graphql_models.store(Comment, ['id', 'commentable_id', 'commentable_type', 'body'])
graphql_models.store(Geozone, ['id', 'name', 'html_map_coordinates'])
TYPE_BUILDER = TypeBuilder.new(graphql_models, filter_strategy: :whitelist)

View File

@@ -46,7 +46,7 @@ module Consul
config.paths['app/views'].unshift(Rails.root.join('app', 'views', 'custom'))
# Add GraphQL directories to the autoload path
config.autoload_paths << Rails.root.join('app', 'graph', 'types')
config.autoload_paths << Rails.root.join('app', 'graph')
end
end