graphql 1.7.14 → 1.8.0.pre1
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 +5 -5
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +1 -6
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/graphql.rb +2 -0
- data/lib/graphql/argument.rb +0 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +18 -16
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +28 -0
- data/lib/graphql/directive.rb +0 -1
- data/lib/graphql/enum_type.rb +1 -3
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/execution/multiplex.rb +29 -12
- data/lib/graphql/field.rb +5 -20
- data/lib/graphql/function.rb +12 -0
- data/lib/graphql/input_object_type.rb +1 -3
- data/lib/graphql/internal_representation/node.rb +14 -26
- data/lib/graphql/internal_representation/visit.rb +6 -3
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- data/lib/graphql/introspection/interfaces_field.rb +0 -1
- data/lib/graphql/introspection/of_type_field.rb +0 -1
- data/lib/graphql/introspection/possible_types_field.rb +0 -1
- data/lib/graphql/introspection/schema_field.rb +0 -1
- data/lib/graphql/introspection/type_by_name_field.rb +0 -1
- data/lib/graphql/introspection/typename_field.rb +0 -1
- data/lib/graphql/language.rb +0 -3
- data/lib/graphql/language/generation.rb +182 -3
- data/lib/graphql/language/lexer.rb +69 -144
- data/lib/graphql/language/lexer.rl +4 -15
- data/lib/graphql/language/nodes.rb +76 -136
- data/lib/graphql/language/parser.rb +621 -668
- data/lib/graphql/language/parser.y +11 -17
- data/lib/graphql/language/token.rb +3 -10
- data/lib/graphql/object_type.rb +6 -1
- data/lib/graphql/query.rb +13 -8
- data/lib/graphql/query/arguments.rb +33 -48
- data/lib/graphql/query/context.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -4
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +19 -14
- data/lib/graphql/schema.rb +219 -12
- data/lib/graphql/schema/argument.rb +33 -0
- data/lib/graphql/schema/build_from_definition.rb +18 -64
- data/lib/graphql/schema/enum.rb +76 -0
- data/lib/graphql/schema/field.rb +127 -0
- data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
- data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
- data/lib/graphql/schema/input_object.rb +61 -0
- data/lib/graphql/schema/interface.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member.rb +97 -0
- data/lib/graphql/schema/member/build_type.rb +106 -0
- data/lib/graphql/schema/member/has_fields.rb +56 -0
- data/lib/graphql/schema/member/instrumentation.rb +113 -0
- data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
- data/lib/graphql/schema/object.rb +65 -0
- data/lib/graphql/schema/printer.rb +266 -33
- data/lib/graphql/schema/scalar.rb +25 -0
- data/lib/graphql/schema/traversal.rb +26 -17
- data/lib/graphql/schema/union.rb +48 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
- data/lib/graphql/tracing.rb +0 -1
- data/lib/graphql/tracing/platform_tracing.rb +7 -20
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -3
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +1 -22
- data/spec/dummy/log/development.log +0 -239
- data/spec/dummy/log/test.log +0 -204
- data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/generators/graphql/function_generator_spec.rb +0 -26
- data/spec/generators/graphql/loader_generator_spec.rb +0 -24
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/backtrace_spec.rb +0 -10
- data/spec/graphql/base_type_spec.rb +5 -19
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +1 -3
- data/spec/graphql/enum_type_spec.rb +5 -18
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +2 -15
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +0 -1
- data/spec/graphql/language/generation_spec.rb +186 -21
- data/spec/graphql/language/lexer_spec.rb +1 -21
- data/spec/graphql/language/nodes_spec.rb +12 -21
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/query/arguments_spec.rb +15 -37
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +5 -31
- data/spec/graphql/rake_task_spec.rb +1 -3
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +3 -3
- data/spec/graphql/relay/relation_connection_spec.rb +1 -65
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
- data/spec/graphql/schema/enum_spec.rb +60 -0
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/input_object_spec.rb +43 -0
- data/spec/graphql/schema/interface_spec.rb +98 -0
- data/spec/graphql/schema/object_spec.rb +119 -0
- data/spec/graphql/schema/printer_spec.rb +15 -92
- data/spec/graphql/schema/scalar_spec.rb +40 -0
- data/spec/graphql/schema/union_spec.rb +35 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +25 -23
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +1 -1
- data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
- data/spec/support/dummy/schema.rb +25 -39
- data/spec/support/jazz.rb +334 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/star_wars/data.rb +7 -6
- data/spec/support/star_wars/schema.rb +109 -142
- metadata +39 -33
- data/lib/graphql/execution/instrumentation.rb +0 -82
- data/lib/graphql/language/block_string.rb +0 -47
- data/lib/graphql/language/document_from_schema_definition.rb +0 -277
- data/lib/graphql/language/printer.rb +0 -351
- data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
- data/spec/graphql/execution/instrumentation_spec.rb +0 -165
- data/spec/graphql/language/block_string_spec.rb +0 -70
- data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
- data/spec/graphql/language/printer_spec.rb +0 -203
| @@ -0,0 +1,334 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Here's the "application"
         | 
| 4 | 
            +
            module Jazz
         | 
| 5 | 
            +
              module Models
         | 
| 6 | 
            +
                Instrument = Struct.new(:name, :family)
         | 
| 7 | 
            +
                Ensemble = Struct.new(:name)
         | 
| 8 | 
            +
                Musician = Struct.new(:name, :favorite_key)
         | 
| 9 | 
            +
                Key = Struct.new(:root, :sharp, :flat) do
         | 
| 10 | 
            +
                  def self.from_notation(key_str)
         | 
| 11 | 
            +
                    key, sharp_or_flat = key_str.split("")
         | 
| 12 | 
            +
                    sharp = sharp_or_flat ==  "♯"
         | 
| 13 | 
            +
                    flat = sharp_or_flat == "♭"
         | 
| 14 | 
            +
                    Models::Key.new(key, sharp, flat)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def to_notation
         | 
| 18 | 
            +
                    "#{root}#{sharp ? "♯" : ""}#{flat ? "♭" : ""}"
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def self.reset
         | 
| 23 | 
            +
                  @data = {
         | 
| 24 | 
            +
                    "Instrument" => [
         | 
| 25 | 
            +
                      Models::Instrument.new("Banjo", :str),
         | 
| 26 | 
            +
                      Models::Instrument.new("Flute", "WOODWIND"),
         | 
| 27 | 
            +
                      Models::Instrument.new("Trumpet", "BRASS"),
         | 
| 28 | 
            +
                      Models::Instrument.new("Piano", "KEYS"),
         | 
| 29 | 
            +
                      Models::Instrument.new("Organ", "KEYS"),
         | 
| 30 | 
            +
                      Models::Instrument.new("Drum Kit", "PERCUSSION"),
         | 
| 31 | 
            +
                    ],
         | 
| 32 | 
            +
                    "Ensemble" => [
         | 
| 33 | 
            +
                      Models::Ensemble.new("Bela Fleck and the Flecktones"),
         | 
| 34 | 
            +
                    ],
         | 
| 35 | 
            +
                    "Musician" => [
         | 
| 36 | 
            +
                      Models::Musician.new("Herbie Hancock", Models::Key.from_notation("B♭")),
         | 
| 37 | 
            +
                    ]
         | 
| 38 | 
            +
                  }
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def self.data
         | 
| 42 | 
            +
                  @data || reset
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              class BaseArgument < GraphQL::Schema::Argument
         | 
| 47 | 
            +
                def initialize(name, type, desc = nil, custom: nil, **kwargs)
         | 
| 48 | 
            +
                  @custom = custom
         | 
| 49 | 
            +
                  super(name, type, desc, **kwargs)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def to_graphql
         | 
| 53 | 
            +
                  arg_defn = super
         | 
| 54 | 
            +
                  arg_defn.metadata[:custom] = @custom
         | 
| 55 | 
            +
                  arg_defn
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              # A custom field class that supports the `upcase:` option
         | 
| 60 | 
            +
              class BaseField < GraphQL::Schema::Field
         | 
| 61 | 
            +
                argument_class BaseArgument
         | 
| 62 | 
            +
                def initialize(*args, options, &block)
         | 
| 63 | 
            +
                  @upcase = options.delete(:upcase)
         | 
| 64 | 
            +
                  super(*args, options, &block)
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def to_graphql
         | 
| 68 | 
            +
                  field_defn = super
         | 
| 69 | 
            +
                  if @upcase
         | 
| 70 | 
            +
                    inner_resolve = field_defn.resolve_proc
         | 
| 71 | 
            +
                    field_defn.resolve = ->(obj, args, ctx) {
         | 
| 72 | 
            +
                      inner_resolve.call(obj, args, ctx).upcase
         | 
| 73 | 
            +
                    }
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  field_defn
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              class BaseObject < GraphQL::Schema::Object
         | 
| 80 | 
            +
                # Use this overridden field class
         | 
| 81 | 
            +
                field_class BaseField
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                class << self
         | 
| 84 | 
            +
                  def config(key, value)
         | 
| 85 | 
            +
                    configs[key] = value
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  def configs
         | 
| 89 | 
            +
                    @configs ||= {}
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  def to_graphql
         | 
| 93 | 
            +
                    type_defn = super
         | 
| 94 | 
            +
                    configs.each do |k,v|
         | 
| 95 | 
            +
                      type_defn.metadata[k] = v
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                    type_defn
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              class BaseInterface < GraphQL::Schema::Interface
         | 
| 103 | 
            +
                # Use this overridden field class
         | 
| 104 | 
            +
                field_class BaseField
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
             | 
| 108 | 
            +
              # Some arbitrary global ID scheme
         | 
| 109 | 
            +
              # *Type suffix is removed automatically
         | 
| 110 | 
            +
              class GloballyIdentifiableType < BaseInterface
         | 
| 111 | 
            +
                description "A fetchable object in the system"
         | 
| 112 | 
            +
                field :id, ID, "A unique identifier for this object", null: false
         | 
| 113 | 
            +
                field :upcasedId, ID, null: false, upcase: true, method: :id
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                module Implementation
         | 
| 116 | 
            +
                  def id
         | 
| 117 | 
            +
                    GloballyIdentifiableType.to_id(@object)
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                def self.to_id(object)
         | 
| 122 | 
            +
                  "#{object.class.name.split("::").last}/#{object.name}"
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                def self.find(id)
         | 
| 126 | 
            +
                  class_name, object_name = id.split("/")
         | 
| 127 | 
            +
                  Models.data[class_name].find { |obj| obj.name == object_name }
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
              end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
              # A legacy-style interface used by new-style types
         | 
| 132 | 
            +
              NamedEntity = GraphQL::InterfaceType.define do
         | 
| 133 | 
            +
                name "NamedEntity"
         | 
| 134 | 
            +
                field :name, !types.String
         | 
| 135 | 
            +
              end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
              # test field inheritance
         | 
| 138 | 
            +
              class ObjectWithUpcasedName < BaseObject
         | 
| 139 | 
            +
                # Test extra arguments:
         | 
| 140 | 
            +
                field :upcaseName, String, null: false, upcase: true
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                def upcase_name
         | 
| 143 | 
            +
                  @object.name # upcase is applied by the superclass
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
              end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
              # Here's a new-style GraphQL type definition
         | 
| 148 | 
            +
              class Ensemble < ObjectWithUpcasedName
         | 
| 149 | 
            +
                implements GloballyIdentifiableType, NamedEntity
         | 
| 150 | 
            +
                description "A group of musicians playing together"
         | 
| 151 | 
            +
                config :config, :configged
         | 
| 152 | 
            +
                # Test string type names:
         | 
| 153 | 
            +
                field :name, "String", null: false
         | 
| 154 | 
            +
                field :musicians, "[Jazz::Musician]", null: false
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
              class Family < GraphQL::Schema::Enum
         | 
| 158 | 
            +
                description "Groups of musical instruments"
         | 
| 159 | 
            +
                # support string and symbol
         | 
| 160 | 
            +
                value "STRING", "Makes a sound by vibrating strings", value: :str
         | 
| 161 | 
            +
                value :WOODWIND, "Makes a sound by vibrating air in a pipe"
         | 
| 162 | 
            +
                value :BRASS, "Makes a sound by amplifying the sound of buzzing lips"
         | 
| 163 | 
            +
                value "PERCUSSION", "Makes a sound by hitting something that vibrates"
         | 
| 164 | 
            +
                value "KEYS", "Neither here nor there, really"
         | 
| 165 | 
            +
                value "DIDGERIDOO", "Makes a sound by amplifying the sound of buzzing lips", deprecation_reason: "Merged into BRASS"
         | 
| 166 | 
            +
              end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
              # Lives side-by-side with an old-style definition
         | 
| 169 | 
            +
              using GraphQL::DeprecatedDSL # for ! and types[]
         | 
| 170 | 
            +
              InstrumentType = GraphQL::ObjectType.define do
         | 
| 171 | 
            +
                name "Instrument"
         | 
| 172 | 
            +
                interfaces [NamedEntity]
         | 
| 173 | 
            +
                implements GloballyIdentifiableType
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                field :id, !types.ID, "A unique identifier for this object", resolve: ->(obj, args, ctx) { GloballyIdentifiableType.to_id(obj) }
         | 
| 176 | 
            +
                field :upcasedId, !types.ID, resolve: ->(obj, args, ctx) { GloballyIdentifiableType.to_id(obj).upcase }
         | 
| 177 | 
            +
                if RUBY_ENGINE == "jruby"
         | 
| 178 | 
            +
                  # JRuby doesn't support refinements, so the `using` above won't work
         | 
| 179 | 
            +
                  field :family, Family.to_non_null_type
         | 
| 180 | 
            +
                else
         | 
| 181 | 
            +
                  field :family, !Family
         | 
| 182 | 
            +
                end
         | 
| 183 | 
            +
              end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
              class Key < GraphQL::Schema::Scalar
         | 
| 186 | 
            +
                description "A musical key"
         | 
| 187 | 
            +
                def self.coerce_input(val, ctx)
         | 
| 188 | 
            +
                  Models::Key.from_notation(val)
         | 
| 189 | 
            +
                end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                def self.coerce_result(val, ctx)
         | 
| 192 | 
            +
                  val.to_notation
         | 
| 193 | 
            +
                end
         | 
| 194 | 
            +
              end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
              class Musician < BaseObject
         | 
| 197 | 
            +
                implements GloballyIdentifiableType
         | 
| 198 | 
            +
                implements NamedEntity
         | 
| 199 | 
            +
                description "Someone who plays an instrument"
         | 
| 200 | 
            +
                field :instrument, InstrumentType, null: false
         | 
| 201 | 
            +
                field :favoriteKey, Key, null: true
         | 
| 202 | 
            +
              end
         | 
| 203 | 
            +
             | 
| 204 | 
            +
              LegacyInputType = GraphQL::InputObjectType.define do
         | 
| 205 | 
            +
                name "LegacyInput"
         | 
| 206 | 
            +
                argument :intValue, !types.Int
         | 
| 207 | 
            +
              end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
              class InspectableInput < GraphQL::Schema::InputObject
         | 
| 210 | 
            +
                argument :stringValue, String, required: true
         | 
| 211 | 
            +
                argument :nestedInput, InspectableInput, required: false
         | 
| 212 | 
            +
                argument :legacyInput, LegacyInputType, required: false
         | 
| 213 | 
            +
                def helper_method
         | 
| 214 | 
            +
                  [
         | 
| 215 | 
            +
                    # Context is available in the InputObject
         | 
| 216 | 
            +
                    @context[:message],
         | 
| 217 | 
            +
                    # A GraphQL::Query::Arguments instance is available
         | 
| 218 | 
            +
                    @arguments[:stringValue],
         | 
| 219 | 
            +
                    # Legacy inputs have underscored method access too
         | 
| 220 | 
            +
                    legacy_input ? legacy_input.int_value : "-",
         | 
| 221 | 
            +
                    # Access by method call is available
         | 
| 222 | 
            +
                    "(#{nested_input ? nested_input.helper_method : "-"})",
         | 
| 223 | 
            +
                  ].join(", ")
         | 
| 224 | 
            +
                end
         | 
| 225 | 
            +
              end
         | 
| 226 | 
            +
             | 
| 227 | 
            +
              class InspectableKey < BaseObject
         | 
| 228 | 
            +
                field :root, String, null: false
         | 
| 229 | 
            +
                field :isSharp, Boolean, null: false, method: :sharp
         | 
| 230 | 
            +
                field :isFlat, Boolean, null: false, method: :flat
         | 
| 231 | 
            +
              end
         | 
| 232 | 
            +
             | 
| 233 | 
            +
              class PerformingAct < GraphQL::Schema::Union
         | 
| 234 | 
            +
                possible_types Musician, Ensemble
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                def resolve_type
         | 
| 237 | 
            +
                  if @object.is_a?(Models::Ensemble)
         | 
| 238 | 
            +
                    Ensemble
         | 
| 239 | 
            +
                  else
         | 
| 240 | 
            +
                    Musician
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
              end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
              # Another new-style definition, with method overrides
         | 
| 246 | 
            +
              class Query < BaseObject
         | 
| 247 | 
            +
                field :ensembles, [Ensemble], null: false
         | 
| 248 | 
            +
                field :find, GloballyIdentifiableType, null: true do
         | 
| 249 | 
            +
                  argument :id, ID, required: true, custom: :ok
         | 
| 250 | 
            +
                end
         | 
| 251 | 
            +
                field :instruments, [InstrumentType], null: false do
         | 
| 252 | 
            +
                  argument :family, Family, required: false
         | 
| 253 | 
            +
                end
         | 
| 254 | 
            +
                field :inspectInput, [String], null: false do
         | 
| 255 | 
            +
                  argument :input, InspectableInput, required: true
         | 
| 256 | 
            +
                end
         | 
| 257 | 
            +
                field :inspectKey, InspectableKey, null: false do
         | 
| 258 | 
            +
                  argument :key, Key, required: true
         | 
| 259 | 
            +
                end
         | 
| 260 | 
            +
                field :nowPlaying, PerformingAct, null: false, resolve: ->(o, a, c) { Models.data["Ensemble"].first }
         | 
| 261 | 
            +
                # For asserting that the object is initialized once:
         | 
| 262 | 
            +
                field :objectId, Integer, null: false
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                def ensembles
         | 
| 265 | 
            +
                  Models.data["Ensemble"]
         | 
| 266 | 
            +
                end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                def find(id:)
         | 
| 269 | 
            +
                  if id == "MagicalSkipId"
         | 
| 270 | 
            +
                    @context.skip
         | 
| 271 | 
            +
                  else
         | 
| 272 | 
            +
                    GloballyIdentifiableType.find(id)
         | 
| 273 | 
            +
                  end
         | 
| 274 | 
            +
                end
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                def instruments(family: nil)
         | 
| 277 | 
            +
                  objs = Models.data["Instrument"]
         | 
| 278 | 
            +
                  if family
         | 
| 279 | 
            +
                    objs = objs.select { |i| i.family == family }
         | 
| 280 | 
            +
                  end
         | 
| 281 | 
            +
                  objs
         | 
| 282 | 
            +
                end
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                # This is for testing input object behavior
         | 
| 285 | 
            +
                def inspect_input(input:)
         | 
| 286 | 
            +
                  [
         | 
| 287 | 
            +
                    input.class.name,
         | 
| 288 | 
            +
                    input.helper_method,
         | 
| 289 | 
            +
                    # Access by method
         | 
| 290 | 
            +
                    input.string_value,
         | 
| 291 | 
            +
                    # Access by key:
         | 
| 292 | 
            +
                    input["stringValue"],
         | 
| 293 | 
            +
                    input[:stringValue],
         | 
| 294 | 
            +
                  ]
         | 
| 295 | 
            +
                end
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                def inspect_key(key:)
         | 
| 298 | 
            +
                  key
         | 
| 299 | 
            +
                end
         | 
| 300 | 
            +
              end
         | 
| 301 | 
            +
             | 
| 302 | 
            +
              class EnsembleInput < GraphQL::Schema::InputObject
         | 
| 303 | 
            +
                argument :name, String, required: true
         | 
| 304 | 
            +
              end
         | 
| 305 | 
            +
             | 
| 306 | 
            +
              class Mutation < BaseObject
         | 
| 307 | 
            +
                field :addEnsemble, Ensemble, null: false do
         | 
| 308 | 
            +
                  argument :input, EnsembleInput, required: true
         | 
| 309 | 
            +
                end
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                def add_ensemble(input:)
         | 
| 312 | 
            +
                  ens = Models::Ensemble.new(input.name)
         | 
| 313 | 
            +
                  Models.data["Ensemble"] << ens
         | 
| 314 | 
            +
                  ens
         | 
| 315 | 
            +
                end
         | 
| 316 | 
            +
              end
         | 
| 317 | 
            +
             | 
| 318 | 
            +
              class MetadataPlugin
         | 
| 319 | 
            +
                def self.use(schema_defn, value:)
         | 
| 320 | 
            +
                  schema_defn.target.metadata[:plugin_key] = value
         | 
| 321 | 
            +
                end
         | 
| 322 | 
            +
              end
         | 
| 323 | 
            +
             | 
| 324 | 
            +
              # New-style Schema definition
         | 
| 325 | 
            +
              class Schema < GraphQL::Schema
         | 
| 326 | 
            +
                query(Query)
         | 
| 327 | 
            +
                mutation(Mutation)
         | 
| 328 | 
            +
                use MetadataPlugin, value: "xyz"
         | 
| 329 | 
            +
                def self.resolve_type(type, obj, ctx)
         | 
| 330 | 
            +
                  class_name = obj.class.name.split("::").last
         | 
| 331 | 
            +
                  ctx.schema.types[class_name] || raise("No type for #{obj.inspect}")
         | 
| 332 | 
            +
                end
         | 
| 333 | 
            +
              end
         | 
| 334 | 
            +
            end
         | 
| @@ -46,32 +46,30 @@ module LazyHelpers | |
| 46 46 | 
             
                end
         | 
| 47 47 | 
             
              end
         | 
| 48 48 |  | 
| 49 | 
            -
              LazySum  | 
| 50 | 
            -
                 | 
| 51 | 
            -
                field : | 
| 52 | 
            -
                   | 
| 49 | 
            +
              class LazySum < GraphQL::Schema::Object
         | 
| 50 | 
            +
                field :value, Integer, null: true, resolve: ->(o, a, c) { o == 13 ? nil : o }
         | 
| 51 | 
            +
                field :nestedSum, LazySum, null: false do
         | 
| 52 | 
            +
                  argument :value, Integer, required: true
         | 
| 53 53 | 
             
                end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
                   | 
| 57 | 
            -
                     | 
| 58 | 
            -
             | 
| 59 | 
            -
                     | 
| 60 | 
            -
             | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
                  }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def nested_sum(value:)
         | 
| 56 | 
            +
                  if value == 13
         | 
| 57 | 
            +
                    Wrapper.new(nil)
         | 
| 58 | 
            +
                  else
         | 
| 59 | 
            +
                    SumAll.new(@context, @object + value)
         | 
| 60 | 
            +
                  end
         | 
| 63 61 | 
             
                end
         | 
| 64 62 |  | 
| 65 | 
            -
                field :nullableNestedSum, LazySum do
         | 
| 66 | 
            -
                  argument :value,  | 
| 67 | 
            -
                  resolve ->(o, args, c) {
         | 
| 68 | 
            -
                    if args[:value] == 13
         | 
| 69 | 
            -
                      Wrapper.new(nil)
         | 
| 70 | 
            -
                    else
         | 
| 71 | 
            -
                      SumAll.new(c, o + args[:value])
         | 
| 72 | 
            -
                    end
         | 
| 73 | 
            -
                  }
         | 
| 63 | 
            +
                field :nullableNestedSum, LazySum, null: true do
         | 
| 64 | 
            +
                  argument :value, Integer, required: true
         | 
| 74 65 | 
             
                end
         | 
| 66 | 
            +
                alias :nullable_nested_sum :nested_sum
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              using GraphQL::DeprecatedDSL
         | 
| 70 | 
            +
              if RUBY_ENGINE == "jruby"
         | 
| 71 | 
            +
                # JRuby doesn't support refinements, so the `using` above won't work
         | 
| 72 | 
            +
                GraphQL::DeprecatedDSL.activate
         | 
| 75 73 | 
             
              end
         | 
| 76 74 |  | 
| 77 75 | 
             
              LazyQuery = GraphQL::ObjectType.define do
         | 
| @@ -136,7 +134,7 @@ module LazyHelpers | |
| 136 134 | 
             
                end
         | 
| 137 135 | 
             
              end
         | 
| 138 136 |  | 
| 139 | 
            -
              LazySchema  | 
| 137 | 
            +
              class LazySchema < GraphQL::Schema
         | 
| 140 138 | 
             
                query(LazyQuery)
         | 
| 141 139 | 
             
                mutation(LazyQuery)
         | 
| 142 140 | 
             
                lazy_resolve(Wrapper, :item)
         | 
| @@ -18,12 +18,13 @@ module StarWars | |
| 18 18 | 
             
                'Executor',
         | 
| 19 19 | 
             
              ]
         | 
| 20 20 |  | 
| 21 | 
            +
              # ActiveRecord::Base.logger = Logger.new(STDOUT)
         | 
| 21 22 | 
             
              `rm -f ./_test_.db`
         | 
| 22 23 | 
             
              # Set up "Bases" in ActiveRecord
         | 
| 23 24 |  | 
| 24 25 | 
             
              if jruby?
         | 
| 25 26 | 
             
                ActiveRecord::Base.establish_connection(adapter: "jdbcsqlite3", database: "./_test_.db")
         | 
| 26 | 
            -
                 | 
| 27 | 
            +
                Sequel.connect('jdbc:sqlite:./_test_.db')
         | 
| 27 28 | 
             
              elsif ENV['DATABASE'] == 'POSTGRESQL'
         | 
| 28 29 | 
             
                ActiveRecord::Base.establish_connection(
         | 
| 29 30 | 
             
                  adapter: "postgresql",
         | 
| @@ -59,13 +60,13 @@ module StarWars | |
| 59 60 | 
             
              end
         | 
| 60 61 |  | 
| 61 62 | 
             
              class FactionRecord
         | 
| 62 | 
            -
                attr_reader :id, :name, :ships, :bases, : | 
| 63 | 
            -
                def initialize(id:, name:, ships:, bases:,  | 
| 63 | 
            +
                attr_reader :id, :name, :ships, :bases, :bases_clone
         | 
| 64 | 
            +
                def initialize(id:, name:, ships:, bases:, bases_clone:)
         | 
| 64 65 | 
             
                  @id = id
         | 
| 65 66 | 
             
                  @name = name
         | 
| 66 67 | 
             
                  @ships = ships
         | 
| 67 68 | 
             
                  @bases = bases
         | 
| 68 | 
            -
                  @ | 
| 69 | 
            +
                  @bases_clone = bases_clone
         | 
| 69 70 | 
             
                end
         | 
| 70 71 | 
             
              end
         | 
| 71 72 |  | 
| @@ -74,7 +75,7 @@ module StarWars | |
| 74 75 | 
             
                name: 'Alliance to Restore the Republic',
         | 
| 75 76 | 
             
                ships:  ['1', '2', '3', '4', '5'],
         | 
| 76 77 | 
             
                bases: Base.where(faction_id: 1),
         | 
| 77 | 
            -
                 | 
| 78 | 
            +
                bases_clone: Base.where(faction_id: 1),
         | 
| 78 79 | 
             
              })
         | 
| 79 80 |  | 
| 80 81 |  | 
| @@ -83,7 +84,7 @@ module StarWars | |
| 83 84 | 
             
                name: 'Galactic Empire',
         | 
| 84 85 | 
             
                ships: ['6', '7', '8'],
         | 
| 85 86 | 
             
                bases: Base.where(faction_id: 2),
         | 
| 86 | 
            -
                 | 
| 87 | 
            +
                bases_clone: Base.where(faction_id: 2),
         | 
| 87 88 | 
             
              })
         | 
| 88 89 |  | 
| 89 90 | 
             
              DATA = {
         | 
| @@ -3,31 +3,28 @@ module StarWars | |
| 3 3 | 
             
              # Adapted from graphql-relay-js
         | 
| 4 4 | 
             
              # https://github.com/graphql/graphql-relay-js/blob/master/src/__tests__/starWarsSchema.js
         | 
| 5 5 |  | 
| 6 | 
            -
              Ship  | 
| 7 | 
            -
                 | 
| 8 | 
            -
                interfaces [GraphQL::Relay::Node.interface]
         | 
| 6 | 
            +
              class Ship < GraphQL::Schema::Object
         | 
| 7 | 
            +
                implements GraphQL::Relay::Node.interface
         | 
| 9 8 | 
             
                global_id_field :id
         | 
| 10 | 
            -
                field :name,  | 
| 9 | 
            +
                field :name, String, null: true
         | 
| 11 10 | 
             
                # Test cyclical connection types:
         | 
| 12 | 
            -
                 | 
| 11 | 
            +
                field :ships, Ship.connection_type, null: false
         | 
| 13 12 | 
             
              end
         | 
| 14 13 |  | 
| 15 | 
            -
              BaseType  | 
| 16 | 
            -
                 | 
| 17 | 
            -
                 | 
| 14 | 
            +
              class BaseType < GraphQL::Schema::Object
         | 
| 15 | 
            +
                graphql_name "Base"
         | 
| 16 | 
            +
                implements GraphQL::Relay::Node.interface
         | 
| 18 17 | 
             
                global_id_field :id
         | 
| 19 | 
            -
                field :name,  | 
| 20 | 
            -
                   | 
| 21 | 
            -
                     | 
| 22 | 
            -
                       | 
| 23 | 
            -
             | 
| 24 | 
            -
                       | 
| 25 | 
            -
             | 
| 26 | 
            -
                      end
         | 
| 27 | 
            -
                    }
         | 
| 18 | 
            +
                field :name, String, null: false, resolve: ->(obj, args, ctx) {
         | 
| 19 | 
            +
                  LazyWrapper.new {
         | 
| 20 | 
            +
                    if obj.id.nil?
         | 
| 21 | 
            +
                      raise GraphQL::ExecutionError, "Boom!"
         | 
| 22 | 
            +
                    else
         | 
| 23 | 
            +
                      obj.name
         | 
| 24 | 
            +
                    end
         | 
| 28 25 | 
             
                  }
         | 
| 29 | 
            -
                 | 
| 30 | 
            -
                field :planet,  | 
| 26 | 
            +
                }
         | 
| 27 | 
            +
                field :planet, String, null: true
         | 
| 31 28 | 
             
              end
         | 
| 32 29 |  | 
| 33 30 | 
             
              # Use an optional block to add fields to the connection type:
         | 
| @@ -90,103 +87,81 @@ module StarWars | |
| 90 87 | 
             
                end
         | 
| 91 88 | 
             
              end
         | 
| 92 89 |  | 
| 93 | 
            -
              Faction  | 
| 94 | 
            -
                 | 
| 95 | 
            -
                interfaces [GraphQL::Relay::Node.interface]
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                field :id, !types.ID, resolve: GraphQL::Relay::GlobalIdResolve.new(type: Faction)
         | 
| 98 | 
            -
                field :name, types.String
         | 
| 99 | 
            -
                connection :ships, ShipConnectionWithParentType, max_page_size: 1000 do
         | 
| 100 | 
            -
                  resolve ->(obj, args, ctx) {
         | 
| 101 | 
            -
                    all_ships = obj.ships.map {|ship_id| StarWars::DATA["Ship"][ship_id] }
         | 
| 102 | 
            -
                    if args[:nameIncludes]
         | 
| 103 | 
            -
                      case args[:nameIncludes]
         | 
| 104 | 
            -
                      when "error"
         | 
| 105 | 
            -
                        all_ships = GraphQL::ExecutionError.new("error from within connection")
         | 
| 106 | 
            -
                      when "raisedError"
         | 
| 107 | 
            -
                        raise GraphQL::ExecutionError.new("error raised from within connection")
         | 
| 108 | 
            -
                      when "lazyError"
         | 
| 109 | 
            -
                        all_ships = LazyWrapper.new { GraphQL::ExecutionError.new("lazy error from within connection") }
         | 
| 110 | 
            -
                      when "lazyRaisedError"
         | 
| 111 | 
            -
                        all_ships = LazyWrapper.new { raise GraphQL::ExecutionError.new("lazy raised error from within connection") }
         | 
| 112 | 
            -
                      when "null"
         | 
| 113 | 
            -
                        all_ships = nil
         | 
| 114 | 
            -
                      when "lazyObject"
         | 
| 115 | 
            -
                        prev_all_ships = all_ships
         | 
| 116 | 
            -
                        all_ships = LazyWrapper.new { prev_all_ships }
         | 
| 117 | 
            -
                      else
         | 
| 118 | 
            -
                        all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])}
         | 
| 119 | 
            -
                      end
         | 
| 120 | 
            -
                    end
         | 
| 121 | 
            -
                    all_ships
         | 
| 122 | 
            -
                  }
         | 
| 123 | 
            -
                  # You can define arguments here and use them in the connection
         | 
| 124 | 
            -
                  argument :nameIncludes, types.String
         | 
| 125 | 
            -
                end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                connection :shipsWithMaxPageSize, max_page_size: 2, function: ShipsWithMaxPageSize.new
         | 
| 90 | 
            +
              class Faction < GraphQL::Schema::Object
         | 
| 91 | 
            +
                implements GraphQL::Relay::Node.interface
         | 
| 128 92 |  | 
| 129 | 
            -
                 | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
                   | 
| 133 | 
            -
             | 
| 134 | 
            -
                     | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
                     | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
                       | 
| 93 | 
            +
                field :id, ID, null: false, resolve: GraphQL::Relay::GlobalIdResolve.new(type: Faction)
         | 
| 94 | 
            +
                field :name, String, null: true
         | 
| 95 | 
            +
                field :ships, ShipConnectionWithParentType, connection: true, max_page_size: 1000, null: true, resolve: ->(obj, args, ctx) {
         | 
| 96 | 
            +
                  all_ships = obj.ships.map {|ship_id| StarWars::DATA["Ship"][ship_id] }
         | 
| 97 | 
            +
                  if args[:nameIncludes]
         | 
| 98 | 
            +
                    case args[:nameIncludes]
         | 
| 99 | 
            +
                    when "error"
         | 
| 100 | 
            +
                      all_ships = GraphQL::ExecutionError.new("error from within connection")
         | 
| 101 | 
            +
                    when "raisedError"
         | 
| 102 | 
            +
                      raise GraphQL::ExecutionError.new("error raised from within connection")
         | 
| 103 | 
            +
                    when "lazyError"
         | 
| 104 | 
            +
                      all_ships = LazyWrapper.new { GraphQL::ExecutionError.new("lazy error from within connection") }
         | 
| 105 | 
            +
                    when "lazyRaisedError"
         | 
| 106 | 
            +
                      all_ships = LazyWrapper.new { raise GraphQL::ExecutionError.new("lazy raised error from within connection") }
         | 
| 107 | 
            +
                    when "null"
         | 
| 108 | 
            +
                      all_ships = nil
         | 
| 109 | 
            +
                    when "lazyObject"
         | 
| 110 | 
            +
                      prev_all_ships = all_ships
         | 
| 111 | 
            +
                      all_ships = LazyWrapper.new { prev_all_ships }
         | 
| 148 112 | 
             
                    else
         | 
| 149 | 
            -
                       | 
| 113 | 
            +
                      all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])}
         | 
| 150 114 | 
             
                    end
         | 
| 151 | 
            -
                   | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                  all_ships
         | 
| 117 | 
            +
                } do
         | 
| 118 | 
            +
                  # You can define arguments here and use them in the connection
         | 
| 119 | 
            +
                  argument :nameIncludes, String, required: false
         | 
| 152 120 | 
             
                end
         | 
| 153 121 |  | 
| 154 | 
            -
                 | 
| 155 | 
            -
                  resolve ->(object, args, context) { Base.all }
         | 
| 156 | 
            -
                end
         | 
| 122 | 
            +
                field :shipsWithMaxPageSize, max_page_size: 2, function: ShipsWithMaxPageSize.new
         | 
| 157 123 |  | 
| 158 | 
            -
                 | 
| 159 | 
            -
                   | 
| 124 | 
            +
                field :bases, BaseConnectionWithTotalCountType, null: true, connection: true, resolve: ->(obj, args, ctx) {
         | 
| 125 | 
            +
                  all_bases = Base.where(id: obj.bases)
         | 
| 126 | 
            +
                  if args[:nameIncludes]
         | 
| 127 | 
            +
                    all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%")
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                  all_bases
         | 
| 130 | 
            +
                } do
         | 
| 131 | 
            +
                  argument :nameIncludes, String, required: false
         | 
| 160 132 | 
             
                end
         | 
| 161 133 |  | 
| 162 | 
            -
                 | 
| 163 | 
            -
             | 
| 134 | 
            +
                field :basesClone, BaseType.connection_type, null: true
         | 
| 135 | 
            +
                field :basesByName, BaseType.connection_type, null: true do
         | 
| 136 | 
            +
                  argument :order, String, default_value: "name", required: false
         | 
| 164 137 | 
             
                end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 167 | 
            -
             | 
| 138 | 
            +
                def bases_by_name(order: nil)
         | 
| 139 | 
            +
                  if order.present?
         | 
| 140 | 
            +
                    @object.bases.order(order)
         | 
| 141 | 
            +
                  else
         | 
| 142 | 
            +
                    @object.bases
         | 
| 143 | 
            +
                  end
         | 
| 168 144 | 
             
                end
         | 
| 169 145 |  | 
| 170 | 
            -
                 | 
| 171 | 
            -
             | 
| 172 | 
            -
                 | 
| 146 | 
            +
                field :basesWithMaxLimitRelation, BaseType.connection_type, null: true, max_page_size: 2, resolve: Proc.new { Base.all}
         | 
| 147 | 
            +
                field :basesWithMaxLimitArray, BaseType.connection_type, null: true, max_page_size: 2, resolve: Proc.new { Base.all.to_a }
         | 
| 148 | 
            +
                field :basesWithDefaultMaxLimitRelation, BaseType.connection_type, null: true, resolve: Proc.new { Base.all }
         | 
| 149 | 
            +
                field :basesWithDefaultMaxLimitArray, BaseType.connection_type, null: true, resolve: Proc.new { Base.all.to_a }
         | 
| 150 | 
            +
                field :basesWithLargeMaxLimitRelation, BaseType.connection_type, null: true, max_page_size: 1000, resolve: Proc.new { Base.all }
         | 
| 173 151 |  | 
| 174 | 
            -
                 | 
| 175 | 
            -
                  argument :nameIncludes,  | 
| 176 | 
            -
                  resolve ->(obj, args, ctx) {
         | 
| 177 | 
            -
                    all_bases = SequelBase.where(faction_id: obj.id)
         | 
| 178 | 
            -
                    if args[:nameIncludes]
         | 
| 179 | 
            -
                      all_bases = all_bases.where(Sequel.like(:name, "%#{args[:nameIncludes]}%"))
         | 
| 180 | 
            -
                    end
         | 
| 181 | 
            -
                    all_bases
         | 
| 182 | 
            -
                  }
         | 
| 152 | 
            +
                field :basesAsSequelDataset, BaseConnectionWithTotalCountType, null: true, connection: true, max_page_size: 1000 do
         | 
| 153 | 
            +
                  argument :nameIncludes, String, required: false
         | 
| 183 154 | 
             
                end
         | 
| 184 155 |  | 
| 185 | 
            -
                 | 
| 186 | 
            -
                   | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 156 | 
            +
                def bases_as_sequel_dataset(name_includes: nil)
         | 
| 157 | 
            +
                  all_bases = SequelBase.where(faction_id: @object.id)
         | 
| 158 | 
            +
                  if name_includes
         | 
| 159 | 
            +
                    all_bases = all_bases.where(Sequel.like(:name, "%#{name_includes}%"))
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                  all_bases
         | 
| 189 162 | 
             
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                field :basesWithCustomEdge, CustomEdgeBaseConnectionType, null: true, connection: true, resolve: ->(o, a, c) { LazyNodesWrapper.new(o.bases) }
         | 
| 190 165 | 
             
              end
         | 
| 191 166 |  | 
| 192 167 | 
             
              # Define a mutation. It will also:
         | 
| @@ -323,60 +298,52 @@ module StarWars | |
| 323 298 |  | 
| 324 299 | 
             
              GraphQL::Relay::BaseConnection.register_connection_implementation(LazyNodesWrapper, LazyNodesRelationConnection)
         | 
| 325 300 |  | 
| 326 | 
            -
              QueryType  | 
| 327 | 
            -
                 | 
| 328 | 
            -
                field :rebels, Faction do
         | 
| 329 | 
            -
                  resolve ->(obj, args, ctx) { StarWars::DATA["Faction"]["1"]}
         | 
| 330 | 
            -
                end
         | 
| 301 | 
            +
              class QueryType < GraphQL::Schema::Object
         | 
| 302 | 
            +
                graphql_name "Query"
         | 
| 331 303 |  | 
| 332 | 
            -
                field : | 
| 333 | 
            -
                  resolve ->(obj, args, ctx) { StarWars::DATA["Faction"]["2"]}
         | 
| 334 | 
            -
                end
         | 
| 304 | 
            +
                field :rebels, Faction, null: true, resolve: ->(obj, args, ctx) { StarWars::DATA["Faction"]["1"]}
         | 
| 335 305 |  | 
| 336 | 
            -
                field : | 
| 337 | 
            -
                  resolve ->(obj, args, ctx) { Base.find(3) }
         | 
| 338 | 
            -
                end
         | 
| 306 | 
            +
                field :empire, Faction, null: true, resolve: ->(obj, args, ctx) { StarWars::DATA["Faction"]["2"]}
         | 
| 339 307 |  | 
| 340 | 
            -
                 | 
| 341 | 
            -
                  resolve ->(obj, args, ctx) {
         | 
| 342 | 
            -
                    Base
         | 
| 343 | 
            -
                      .having('id in (select max(id) from bases group by faction_id)')
         | 
| 344 | 
            -
                      .group(:id)
         | 
| 345 | 
            -
                      .order('faction_id desc')
         | 
| 346 | 
            -
                  }
         | 
| 347 | 
            -
                end
         | 
| 308 | 
            +
                field :largestBase, BaseType, null: true, resolve: ->(obj, args, ctx) { Base.find(3) }
         | 
| 348 309 |  | 
| 349 | 
            -
                 | 
| 350 | 
            -
                   | 
| 351 | 
            -
                     | 
| 352 | 
            -
             | 
| 353 | 
            -
             | 
| 310 | 
            +
                field :newestBasesGroupedByFaction, BaseType.connection_type, null: true, resolve: ->(obj, args, ctx) {
         | 
| 311 | 
            +
                  Base
         | 
| 312 | 
            +
                    .having('id in (select max(id) from bases group by faction_id)')
         | 
| 313 | 
            +
                    .group(:id)
         | 
| 314 | 
            +
                    .order('faction_id desc')
         | 
| 315 | 
            +
                }
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                field :basesWithNullName, BaseType.connection_type, null: false, resolve: ->(obj, args, ctx) {
         | 
| 318 | 
            +
                  [OpenStruct.new(id: nil)]
         | 
| 319 | 
            +
                }
         | 
| 354 320 |  | 
| 355 | 
            -
                field :node, GraphQL::Relay::Node.field
         | 
| 321 | 
            +
                field :node, field: GraphQL::Relay::Node.field
         | 
| 356 322 |  | 
| 357 323 | 
             
                custom_node_field = GraphQL::Relay::Node.field do
         | 
| 358 324 | 
             
                  resolve ->(_, _, _) { StarWars::DATA["Faction"]["1"] }
         | 
| 359 325 | 
             
                end
         | 
| 360 | 
            -
                field :nodeWithCustomResolver, custom_node_field
         | 
| 326 | 
            +
                field :nodeWithCustomResolver, field: custom_node_field
         | 
| 361 327 |  | 
| 362 | 
            -
                field :nodes, GraphQL::Relay::Node.plural_field
         | 
| 363 | 
            -
                field :nodesWithCustomResolver, GraphQL::Relay::Node.plural_field(
         | 
| 328 | 
            +
                field :nodes, field: GraphQL::Relay::Node.plural_field
         | 
| 329 | 
            +
                field :nodesWithCustomResolver, field: GraphQL::Relay::Node.plural_field(
         | 
| 364 330 | 
             
                  resolve: ->(_, _, _) { [StarWars::DATA["Faction"]["1"], StarWars::DATA["Faction"]["2"]] }
         | 
| 365 331 | 
             
                )
         | 
| 366 332 |  | 
| 367 | 
            -
                field :batchedBase, BaseType do
         | 
| 368 | 
            -
                  argument :id,  | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 333 | 
            +
                field :batchedBase, BaseType, null: true do
         | 
| 334 | 
            +
                  argument :id, ID, required: true
         | 
| 335 | 
            +
                end
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                def batched_base(id:)
         | 
| 338 | 
            +
                  LazyLoader.defer(@context, Base, id)
         | 
| 372 339 | 
             
                end
         | 
| 373 340 | 
             
              end
         | 
| 374 341 |  | 
| 375 | 
            -
              MutationType  | 
| 376 | 
            -
                 | 
| 342 | 
            +
              class MutationType < GraphQL::Schema::Object
         | 
| 343 | 
            +
                graphql_name "Mutation"
         | 
| 377 344 | 
             
                # The mutation object exposes a field:
         | 
| 378 345 | 
             
                field :introduceShip, field: IntroduceShipMutation.field
         | 
| 379 | 
            -
                field :introduceShipFunction, IntroduceShipFunctionMutation.field
         | 
| 346 | 
            +
                field :introduceShipFunction, field: IntroduceShipFunctionMutation.field
         | 
| 380 347 | 
             
              end
         | 
| 381 348 |  | 
| 382 349 | 
             
              class ClassNameRecorder
         | 
| @@ -399,12 +366,12 @@ module StarWars | |
| 399 366 | 
             
                end
         | 
| 400 367 | 
             
              end
         | 
| 401 368 |  | 
| 402 | 
            -
              Schema  | 
| 369 | 
            +
              class Schema < GraphQL::Schema
         | 
| 403 370 | 
             
                query(QueryType)
         | 
| 404 371 | 
             
                mutation(MutationType)
         | 
| 405 372 | 
             
                default_max_page_size 3
         | 
| 406 373 |  | 
| 407 | 
            -
                resolve_type | 
| 374 | 
            +
                def self.resolve_type(type, object, ctx)
         | 
| 408 375 | 
             
                  if object == :test_error
         | 
| 409 376 | 
             
                    :not_a_type
         | 
| 410 377 | 
             
                  elsif object.is_a?(Base)
         | 
| @@ -416,14 +383,14 @@ module StarWars | |
| 416 383 | 
             
                  else
         | 
| 417 384 | 
             
                    nil
         | 
| 418 385 | 
             
                  end
         | 
| 419 | 
            -
                 | 
| 386 | 
            +
                end
         | 
| 420 387 |  | 
| 421 | 
            -
                object_from_id | 
| 388 | 
            +
                def self.object_from_id(node_id, ctx)
         | 
| 422 389 | 
             
                  type_name, id = GraphQL::Schema::UniqueWithinType.decode(node_id)
         | 
| 423 390 | 
             
                  StarWars::DATA[type_name][id]
         | 
| 424 391 | 
             
                end
         | 
| 425 392 |  | 
| 426 | 
            -
                id_from_object | 
| 393 | 
            +
                def self.id_from_object(object, type, ctx)
         | 
| 427 394 | 
             
                  GraphQL::Schema::UniqueWithinType.encode(type.name, object.id)
         | 
| 428 395 | 
             
                end
         | 
| 429 396 |  |