Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphql setup #28

Open
wants to merge 6 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ gem "loofah", ">= 2.2.3"
gem 'webpacker'
gem 'react-rails'

gem 'rb-readline'
gem 'graphql'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

Expand All @@ -101,3 +104,5 @@ end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gem 'graphiql-rails', group: :development
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ GEM
fraction (0.3.2)
globalid (0.4.2)
activesupport (>= 4.2.0)
graphiql-rails (1.7.0)
railties
sprockets-rails
graphql (1.9.3)
hashid-rails (1.2.2)
activerecord (>= 4.0)
hashids (~> 1.0)
Expand Down Expand Up @@ -207,6 +211,7 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rb-readline (0.5.5)
react-rails (2.4.7)
babel-transpiler (>= 0.7.0)
connection_pool
Expand Down Expand Up @@ -297,6 +302,8 @@ DEPENDENCIES
faker (= 1.7.3)
ffi (>= 1.9.24)
fraction (~> 0.3.2)
graphiql-rails
graphql
hashid-rails (~> 1.2, >= 1.2.1)
jbuilder (~> 2.5)
jquery-rails (~> 4.3, >= 4.3.1)
Expand All @@ -314,6 +321,7 @@ DEPENDENCIES
rack (>= 2.0.6)
rails (~> 5.1.4)
rails-controller-testing
rb-readline
react-rails
rubyzip (>= 1.2.2)
sass-rails
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
protect_from_forgery unless: -> { request.format.json? }
include SessionsHelper
include ActionController::Helpers

Expand Down
43 changes: 43 additions & 0 deletions app/controllers/graphql_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class GraphqlController < ApplicationController
def execute
variables = ensure_hash(params[:variables])
query = params[:query]
operation_name = params[:operationName]
context = {
# Query context goes here, for example:
# current_user: current_user,
}
result = StockcubeAppSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
render json: result
rescue => e
raise e unless Rails.env.development?
handle_error_in_development e
end

private

# Handle form data, JSON body, or a blank value
def ensure_hash(ambiguous_param)
case ambiguous_param
when String
if ambiguous_param.present?
ensure_hash(JSON.parse(ambiguous_param))
else
{}
end
when Hash, ActionController::Parameters
ambiguous_param
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
end
end

def handle_error_in_development(e)
logger.error e.message
logger.error e.backtrace.join("\n")

render json: { error: { message: e.message, backtrace: e.backtrace }, data: {} }, status: 500
end
end
Empty file added app/graphql/mutations/.keep
Empty file.
4 changes: 4 additions & 0 deletions app/graphql/stockcube_app_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class StockcubeAppSchema < GraphQL::Schema
# mutation(Types::MutationType)
query(Types::QueryType)
end
Empty file added app/graphql/types/.keep
Empty file.
4 changes: 4 additions & 0 deletions app/graphql/types/base_enum.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Types
class BaseEnum < GraphQL::Schema::Enum
end
end
4 changes: 4 additions & 0 deletions app/graphql/types/base_input_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Types
class BaseInputObject < GraphQL::Schema::InputObject
end
end
5 changes: 5 additions & 0 deletions app/graphql/types/base_interface.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Types
module BaseInterface
include GraphQL::Schema::Interface
end
end
3 changes: 3 additions & 0 deletions app/graphql/types/base_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Types::BaseObject < GraphQL::Schema::Object
field :limit, Integer, null: true
end
4 changes: 4 additions & 0 deletions app/graphql/types/base_scalar.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Types
class BaseScalar < GraphQL::Schema::Scalar
end
end
4 changes: 4 additions & 0 deletions app/graphql/types/base_union.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Types
class BaseUnion < GraphQL::Schema::Union
end
end
12 changes: 12 additions & 0 deletions app/graphql/types/cupboard_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Types::CupboardType < Types::BaseObject
field :id, ID, null: false
field :users, [Types::UserType], "The users associated to this cupboard", null: false
field :stocks, [Types::StockType], "The stock in this cupboard", null: true
field :location, String, null: true
field :created_at, String, null: false
field :updated_at, String, null: false
field :hidden, Boolean, null: true
field :setup, Boolean, null: true
field :communal, Boolean, null: true
field :stocks, [Types::StockType], "The stock in this cupboard", null: false
end
20 changes: 20 additions & 0 deletions app/graphql/types/date.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# app/graphql/types/date.rb
class Types::Date < Types::BaseScalar
description "A valid Date, transported as a DateTime"

def self.coerce_input(input_value, context)
# Parse the incoming object into a `DateTime`
date = input_value.to_datetime
if date.class.to_s == 'DateTime'
# It's valid, return the date object
date
else
raise GraphQL::CoercionError, "#{input_value.inspect} is not a valid DateTime"
end
end

def self.coerce_result(ruby_value, context)
# It's transported as a string, so stringify it
ruby_value.to_date.to_s(:long)
end
end
21 changes: 21 additions & 0 deletions app/graphql/types/days_from_now.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'action_view'
include ActionView::Helpers::DateHelper

# app/graphql/types/days_from_now.rb
class Types::DaysFromNow < Types::BaseScalar
description "Numbers of days from now, transported as a descriptive String"

def self.coerce_input(input_value, context)
input_value
end

def self.coerce_result(ruby_value, context)
# It's transported as a string, so stringify it
# days_from_now = distance_of_time_in_words(Time.zone.now, ruby_value) + (ruby_value <= Time.zone.now ? ' ago': '')
if ruby_value.class.to_s == "Date"
days_from_now = ruby_value - Date.current
else
days_from_now = ruby_value.to_date - Date.current
end
end
end
15 changes: 15 additions & 0 deletions app/graphql/types/ingredient_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Types::IngredientType < Types::BaseObject
field :id, ID, null: false
field :stocks, [Types::StockType], "The stocks for this ingredient", null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
field :name, String, null: false
field :vegan, Boolean, null: false
field :vegetarian, Boolean, null: false
field :gluten_free, Boolean, null: false
field :dairy_free, Boolean, null: false
field :kosher, Boolean, null: false
end

# field :portions, [Types::PortionType], "The portions for this ingredient", null: true
# field :recipes, [Types::RecipeType], "The stocks for this ingredient", null: true
10 changes: 10 additions & 0 deletions app/graphql/types/mutation_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Types
class MutationType < Types::BaseObject
# TODO: remove me
field :test_field, String, null: false,
description: "An example field added by the generator"
def test_field
"Hello World"
end
end
end
11 changes: 11 additions & 0 deletions app/graphql/types/portion_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Types::PortionType < Types::BaseObject
field :id, ID, null: false
field :recipe, Types::RecipeType, "The recipe this portion is within", null: false
field :unit, Types::UnitType, "The unit for this stock", null: false
field :use_by_date, Types::Date, null: false
field :amount, Float, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
field :hidden, Boolean, null: false
field :always_available, Boolean, null: false
end
34 changes: 34 additions & 0 deletions app/graphql/types/query_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Types
class QueryType < Types::BaseObject
# Add root-level fields here.
# They will be entry points for queries on your schema.

field :recipes, [RecipeType], null: true do
description "A group of all recipes"
argument :limit, Integer, required: false
end

field :user_fav_stock, [UserFavStockType], null: true do
description "A group of user favourite stock - aka quick add stock"
argument :user_id, Integer, required: true
end

field :cupboards_from_user_id, [CupboardType], null: true do
description "A collection of cupboards from a user id"
argument :user_id, Integer, required: true
argument :limit, Integer, required: false
end

def recipes(limit: 4)
Recipe.all.limit(limit)
end

def user_fav_stock(user_id: nil)
UserFavStock.where(user_id: user_id)
end

def cupboards_from_user_id(user_id: nil, limit: 4)
Cupboard.where(id: CupboardUser.where(user_id: user_id, accepted: true).map{|cu| cu.cupboard.id unless cu.cupboard.setup == true || cu.cupboard.hidden == true }.compact).order(created_at: :desc).limit(limit)
end
end
end
16 changes: 16 additions & 0 deletions app/graphql/types/recipe_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Types::RecipeType < Types::BaseObject
field :id, ID, null: false
field :title, String, null: true
field :description, String, null: true
field :cuisine, String, null: true
field :prep_time, String, null: true
field :cook_time, String, null: true
field :yield, String, null: true
field :public, Boolean, null: false
field :show_users_name, Boolean, null: true
field :user, Types::UserType, "The creator of this recipe", null: false
field :live, Boolean, null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: true
field :updated_at, GraphQL::Types::ISO8601DateTime, null: true
field :note, String, null: true
end
14 changes: 14 additions & 0 deletions app/graphql/types/stock_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Types::StockType < Types::BaseObject
field :id, ID, null: false
field :cupboard, Types::CupboardType, "The cupboard this stock is within", null: false
field :ingredient, Types::IngredientType, "The ingredient for this stock", null: false
field :users, [Types::UserType], "The user this stock belongs to", null: false
field :unit, Types::UnitType, "The unit for this stock", null: false
# field :use_by_date, Types::Date, null: false
field :use_by_date, Types::DaysFromNow, null: false
field :amount, Float, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
field :hidden, Boolean, null: false
field :always_available, Boolean, null: false
end
10 changes: 10 additions & 0 deletions app/graphql/types/unit_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Types::UnitType < Types::BaseObject
field :id, ID, null: false
field :unit_number, Integer, null: true
field :name, String, null: true
field :short_name, String, null: true
field :unit_type, String, null: true
field :metric_ratio, Float, null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: true
field :updated_at, GraphQL::Types::ISO8601DateTime, null: true
end
10 changes: 10 additions & 0 deletions app/graphql/types/user_fav_stock_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Types::UserFavStockType < Types::BaseObject
field :id, ID, null: false
field :ingredient, Types::IngredientType, "The ingredient in this User Fav Stock", null: false
field :unit, Types::UnitType, "The unit for this User Fav Stock", null: false
field :user, Types::UserType, "The user this user fav stock belongs to", null: false
field :stock_amount, Integer, null: true
field :standard_use_by_limit, Integer, null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
16 changes: 16 additions & 0 deletions app/graphql/types/user_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Types::UserType < Types::BaseObject
field :id, ID, null: true
field :name, String, null: true
field :email, String, null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: true
field :updated_at, GraphQL::Types::ISO8601DateTime, null: true
field :password_digest, String, null: true
field :remember_digest, String, null: true
field :admin, Boolean, null: true
field :activation_digest, String, null: true
field :activated, Boolean, null: true
field :activated_at, GraphQL::Types::ISO8601DateTime, null: true
field :reset_digest, String, null: true
field :reset_sent_at, GraphQL::Types::ISO8601DateTime, null: true
field :demo, Boolean, null: true
end
9 changes: 2 additions & 7 deletions app/models/portion.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
class Portion < ApplicationRecord
belongs_to :recipe
belongs_to :ingredient
has_one :unit, through: :ingredient

accepts_nested_attributes_for :ingredient,
:reject_if => :all_blank
accepts_nested_attributes_for :unit
belongs_to :unit

validates :amount, presence: true
validates_numericality_of :amount, on: :create
validates :ingredient_id, presence: true
validates :unit_number, presence: true

validates :unit_id, presence: true


def quantity
Expand Down
7 changes: 1 addition & 6 deletions app/models/unit.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
class Unit < ApplicationRecord
has_many :ingredients
has_many :portions, through: :ingredients
has_one :portion
has_one :stock
has_one :user_fav_stock

accepts_nested_attributes_for :portions,
:reject_if => :all_blank,
:allow_destroy => true
accepts_nested_attributes_for :ingredients
end
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
Rails.application.routes.draw do
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
end

post "/graphql", to: "graphql#execute"
match '/404', :to => 'errors#not_found', :via => :all
match '/500', :to => 'errors#internal_server_error', :via => :all
root 'static_pages#home'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class RenameUnitNumberToUnitIdForPortions < ActiveRecord::Migration[5.1]
def change
rename_column :portions, :unit_number, :unit_id
end
end
Loading