Skip to content

Instantly share code, notes, and snippets.

@harigopal
harigopal / let_env.rb
Last active November 27, 2019 10:05
A small helper method that temporarily changes environment variables in specs. It's an alternative to the ClimateControl rubygem that feels more like RSpec.
# A tiny RSpec helper
#
# spec/support/helpers/let_env.rb
module LetEnv
def let_env(name)
around do |example|
@original_environment_vars ||= {}
@original_environment_vars[name] ||= ENV[name.to_s]
ENV[name.to_s] = yield
@harigopal
harigopal / schema_and_query_type.rb
Last active November 10, 2019 09:50
Conventions for setting up a GraphQL Server on Rails - Schema & QueryType
# app/graphql/my_rails_app_schema.rb
class MyRailsAppSchema < GraphQL::Schema
mutation(Types::MutationType)
query(Types::QueryType)
end
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
# Add root-level fields here. They will be entry points for queries on your schema.
@harigopal
harigopal / routes_and_controller.rb
Last active November 10, 2019 09:34
Conventions for setting up a GraphQL Server on Rails - Routes & controllers
# config/routes.rb
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
end
post "/graphql", to: "graphql#execute"
# app/controllers/graphql_controller.rb
class GraphqlController < ApplicationController
def execute
@harigopal
harigopal / update_post_and_type.rb
Created November 5, 2019 14:40
Conventions for setting up a GraphQL Server on Rails - Custom types for mutations
# app/graphql/mutations/update_post.rb
module Mutations
class UpdatePost < GraphQL::Schema::Mutation
argument :post_id, ID, required: true
argument :description, String, required: true
description "Create a new post in a team"
field :post, Types::UpdatedPostType, null: true
field :errors, [String], null: false
@harigopal
harigopal / create_comment_mutator.rb
Last active November 6, 2019 19:56
Conventions for setting up a GraphQL Server on Rails - CreateCommentMutator
# app/queries/create_comment_mutator.rb
class CreateCommentMutator < ApplicationQuery
property :post_id
property :comment, validates: { length: { minimum: 1, maximum: 500 } }
validate :post_belongs_to_team
def post_belongs_to_team
return if post.present?
@harigopal
harigopal / create_comment.rb
Last active November 6, 2019 19:55
Conventions for setting up a GraphQL Server on Rails - Create a comment
# app/graphql/mutations/create_comment.rb
module Mutations
class CreateComment < GraphQL::Schema::Mutation
argument :post_id, ID, required: true
argument :comment, String, required: true
description "Create a comment on a post"
field :id, ID, null: true
field :errors, [String], null: false
@harigopal
harigopal / query_type_and_user_resolver.rb
Last active November 6, 2019 19:27
Conventions for setting up a GraphQL Server on Rails - Query a single user
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
field :user, Types::UserType, null: false do
argument :id, ID, required: true
end
def user
resolver = UserResolver.new(context, args)
resolver.user
@harigopal
harigopal / users_resolver.rb
Last active November 6, 2019 19:47
Conventions for setting up a GraphQL Server on Rails - UsersResolver
# app/queries/users_resolver.rb
class UsersResolver < ApplicationQuery
def users
scope = if current_user.admin?
User.all
else
current_user.team.users
end
# Avoid N+1 when accessing the avatar, with a shortcut for `.includes(avatar_attachment: :blob)`.
@harigopal
harigopal / query_type.rb
Last active November 6, 2019 19:43
Conventions for setting up a GraphQL Server on Rails - List users
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
field :users, [Types::UserType], null: false
def users
resolver = UsersResolver.new(context)
resolver.users
end
end
@harigopal
harigopal / application_query.rb
Last active November 6, 2019 19:36
Conventions for setting up a GraphQL Server on Rails - ApplicationQuery
# app/queries/application_query.rb
class ApplicationQuery
include ActiveModel::Model
# Set up accessors with validations in a single step.
def self.property(name, options = {})
attr_accessor name
validates(name, options[:validates]) if options.key?(:validates)
end