graphql 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/graph_ql/directive.rb +36 -0
 - data/lib/graph_ql/directives/directive_chain.rb +33 -0
 - data/lib/graph_ql/directives/include_directive.rb +15 -0
 - data/lib/graph_ql/directives/skip_directive.rb +15 -0
 - data/lib/graph_ql/enum.rb +34 -0
 - data/lib/graph_ql/fields/abstract_field.rb +37 -0
 - data/lib/graph_ql/fields/access_field.rb +24 -0
 - data/lib/graph_ql/fields/field.rb +34 -0
 - data/lib/graph_ql/interface.rb +14 -0
 - data/lib/graph_ql/introspection/arguments_field.rb +5 -0
 - data/lib/graph_ql/introspection/directive_type.rb +12 -0
 - data/lib/graph_ql/introspection/enum_value_type.rb +10 -0
 - data/lib/graph_ql/introspection/enum_values_field.rb +15 -0
 - data/lib/graph_ql/introspection/field_type.rb +11 -0
 - data/lib/graph_ql/introspection/fields_field.rb +14 -0
 - data/lib/graph_ql/introspection/input_fields_field.rb +12 -0
 - data/lib/graph_ql/introspection/input_value_type.rb +10 -0
 - data/lib/graph_ql/introspection/of_type_field.rb +12 -0
 - data/lib/graph_ql/introspection/possible_types_field.rb +12 -0
 - data/lib/graph_ql/introspection/schema_type.rb +32 -0
 - data/lib/graph_ql/introspection/type_kind_enum.rb +7 -0
 - data/lib/graph_ql/introspection/type_type.rb +22 -0
 - data/lib/graph_ql/parser/nodes.rb +72 -0
 - data/lib/graph_ql/parser/parser.rb +108 -0
 - data/lib/graph_ql/parser/transform.rb +86 -0
 - data/lib/graph_ql/parser/visitor.rb +47 -0
 - data/lib/graph_ql/query.rb +50 -0
 - data/lib/graph_ql/query/arguments.rb +25 -0
 - data/lib/graph_ql/query/field_resolution_strategy.rb +83 -0
 - data/lib/graph_ql/query/fragment_spread_resolution_strategy.rb +16 -0
 - data/lib/graph_ql/query/inline_fragment_resolution_strategy.rb +14 -0
 - data/lib/graph_ql/query/operation_resolver.rb +28 -0
 - data/lib/graph_ql/query/selection_resolver.rb +20 -0
 - data/lib/graph_ql/query/type_resolver.rb +19 -0
 - data/lib/graph_ql/repl.rb +27 -0
 - data/lib/graph_ql/schema.rb +30 -0
 - data/lib/graph_ql/schema/type_reducer.rb +44 -0
 - data/lib/graph_ql/type_kinds.rb +15 -0
 - data/lib/graph_ql/types/abstract_type.rb +14 -0
 - data/lib/graph_ql/types/boolean_type.rb +6 -0
 - data/lib/graph_ql/types/float_type.rb +6 -0
 - data/lib/graph_ql/types/input_object_type.rb +17 -0
 - data/lib/graph_ql/types/input_value.rb +10 -0
 - data/lib/graph_ql/types/int_type.rb +6 -0
 - data/lib/graph_ql/types/list_type.rb +10 -0
 - data/lib/graph_ql/types/non_null_type.rb +18 -0
 - data/lib/graph_ql/types/non_null_with_bang.rb +5 -0
 - data/lib/graph_ql/types/object_type.rb +62 -0
 - data/lib/graph_ql/types/scalar_type.rb +5 -0
 - data/lib/graph_ql/types/string_type.rb +6 -0
 - data/lib/graph_ql/types/type_definer.rb +16 -0
 - data/lib/graph_ql/union.rb +35 -0
 - data/lib/graph_ql/validations/fields_are_defined_on_type.rb +44 -0
 - data/lib/graph_ql/validations/fields_will_merge.rb +80 -0
 - data/lib/graph_ql/validations/fragments_are_used.rb +24 -0
 - data/lib/graph_ql/validator.rb +29 -0
 - data/lib/graph_ql/version.rb +3 -0
 - data/lib/graphql.rb +92 -99
 - data/readme.md +17 -177
 - data/spec/graph_ql/directive_spec.rb +81 -0
 - data/spec/graph_ql/enum_spec.rb +5 -0
 - data/spec/graph_ql/fields/field_spec.rb +10 -0
 - data/spec/graph_ql/interface_spec.rb +13 -0
 - data/spec/graph_ql/introspection/directive_type_spec.rb +40 -0
 - data/spec/graph_ql/introspection/schema_type_spec.rb +39 -0
 - data/spec/graph_ql/introspection/type_type_spec.rb +104 -0
 - data/spec/graph_ql/parser/parser_spec.rb +120 -0
 - data/spec/graph_ql/parser/transform_spec.rb +109 -0
 - data/spec/graph_ql/parser/visitor_spec.rb +31 -0
 - data/spec/graph_ql/query/operation_resolver_spec.rb +14 -0
 - data/spec/graph_ql/query_spec.rb +82 -0
 - data/spec/graph_ql/schema/type_reducer_spec.rb +24 -0
 - data/spec/graph_ql/types/input_object_type_spec.rb +12 -0
 - data/spec/graph_ql/types/object_type_spec.rb +35 -0
 - data/spec/graph_ql/union_spec.rb +27 -0
 - data/spec/graph_ql/validations/fields_are_defined_on_type_spec.rb +28 -0
 - data/spec/graph_ql/validations/fields_will_merge_spec.rb +40 -0
 - data/spec/graph_ql/validations/fragments_are_used_spec.rb +28 -0
 - data/spec/graph_ql/validator_spec.rb +24 -0
 - data/spec/spec_helper.rb +2 -2
 - data/spec/support/dummy_app.rb +123 -63
 - data/spec/support/dummy_data.rb +11 -0
 - metadata +107 -59
 - data/lib/graphql/call.rb +0 -8
 - data/lib/graphql/connection.rb +0 -65
 - data/lib/graphql/field.rb +0 -12
 - data/lib/graphql/field_definer.rb +0 -25
 - data/lib/graphql/introspection/call_type.rb +0 -13
 - data/lib/graphql/introspection/connection.rb +0 -9
 - data/lib/graphql/introspection/field_type.rb +0 -10
 - data/lib/graphql/introspection/root_call_argument_node.rb +0 -5
 - data/lib/graphql/introspection/root_call_type.rb +0 -20
 - data/lib/graphql/introspection/schema_call.rb +0 -8
 - data/lib/graphql/introspection/schema_type.rb +0 -17
 - data/lib/graphql/introspection/type_call.rb +0 -8
 - data/lib/graphql/introspection/type_type.rb +0 -18
 - data/lib/graphql/node.rb +0 -244
 - data/lib/graphql/parser/parser.rb +0 -39
 - data/lib/graphql/parser/transform.rb +0 -22
 - data/lib/graphql/query.rb +0 -109
 - data/lib/graphql/root_call.rb +0 -202
 - data/lib/graphql/root_call_argument.rb +0 -11
 - data/lib/graphql/root_call_argument_definer.rb +0 -17
 - data/lib/graphql/schema/all.rb +0 -46
 - data/lib/graphql/schema/schema.rb +0 -87
 - data/lib/graphql/schema/schema_validation.rb +0 -32
 - data/lib/graphql/syntax/call.rb +0 -8
 - data/lib/graphql/syntax/field.rb +0 -9
 - data/lib/graphql/syntax/fragment.rb +0 -7
 - data/lib/graphql/syntax/node.rb +0 -8
 - data/lib/graphql/syntax/query.rb +0 -8
 - data/lib/graphql/syntax/variable.rb +0 -7
 - data/lib/graphql/types/boolean_type.rb +0 -3
 - data/lib/graphql/types/number_type.rb +0 -3
 - data/lib/graphql/types/object_type.rb +0 -6
 - data/lib/graphql/types/string_type.rb +0 -3
 - data/lib/graphql/version.rb +0 -3
 - data/spec/graphql/node_spec.rb +0 -69
 - data/spec/graphql/parser/parser_spec.rb +0 -168
 - data/spec/graphql/parser/transform_spec.rb +0 -157
 - data/spec/graphql/query_spec.rb +0 -274
 - data/spec/graphql/root_call_spec.rb +0 -69
 - data/spec/graphql/schema/schema_spec.rb +0 -93
 - data/spec/graphql/schema/schema_validation_spec.rb +0 -48
 - data/spec/support/nodes.rb +0 -175
 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Visitor do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:document) { GraphQL.parse("
         
     | 
| 
      
 5 
     | 
    
         
            +
                query cheese { cheese(id: 1) { flavor, source, producers(first: 3) { name } } }
         
     | 
| 
      
 6 
     | 
    
         
            +
                fragment cheeseFields on Cheese { flavor }
         
     | 
| 
      
 7 
     | 
    
         
            +
                ")}
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:counts) { {fields_entered: 0, arguments_entered: 0, arguments_left: 0, argument_names: []} }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              let(:visitor) do
         
     | 
| 
      
 11 
     | 
    
         
            +
                v = GraphQL::Visitor.new
         
     | 
| 
      
 12 
     | 
    
         
            +
                v[GraphQL::Nodes::Field] << -> (node) { counts[:fields_entered] += 1 }
         
     | 
| 
      
 13 
     | 
    
         
            +
                # two ways to set up enter hooks:
         
     | 
| 
      
 14 
     | 
    
         
            +
                v[GraphQL::Nodes::Argument] <<       -> (node) { counts[:argument_names] << node.name }
         
     | 
| 
      
 15 
     | 
    
         
            +
                v[GraphQL::Nodes::Argument].enter << -> (node) { counts[:arguments_entered] += 1}
         
     | 
| 
      
 16 
     | 
    
         
            +
                v[GraphQL::Nodes::Argument].leave << -> (node) { counts[:arguments_left] += 1 }
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                v[GraphQL::Nodes::Document].leave << -> (node) { counts[:finished] = true }
         
     | 
| 
      
 19 
     | 
    
         
            +
                v
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              it 'calls hooks during a depth-first tree traversal' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_equal(2, visitor[GraphQL::Nodes::Argument].enter.length)
         
     | 
| 
      
 24 
     | 
    
         
            +
                visitor.visit(document)
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert_equal(6, counts[:fields_entered])
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal(2, counts[:arguments_entered])
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal(2, counts[:arguments_left])
         
     | 
| 
      
 28 
     | 
    
         
            +
                assert_equal(["id", "first"], counts[:argument_names])
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert(counts[:finished])
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Query::OperationResolver do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:operation) { GraphQL.parse("query getCheese($cheeseId: Int!) { cheese(id: $cheeseId) { name }}", as: :operation_definition) }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:params) { {"cheeseId" => 1}}
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:query) { q = Minitest::Mock.new; q.expect(:params, params); q}
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:resolver) { GraphQL::Query::OperationResolver.new(operation, query)}
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              describe "variables" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                it 'returns variables by name' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  assert_equal(1, resolver.variables["cheeseId"])
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Query do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe '#execute' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:query_string) { %|
         
     | 
| 
      
 6 
     | 
    
         
            +
                  query getFlavor($cheeseId: Int!) {
         
     | 
| 
      
 7 
     | 
    
         
            +
                    brie: cheese(id: 1)   { ...cheeseFields, ... meatFields, taste: flavor },
         
     | 
| 
      
 8 
     | 
    
         
            +
                    cheese(id: $cheeseId)  {
         
     | 
| 
      
 9 
     | 
    
         
            +
                      __typename,
         
     | 
| 
      
 10 
     | 
    
         
            +
                      id,
         
     | 
| 
      
 11 
     | 
    
         
            +
                      ...cheeseFields,
         
     | 
| 
      
 12 
     | 
    
         
            +
                      ... edibleFields,
         
     | 
| 
      
 13 
     | 
    
         
            +
                      ... on Cheese { cheeseKind: flavor },
         
     | 
| 
      
 14 
     | 
    
         
            +
                      ... on Meat { cut }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    }
         
     | 
| 
      
 16 
     | 
    
         
            +
                    fromSource(source: COW) { id }
         
     | 
| 
      
 17 
     | 
    
         
            +
                    firstSheep: searchDairy(product: {source: SHEEP}) { ... dairyFields }
         
     | 
| 
      
 18 
     | 
    
         
            +
                    favoriteEdible { __typename, fatContent }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  fragment cheeseFields on Cheese { flavor }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  fragment edibleFields on Edible { fatContent }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  fragment meatFields on Meat { cut }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  fragment dairyFields on DairyProduct {
         
     | 
| 
      
 24 
     | 
    
         
            +
                     ... on Cheese { flavor }
         
     | 
| 
      
 25 
     | 
    
         
            +
                     ... on Milk   { source }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  }
         
     | 
| 
      
 27 
     | 
    
         
            +
                |}
         
     | 
| 
      
 28 
     | 
    
         
            +
                let(:query) { GraphQL::Query.new(DummySchema, query_string, context: {}, params: {"cheeseId" => 2})}
         
     | 
| 
      
 29 
     | 
    
         
            +
                let(:result) { query.result }
         
     | 
| 
      
 30 
     | 
    
         
            +
                it 'returns fields on objects' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  expected = {"data"=> { "getFlavor" => {
         
     | 
| 
      
 32 
     | 
    
         
            +
                      "brie" =>   { "flavor" => "Brie", "taste" => "Brie" },
         
     | 
| 
      
 33 
     | 
    
         
            +
                      "cheese" => {
         
     | 
| 
      
 34 
     | 
    
         
            +
                        "__typename" => "Cheese",
         
     | 
| 
      
 35 
     | 
    
         
            +
                        "id" => 2,
         
     | 
| 
      
 36 
     | 
    
         
            +
                        "fatContent" => 0.3,
         
     | 
| 
      
 37 
     | 
    
         
            +
                        "flavor" => "Gouda",
         
     | 
| 
      
 38 
     | 
    
         
            +
                        "cheeseKind" => "Gouda",
         
     | 
| 
      
 39 
     | 
    
         
            +
                      },
         
     | 
| 
      
 40 
     | 
    
         
            +
                      "fromSource" => [{ "id" => 1 }, {"id" => 2}],
         
     | 
| 
      
 41 
     | 
    
         
            +
                      "firstSheep" => { "flavor" => "Manchego" },
         
     | 
| 
      
 42 
     | 
    
         
            +
                      "favoriteEdible"=>{"__typename"=>"Edible", "fatContent"=>0.04},
         
     | 
| 
      
 43 
     | 
    
         
            +
                  }}}
         
     | 
| 
      
 44 
     | 
    
         
            +
                  assert_equal(expected, result)
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                it 'exposes fragments' do
         
     | 
| 
      
 48 
     | 
    
         
            +
                  assert_equal(GraphQL::Nodes::FragmentDefinition, query.fragments['cheeseFields'].class)
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                describe 'runtime errors' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  let(:query_string) {%| query noMilk { milk(id: 1000) { name } }|}
         
     | 
| 
      
 53 
     | 
    
         
            +
                  it 'turns into error messages' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                    expected = {"errors"=>[
         
     | 
| 
      
 55 
     | 
    
         
            +
                      {"message"=>"Something went wrong during query execution: No field found on Query 'Query' for 'milk'"}
         
     | 
| 
      
 56 
     | 
    
         
            +
                    ]}
         
     | 
| 
      
 57 
     | 
    
         
            +
                    assert_equal(expected, result)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                describe 'execution order' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  let(:query_string) {%|
         
     | 
| 
      
 64 
     | 
    
         
            +
                    mutation setInOrder {
         
     | 
| 
      
 65 
     | 
    
         
            +
                      first:  pushValue(value: 1)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      second: pushValue(value: 5)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      third:  pushValue(value: 2)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    }
         
     | 
| 
      
 69 
     | 
    
         
            +
                  |}
         
     | 
| 
      
 70 
     | 
    
         
            +
                  it 'executes mutations in order' do
         
     | 
| 
      
 71 
     | 
    
         
            +
                    expected = {"data"=>{
         
     | 
| 
      
 72 
     | 
    
         
            +
                      "setInOrder"=>{
         
     | 
| 
      
 73 
     | 
    
         
            +
                        "first"=> [1],
         
     | 
| 
      
 74 
     | 
    
         
            +
                        "second"=>[1, 5],
         
     | 
| 
      
 75 
     | 
    
         
            +
                        "third"=> [1, 5, 2],
         
     | 
| 
      
 76 
     | 
    
         
            +
                      }
         
     | 
| 
      
 77 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 78 
     | 
    
         
            +
                    assert_equal(expected, result)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Schema::TypeReducer do
         
     | 
| 
      
 4 
     | 
    
         
            +
              it 'finds types from a single type and its fields' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                reducer = GraphQL::Schema::TypeReducer.new(CheeseType, {})
         
     | 
| 
      
 6 
     | 
    
         
            +
                expected = {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  "Cheese" => CheeseType,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  "Int" => GraphQL::INT_TYPE,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  "String" => GraphQL::STRING_TYPE,
         
     | 
| 
      
 10 
     | 
    
         
            +
                  "DairyAnimal" => DairyAnimalEnum,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  "Float" => GraphQL::FLOAT_TYPE,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  "Edible" => Edible,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "Milk" => MilkType,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  "AnimalProduct" => AnimalProduct,
         
     | 
| 
      
 15 
     | 
    
         
            +
                }
         
     | 
| 
      
 16 
     | 
    
         
            +
                assert_equal(expected.keys, reducer.result.keys)
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal(expected, reducer.result)
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              it 'finds type from arguments' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                reducer = GraphQL::Schema::TypeReducer.new(QueryType, {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                assert_equal(DairyProductInputType, reducer.result["DairyProductInput"])
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::InputObjectType do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:input_object) { DairyProductInputType }
         
     | 
| 
      
 5 
     | 
    
         
            +
              it 'has a description' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                assert(input_object.description)
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it 'has input fields' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                assert(DairyProductInputType.input_fields["fatContent"])
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::ObjectType do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:type) { CheeseType }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              it 'has a name' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                assert_equal("Cheese", type.name)
         
     | 
| 
      
 8 
     | 
    
         
            +
                type.name("Fromage")
         
     | 
| 
      
 9 
     | 
    
         
            +
                assert_equal("Fromage", type.name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                type.name("Cheese")
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it 'has a description' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                assert_equal(22, type.description.length)
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              it 'may have interfaces' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert_equal([Edible, AnimalProduct], type.interfaces)
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              it 'becomes non-null with !' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                non_null_type = !type
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_equal(GraphQL::TypeKinds::NON_NULL, non_null_type.kind)
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert_equal(type, non_null_type.of_type)
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert_equal(GraphQL::TypeKinds::NON_NULL, (!GraphQL::STRING_TYPE).kind)
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              describe '.fields ' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                it 'exposes fields' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  field = type.fields["id"]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  assert_equal(GraphQL::TypeKinds::NON_NULL, field.type.kind)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  assert_equal(GraphQL::TypeKinds::SCALAR, field.type.of_type.kind)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Union do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:type_1) { OpenStruct.new(kind: GraphQL::TypeKinds::OBJECT)}
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:type_2) { OpenStruct.new(kind: GraphQL::TypeKinds::OBJECT)}
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:union) { GraphQL::Union.new("MyUnion", [type_1, type_2]) }
         
     | 
| 
      
 7 
     | 
    
         
            +
              it 'has a name' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                assert_equal("MyUnion", union.name)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it 'identifies members' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                assert(union.include?(type_1))
         
     | 
| 
      
 13 
     | 
    
         
            +
                assert(!union.include?(:type_3))
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              it 'must be 2+ types' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_raises(ArgumentError) { GraphQL::Union.new("Something", [type_1])}
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              it 'must be all object types' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                assert_raises(ArgumentError) { GraphQL::Union.new("Something", [type_1, type_2, union])}
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              it 'infers type from an object' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert_equal(CheeseType, DairyProductUnion.resolve_type(CHEESES[1]))
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Validations::FieldsAreDefinedOnType do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:document) { GraphQL.parse("
         
     | 
| 
      
 5 
     | 
    
         
            +
                query getCheese($sourceVar: DairyAnimal!) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  notDefinedField { name }
         
     | 
| 
      
 7 
     | 
    
         
            +
                  cheese(id: 1) { nonsenseField, flavor }
         
     | 
| 
      
 8 
     | 
    
         
            +
                  fromSource(source: COW) { bogusField }
         
     | 
| 
      
 9 
     | 
    
         
            +
                }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                fragment cheeseFields on Cheese { fatContent, hogwashField }
         
     | 
| 
      
 12 
     | 
    
         
            +
              ")}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              let(:validator) { GraphQL::Validator.new(schema: DummySchema, validators: [GraphQL::Validations::FieldsAreDefinedOnType]) }
         
     | 
| 
      
 15 
     | 
    
         
            +
              let(:errors) { validator.validate(document) }
         
     | 
| 
      
 16 
     | 
    
         
            +
              it "finds fields that are requested on types that don't have that field" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                expected_errors = [
         
     | 
| 
      
 18 
     | 
    
         
            +
                  "Field 'notDefinedField' doesn't exist on type 'Query'",  # from query root
         
     | 
| 
      
 19 
     | 
    
         
            +
                  "Field 'nonsenseField' doesn't exist on type 'Cheese'",   # from another field
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "Field 'bogusField' doesn't exist on type 'Cheese'",      # from a list
         
     | 
| 
      
 21 
     | 
    
         
            +
                  "Field 'hogwashField' doesn't exist on type 'Cheese'",    # from a fragment
         
     | 
| 
      
 22 
     | 
    
         
            +
                ]
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_equal(expected_errors, errors)
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              it 'finds invalid fields on interfaces'
         
     | 
| 
      
 27 
     | 
    
         
            +
              it 'finds invalid fields on unions'
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Validations::FieldsWillMerge do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:document) { GraphQL.parse("
         
     | 
| 
      
 5 
     | 
    
         
            +
                query getCheese($sourceVar: DairyAnimal!) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  id
         
     | 
| 
      
 7 
     | 
    
         
            +
                  nickname: name,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  nickname: fatContent,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  fatContent
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  similarCheeses(source: $sourceVar)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  origin { originName: id },
         
     | 
| 
      
 14 
     | 
    
         
            +
                  ...cheeseFields
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ... on Cheese {
         
     | 
| 
      
 16 
     | 
    
         
            +
                    fatContent: name
         
     | 
| 
      
 17 
     | 
    
         
            +
                    similarCheeses(source: SHEEP)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  }
         
     | 
| 
      
 19 
     | 
    
         
            +
                }
         
     | 
| 
      
 20 
     | 
    
         
            +
                fragment cheeseFields on Cheese {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  fatContent,
         
     | 
| 
      
 22 
     | 
    
         
            +
                  origin { originName: name }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  id @someFlag
         
     | 
| 
      
 24 
     | 
    
         
            +
                }
         
     | 
| 
      
 25 
     | 
    
         
            +
              ")}
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              let(:validator) { GraphQL::Validator.new(schema: nil, validators: [GraphQL::Validations::FieldsWillMerge]) }
         
     | 
| 
      
 28 
     | 
    
         
            +
              let(:errors) { validator.validate(document) }
         
     | 
| 
      
 29 
     | 
    
         
            +
              it 'finds field naming conflicts' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                expected_errors = [
         
     | 
| 
      
 31 
     | 
    
         
            +
                  "Field 'nickname' has a field conflict: name or fatContent?",             # alias conflict in query
         
     | 
| 
      
 32 
     | 
    
         
            +
                  "Field 'originName' has a field conflict: id or name?",                   # nested conflict
         
     | 
| 
      
 33 
     | 
    
         
            +
                  "Field 'id' has a directive conflict: [] or [someFlag]?",                 # different directives
         
     | 
| 
      
 34 
     | 
    
         
            +
                  "Field 'id' has a directive argument conflict: [] or [{}]?",              # not sure this is a great way to handle it but here we are!
         
     | 
| 
      
 35 
     | 
    
         
            +
                  "Field 'fatContent' has a field conflict: fatContent or name?",           # alias/name conflict in query and fragment
         
     | 
| 
      
 36 
     | 
    
         
            +
                  "Field 'similarCheeses' has an argument conflict: {\"source\":\"sourceVar\"} or {\"source\":\"SHEEP\"}?", # different arguments
         
     | 
| 
      
 37 
     | 
    
         
            +
                ]
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_equal(expected_errors, errors)
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe GraphQL::Validations::FragmentsAreUsed do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:document) { GraphQL.parse("
         
     | 
| 
      
 5 
     | 
    
         
            +
                query getCheese {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  name,
         
     | 
| 
      
 7 
     | 
    
         
            +
                  ...cheeseFields,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  origin {
         
     | 
| 
      
 9 
     | 
    
         
            +
                    ...originFields
         
     | 
| 
      
 10 
     | 
    
         
            +
                    ...undefinedFields
         
     | 
| 
      
 11 
     | 
    
         
            +
                  }
         
     | 
| 
      
 12 
     | 
    
         
            +
                }
         
     | 
| 
      
 13 
     | 
    
         
            +
                fragment cheeseFields on Cheese { fatContent }
         
     | 
| 
      
 14 
     | 
    
         
            +
                fragment originFields on Country { name, continent { ...continentFields }}
         
     | 
| 
      
 15 
     | 
    
         
            +
                fragment continentFields on Continent { name }
         
     | 
| 
      
 16 
     | 
    
         
            +
                fragment unusedFields on Cheese { is, not, used }
         
     | 
| 
      
 17 
     | 
    
         
            +
              ")}
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              let(:validator) { GraphQL::Validator.new(schema: nil, validators: [GraphQL::Validations::FragmentsAreUsed]) }
         
     | 
| 
      
 20 
     | 
    
         
            +
              let(:errors) { validator.validate(document) }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              it 'adds errors for unused fragment definitions' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_includes(errors, 'Some fragments were defined but not used: unusedFields')
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              it 'adds errors for undefined fragment spreads' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_includes(errors, 'Some fragments were used but not defined: undefinedFields')
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SchemaErrorValidator
         
     | 
| 
      
 4 
     | 
    
         
            +
              def validate(context)
         
     | 
| 
      
 5 
     | 
    
         
            +
                context.errors << "Something is wrong: #{context.schema}"
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class DocumentErrorValidator
         
     | 
| 
      
 10 
     | 
    
         
            +
              def validate(context)
         
     | 
| 
      
 11 
     | 
    
         
            +
                context.errors << "Something is wrong: #{context.document.name}"
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            describe GraphQL::Validator do
         
     | 
| 
      
 16 
     | 
    
         
            +
              let(:document)  { OpenStruct.new(name: "This is not a document", children: []) }
         
     | 
| 
      
 17 
     | 
    
         
            +
              let(:validator) { GraphQL::Validator.new(schema: "This is not a schema", validators: [SchemaErrorValidator, DocumentErrorValidator]) }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              it 'uses validators' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                errors = validator.validate(document)
         
     | 
| 
      
 21 
     | 
    
         
            +
                expected_errors = ["Something is wrong: This is not a schema", "Something is wrong: This is not a document"]
         
     | 
| 
      
 22 
     | 
    
         
            +
                assert_equal(expected_errors, errors)
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "codeclimate-test-reporter"
         
     | 
| 
       2 
2 
     | 
    
         
             
            CodeClimate::TestReporter.start
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'graphql'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'date'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require "minitest/autorun"
         
     | 
| 
       6 
6 
     | 
    
         
             
            require "minitest/focus"
         
     | 
| 
         @@ -16,4 +16,4 @@ Minitest.backtrace_filter = Minitest::BacktraceFilter.new 
     | 
|
| 
       16 
16 
     | 
    
         
             
            Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
            require 'parslet'
         
     | 
| 
       19 
     | 
    
         
            -
            require 'parslet/convenience'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'parslet/convenience'
         
     | 
    
        data/spec/support/dummy_app.rb
    CHANGED
    
    | 
         @@ -1,81 +1,141 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
              def initialize(attributes={})
         
     | 
| 
       3 
     | 
    
         
            -
                attributes.each do |key, value|
         
     | 
| 
       4 
     | 
    
         
            -
                  self.send("#{key}=", value)
         
     | 
| 
       5 
     | 
    
         
            -
                end
         
     | 
| 
       6 
     | 
    
         
            -
              end
         
     | 
| 
      
 1 
     | 
    
         
            +
            require_relative './dummy_data'
         
     | 
| 
       7 
2 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
               
     | 
| 
      
 3 
     | 
    
         
            +
            Edible = GraphQL::Interface.new do
         
     | 
| 
      
 4 
     | 
    
         
            +
              name "Edible"
         
     | 
| 
      
 5 
     | 
    
         
            +
              description "Something you can eat, yum"
         
     | 
| 
      
 6 
     | 
    
         
            +
              fields({
         
     | 
| 
      
 7 
     | 
    
         
            +
                fatContent: field(type: !type.Float, desc: "Percentage which is fat"),
         
     | 
| 
      
 8 
     | 
    
         
            +
              })
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                  all.find { |object| object.id.to_s == id.to_s }
         
     | 
| 
       20 
     | 
    
         
            -
                end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                def where(query={})
         
     | 
| 
       23 
     | 
    
         
            -
                  result = []
         
     | 
| 
       24 
     | 
    
         
            -
                  all.each do |object|
         
     | 
| 
       25 
     | 
    
         
            -
                    match = true
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                    query.each do |key, value|
         
     | 
| 
       28 
     | 
    
         
            -
                      if object.send(key) != value
         
     | 
| 
       29 
     | 
    
         
            -
                        match = false
         
     | 
| 
       30 
     | 
    
         
            -
                      end
         
     | 
| 
       31 
     | 
    
         
            -
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
            AnimalProduct = GraphQL::Interface.new do
         
     | 
| 
      
 12 
     | 
    
         
            +
              name "AnimalProduct"
         
     | 
| 
      
 13 
     | 
    
         
            +
              description "Comes from an animal, no joke"
         
     | 
| 
      
 14 
     | 
    
         
            +
              fields({
         
     | 
| 
      
 15 
     | 
    
         
            +
                source: field(type: !type.String, desc: "Animal which produced this product"),
         
     | 
| 
      
 16 
     | 
    
         
            +
              })
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
       32 
18 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                 
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
               
     | 
| 
      
 19 
     | 
    
         
            +
            DairyAnimalEnum = GraphQL::Enum.new do |e|
         
     | 
| 
      
 20 
     | 
    
         
            +
              e.name "DairyAnimal"
         
     | 
| 
      
 21 
     | 
    
         
            +
              e.description "An animal which can yield milk"
         
     | 
| 
      
 22 
     | 
    
         
            +
              e.value("COW",    "Animal with black and white spots")
         
     | 
| 
      
 23 
     | 
    
         
            +
              e.value("GOAT",   "Animal with horns")
         
     | 
| 
      
 24 
     | 
    
         
            +
              e.value("SHEEP",  "Animal with wool")
         
     | 
| 
      
 25 
     | 
    
         
            +
              e.value("YAK",    "Animal with long hair", deprecation_reason: "Out of fashion")
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            CheeseType = GraphQL::ObjectType.new do
         
     | 
| 
      
 29 
     | 
    
         
            +
              name "Cheese"
         
     | 
| 
      
 30 
     | 
    
         
            +
              description "Cultured dairy product"
         
     | 
| 
      
 31 
     | 
    
         
            +
              interfaces [Edible, AnimalProduct]
         
     | 
| 
      
 32 
     | 
    
         
            +
              self.fields = {
         
     | 
| 
      
 33 
     | 
    
         
            +
                id:           field(type: !type.Int, desc: "Unique identifier"),
         
     | 
| 
      
 34 
     | 
    
         
            +
                flavor:       field(type: !type.String, desc: "Kind of cheese"),
         
     | 
| 
      
 35 
     | 
    
         
            +
                source:       field(type: !DairyAnimalEnum, desc: "Animal which produced the milk for this cheese"),
         
     | 
| 
      
 36 
     | 
    
         
            +
                fatContent:   field(type: !type.Float, desc: "Percentage which is milkfat", deprecation_reason: "Diet fashion has changed"),
         
     | 
| 
      
 37 
     | 
    
         
            +
              }
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            MilkType = GraphQL::ObjectType.new do
         
     | 
| 
      
 41 
     | 
    
         
            +
              name 'Milk'
         
     | 
| 
      
 42 
     | 
    
         
            +
              description "Dairy beverage"
         
     | 
| 
      
 43 
     | 
    
         
            +
              interfaces [Edible, AnimalProduct]
         
     | 
| 
      
 44 
     | 
    
         
            +
              self.fields = {
         
     | 
| 
      
 45 
     | 
    
         
            +
                id:           field(type: !type.Int, desc: "Unique identifier"),
         
     | 
| 
      
 46 
     | 
    
         
            +
                source:       field(type: DairyAnimalEnum, desc: "Animal which produced this milk"),
         
     | 
| 
      
 47 
     | 
    
         
            +
                fatContent:   field(type: !type.Float, desc: "Percentage which is milkfat"),
         
     | 
| 
      
 48 
     | 
    
         
            +
                flavors:      field(
         
     | 
| 
      
 49 
     | 
    
         
            +
                      type: type[type.String],
         
     | 
| 
      
 50 
     | 
    
         
            +
                      desc: "Chocolate, Strawberry, etc",
         
     | 
| 
      
 51 
     | 
    
         
            +
                      args: {limit: {type: type.Int}}
         
     | 
| 
      
 52 
     | 
    
         
            +
                    ),
         
     | 
| 
      
 53 
     | 
    
         
            +
              }
         
     | 
| 
       46 
54 
     | 
    
         
             
            end
         
     | 
| 
       47 
55 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
              attr_accessor :id, :title, :content, :published_at
         
     | 
| 
      
 56 
     | 
    
         
            +
            DairyProductUnion = GraphQL::Union.new("DairyProduct", [MilkType, CheeseType])
         
     | 
| 
       50 
57 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
            DairyProductInputType = GraphQL::InputObjectType.new {
         
     | 
| 
      
 59 
     | 
    
         
            +
              name "DairyProductInput"
         
     | 
| 
      
 60 
     | 
    
         
            +
              description "Properties for finding a dairy product"
         
     | 
| 
      
 61 
     | 
    
         
            +
              input_fields({
         
     | 
| 
      
 62 
     | 
    
         
            +
                source:     arg({type: DairyAnimalEnum}),
         
     | 
| 
      
 63 
     | 
    
         
            +
                fatContent: arg({type: type.Float}),
         
     | 
| 
      
 64 
     | 
    
         
            +
              })
         
     | 
| 
      
 65 
     | 
    
         
            +
            }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            class FetchField < GraphQL::AbstractField
         
     | 
| 
      
 69 
     | 
    
         
            +
              attr_reader :type
         
     | 
| 
      
 70 
     | 
    
         
            +
              attr_accessor :name
         
     | 
| 
      
 71 
     | 
    
         
            +
              def initialize(type:, data:)
         
     | 
| 
      
 72 
     | 
    
         
            +
                @type = type
         
     | 
| 
      
 73 
     | 
    
         
            +
                @data = data
         
     | 
| 
       53 
74 
     | 
    
         
             
              end
         
     | 
| 
       54 
75 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
              def  
     | 
| 
       56 
     | 
    
         
            -
                 
     | 
| 
      
 76 
     | 
    
         
            +
              def description
         
     | 
| 
      
 77 
     | 
    
         
            +
                "Find a #{@type.name} by id"
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def resolve(target, arguments, context)
         
     | 
| 
      
 81 
     | 
    
         
            +
                @data[arguments["id"]]
         
     | 
| 
       57 
82 
     | 
    
         
             
              end
         
     | 
| 
       58 
83 
     | 
    
         
             
            end
         
     | 
| 
       59 
84 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
               
     | 
| 
      
 85 
     | 
    
         
            +
            SourceField = GraphQL::Field.new do |f|
         
     | 
| 
      
 86 
     | 
    
         
            +
              f.type GraphQL::ListType.new(of_type: CheeseType)
         
     | 
| 
      
 87 
     | 
    
         
            +
              f.description "Cheese from source"
         
     | 
| 
      
 88 
     | 
    
         
            +
              f.resolve -> (target, arguments, context) {
         
     | 
| 
      
 89 
     | 
    
         
            +
                CHEESES.values.select{ |c| c.source == arguments["source"] }
         
     | 
| 
      
 90 
     | 
    
         
            +
              }
         
     | 
| 
      
 91 
     | 
    
         
            +
            end
         
     | 
| 
       62 
92 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
               
     | 
| 
      
 93 
     | 
    
         
            +
            FavoriteField = GraphQL::Field.new do |f|
         
     | 
| 
      
 94 
     | 
    
         
            +
              f.description "My favorite food"
         
     | 
| 
      
 95 
     | 
    
         
            +
              f.type Edible
         
     | 
| 
      
 96 
     | 
    
         
            +
              f.resolve -> (t, a, c) { MILKS[1] }
         
     | 
| 
       66 
97 
     | 
    
         
             
            end
         
     | 
| 
       67 
98 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
            class Like < InadequateRecordBase
         
     | 
| 
       69 
     | 
    
         
            -
              attr_accessor :id, :post_id
         
     | 
| 
       70 
99 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
               
     | 
| 
      
 100 
     | 
    
         
            +
            QueryType = GraphQL::ObjectType.new do
         
     | 
| 
      
 101 
     | 
    
         
            +
              name "Query"
         
     | 
| 
      
 102 
     | 
    
         
            +
              description "Query root of the system"
         
     | 
| 
      
 103 
     | 
    
         
            +
              fields({
         
     | 
| 
      
 104 
     | 
    
         
            +
                cheese: FetchField.new(type: CheeseType, data: CHEESES),
         
     | 
| 
      
 105 
     | 
    
         
            +
                fromSource: SourceField,
         
     | 
| 
      
 106 
     | 
    
         
            +
                favoriteEdible: FavoriteField,
         
     | 
| 
      
 107 
     | 
    
         
            +
                searchDairy: GraphQL::Field.new { |f|
         
     | 
| 
      
 108 
     | 
    
         
            +
                  f.name "searchDairy"
         
     | 
| 
      
 109 
     | 
    
         
            +
                  f.description "Find dairy products matching a description"
         
     | 
| 
      
 110 
     | 
    
         
            +
                  f.type DairyProductUnion
         
     | 
| 
      
 111 
     | 
    
         
            +
                  f.arguments({product: {type: DairyProductInputType}})
         
     | 
| 
      
 112 
     | 
    
         
            +
                  f.resolve -> (t, a, c) {
         
     | 
| 
      
 113 
     | 
    
         
            +
                    products = CHEESES.values + MILKS.values
         
     | 
| 
      
 114 
     | 
    
         
            +
                    source =  a["product"]["source"]
         
     | 
| 
      
 115 
     | 
    
         
            +
                    if !source.nil?
         
     | 
| 
      
 116 
     | 
    
         
            +
                      products = products.select { |p| p.source == source }
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
                    products.first
         
     | 
| 
      
 119 
     | 
    
         
            +
                  }
         
     | 
| 
      
 120 
     | 
    
         
            +
                }
         
     | 
| 
      
 121 
     | 
    
         
            +
              })
         
     | 
| 
       74 
122 
     | 
    
         
             
            end
         
     | 
| 
       75 
123 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
               
     | 
| 
      
 124 
     | 
    
         
            +
            GLOBAL_VALUES = []
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            MutationType = GraphQL::ObjectType.new do
         
     | 
| 
      
 127 
     | 
    
         
            +
              name "Mutation"
         
     | 
| 
      
 128 
     | 
    
         
            +
              description "The root for mutations in this schema"
         
     | 
| 
      
 129 
     | 
    
         
            +
              fields({
         
     | 
| 
      
 130 
     | 
    
         
            +
                pushValue: GraphQL::Field.new { |f|
         
     | 
| 
      
 131 
     | 
    
         
            +
                  f.description("Push a value onto a global array :D")
         
     | 
| 
      
 132 
     | 
    
         
            +
                  f.type(!type[!type.Int])
         
     | 
| 
      
 133 
     | 
    
         
            +
                  f.arguments(value: arg(type: !type.Int))
         
     | 
| 
      
 134 
     | 
    
         
            +
                  f.resolve -> (o, args, ctx) {
         
     | 
| 
      
 135 
     | 
    
         
            +
                    GLOBAL_VALUES << args["value"]
         
     | 
| 
      
 136 
     | 
    
         
            +
                    GLOBAL_VALUES
         
     | 
| 
      
 137 
     | 
    
         
            +
                  }
         
     | 
| 
      
 138 
     | 
    
         
            +
                }
         
     | 
| 
      
 139 
     | 
    
         
            +
              })
         
     | 
| 
       81 
140 
     | 
    
         
             
            end
         
     | 
| 
      
 141 
     | 
    
         
            +
            DummySchema = GraphQL::Schema.new(query: QueryType, mutation: MutationType)
         
     |