|
# GraphQL set for Tapas |
|
gem 'graphql' |
|
gem 'graphql-mutable_type' |
|
|
|
# Authorization Set |
|
gem 'rolify' |
|
gem 'pundit' |
|
|
|
# Config |
|
gem 'config' |
|
|
|
# Text Process |
|
gem 'redcarpet', '~> 3.3.4' |
|
gem 'rouge', '~> 1.8.0' |
|
gem 'auto-space' |
|
gem 'nokogiri' |
|
|
|
# RedisObject |
|
gem 'redis-objects' |
|
|
|
# Pagination |
|
gem 'kaminari' |
|
|
|
# Use ActiveModel has_secure_password |
|
gem 'bcrypt', '~> 3.1.7' |
|
|
|
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible |
|
gem 'rack-cors' |
|
|
|
gem 'paranoia', github: 'radar/paranoia', branch: 'core' if yes?('Using ActiveRecord?') |
|
|
|
# use rspec |
|
gem_group :development, :test do |
|
# pry |
|
gem 'pry-rails' |
|
|
|
# specs |
|
gem 'rspec-rails', '~> 3.0' |
|
gem 'factory_girl_rails', '~> 4.0' |
|
|
|
# code style |
|
gem 'rubocop', require: false |
|
end |
|
|
|
# Bundle |
|
run('bundle install') |
|
|
|
# initialize config |
|
generate(:'config:install') |
|
|
|
# initialize pundit |
|
generate(:'pundit:install') |
|
|
|
# initialize rspec |
|
generate(:'rspec:install') |
|
|
|
# initialize factory_girls |
|
file 'spec/support/factory_girl.rb', <<-CODE |
|
RSpec.configure do |config| |
|
config.include FactoryGirl::Syntax::Methods |
|
end |
|
CODE |
|
|
|
# load .rubocop.yml |
|
run('curl -O https://gist.githubusercontent.com/karloku/7776105e8ccc38405ecc/raw/23e5b5d1174292d3e31d951169a49f9675de4e5f/.rubocop.yml') |
|
|
|
# config graphql |
|
application "config.autoload_paths += Dir[Rails.root.join('app', 'graph', '*')]" |
|
run('mkdir app/graph') |
|
run('mkdir app/graph/errors') |
|
run('mkdir app/graph/helpers') |
|
run('mkdir app/graph/scalar_types') |
|
run('mkdir app/graph/types') |
|
run('mkdir app/graph/queries') |
|
run('mkdir app/graph/mutations') |
|
run('mkdir app/graph/mutation_types') |
|
|
|
## add GraphQL acronym inflection |
|
initializer 'inflections.rb', <<-CODE |
|
ActiveSupport::Inflector.inflections(:en) do |inflect| |
|
inflect.acronym 'GraphQL' |
|
end |
|
CODE |
|
|
|
## initialize graphql errors |
|
file 'app/graph/errors/custom_graphql_errors.rb', <<-CODE |
|
module CustomGraphQLErrors |
|
class Error < StandardError; end |
|
|
|
# add your own errrors here |
|
# class YourOwnError < Error; end |
|
end |
|
CODE |
|
|
|
## initialize graphql helpers set |
|
file 'app/graph/helpers/graphql_authorizer.rb', <<-CODE |
|
# Use Pundit in GraphQL |
|
module GraphQLArgumentProcessor |
|
# Module Methods |
|
module ModuleMethods |
|
def camel_keys_to_underscore(arguments) |
|
arguments.to_h |
|
.stringify_keys |
|
.transform_keys(&:underscore) |
|
.symbolize_keys |
|
end |
|
end |
|
|
|
extend ModuleMethods |
|
end |
|
CODE |
|
|
|
file 'app/graph/helpers/graphql_argument_processor.rb', <<-CODE |
|
# Use Pundit in GraphQL |
|
module GraphQLArgumentProcessor |
|
# Module Methods |
|
module ModuleMethods |
|
def camel_keys_to_underscore(arguments) |
|
arguments.to_h |
|
.stringify_keys |
|
.transform_keys(&:underscore) |
|
.symbolize_keys |
|
end |
|
end |
|
|
|
extend ModuleMethods |
|
end |
|
CODE |
|
|
|
file 'app/graph/helpers/graphql_authenticator.rb', <<-CODE |
|
# Authenticate user in GraphQL |
|
GraphQLAuthenticator = Struct.new(:object, :arguments, :context) do |
|
def authenticate(&block) |
|
authenticate_user! |
|
|
|
execute(&block) |
|
end |
|
|
|
def execute(&block) |
|
instance_exec(object, arguments, context, &block) if block_given? |
|
end |
|
|
|
def authenticate_user! |
|
fail TapasGraphQLErrors::AuthenticationError if current_user.blank? |
|
end |
|
|
|
def current_user |
|
@current_user ||= context.instance_variable_get(:'@values').present? && context[:current_user] |
|
end |
|
|
|
# Module Methods |
|
module ModuleMethods |
|
def authenticate(object, arguments, context, &block) |
|
authenticator = new(object, arguments, context) |
|
authenticator.authenticate(&block) |
|
end |
|
|
|
def execute(object, arguments, context, &block) |
|
authenticator = new(object, arguments, context) |
|
authenticator.execute(&block) |
|
end |
|
end |
|
|
|
extend ModuleMethods |
|
end |
|
|
|
CODE |
|
|
|
file 'app/graph/helpers/graphql_type_finder.rb', <<-CODE |
|
module GraphQLTypeFinder |
|
# Module Methods |
|
module ModuleMethods |
|
def find_by_name(name) |
|
types.detect { |type| name == type.name } |
|
end |
|
|
|
def types |
|
ObjectSpace.each_object(GraphQL::BaseType) |
|
end |
|
end |
|
|
|
extend ModuleMethods |
|
end |
|
CODE |
|
|
|
## initialize graphql extend scalar types |
|
file 'app/graph/scalar_types/date_type.rb', <<-CODE |
|
DateType = GraphQL::ScalarType.define do |
|
name 'Date' |
|
description 'ISO-8601 Format (YYYY-MM-DD\'T\'hh:mm:ss.sssZZZZZ)' |
|
|
|
coerce_input -> (value) { Time.zone.parse value } |
|
coerce_result -> (value) { value.as_json } |
|
end |
|
CODE |
|
|
|
## initialize query root |
|
file 'app/graph/query_type.rb', <<-CODE |
|
# frozen_string_literal: true |
|
QueryType = GraphQL::ObjectType.define do |
|
name 'Query' |
|
description 'Query Root' |
|
|
|
# Add your queries here |
|
# field :user, field: FetchField.create(User) |
|
|
|
# Put your query fields under: queries/ |
|
# Put your data types under: types/ |
|
end |
|
CODE |
|
|
|
## initialize mutation root |
|
file 'app/graph/mutation_type.rb', <<-CODE |
|
MutationType = GraphQL::ObjectType.define do |
|
name 'Mutation' |
|
description 'Mutation Root' |
|
|
|
# Add your mutations here |
|
# field :createUser, field: FetchField.create(User) |
|
|
|
# Put your mutations under: mutations/ |
|
# Define your mutation specific types under: mutation_types/ |
|
end |
|
CODE |
|
|
|
## initialize application schema |
|
file 'app/graph/application_schema.rb', <<-CODE |
|
ApplicationSchema = GraphQL::Schema.new( |
|
query: QueryType, |
|
mutation: MutationType |
|
) |
|
|
|
ApplicationSchema.instance_exec do |
|
CustomGraphQLErrors::Error.descendants.each do |error_klass| |
|
rescue_from error_klass, &:message |
|
end |
|
|
|
rescue_from Pundit::NotAuthorizedError do |
|
::I18n.t('pundit.errors.message.not_authorized') |
|
end |
|
end |
|
CODE |