spec/support/star_wars/schema.rb in graphql-1.8.18 vs spec/support/star_wars/schema.rb in graphql-1.9.0.pre1

- old
+ new

@@ -13,19 +13,20 @@ class BaseType < GraphQL::Schema::Object graphql_name "Base" implements GraphQL::Relay::Node.interface global_id_field :id - field :name, String, null: false, resolve: ->(obj, args, ctx) { + field :name, String, null: false + def name LazyWrapper.new { - if obj.id.nil? + if object.id.nil? raise GraphQL::ExecutionError, "Boom!" else - obj.name + object.name end } - } + end field :planet, String, null: true end class BaseEdge < GraphQL::Types::Relay::BaseEdge @@ -84,22 +85,21 @@ def field_name object.field.name end end - # Example of GraphQL::Function used with the connection helper: - class ShipsWithMaxPageSize < GraphQL::Function - argument :nameIncludes, GraphQL::STRING_TYPE - def call(obj, args, ctx) - all_ships = obj.ships.map { |ship_id| StarWars::DATA["Ship"][ship_id] } - if args[:nameIncludes] - all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])} + class ShipsWithMaxPageSize < GraphQL::Schema::Resolver + argument :name_includes, String, required: false + type Ship.connection_type, null: true + + def resolve(name_includes: nil) + all_ships = object.ships.map { |ship_id| StarWars::DATA["Ship"][ship_id] } + if name_includes + all_ships = all_ships.select { |ship| ship.name.include?(name_includes)} end all_ships end - - type Ship.connection_type end class ShipConnectionWithParentType < GraphQL::Types::Relay::BaseConnection edge_type(Ship.edge_type) field :parent_class_name, String, null: false @@ -107,19 +107,37 @@ def parent_class_name object.parent.class.name end end + class ShipsByResolver < GraphQL::Schema::Resolver + type ShipConnectionWithParentType, null: false + + def resolve + object.ships.map { |ship_id| StarWars::DATA["Ship"][ship_id] } + end + end + class Faction < GraphQL::Schema::Object implements GraphQL::Relay::Node.interface - field :id, ID, null: false, resolve: GraphQL::Relay::GlobalIdResolve.new(type: Faction) + field :id, ID, null: false + def id + GraphQL::Relay::GlobalIdResolve.new(type: Faction).call(object, {}, context) + end + field :name, String, null: true - field :ships, ShipConnectionWithParentType, connection: true, max_page_size: 1000, null: true, resolve: ->(obj, args, ctx) { - all_ships = obj.ships.map {|ship_id| StarWars::DATA["Ship"][ship_id] } - if args[:nameIncludes] - case args[:nameIncludes] + field :ships, ShipConnectionWithParentType, connection: true, max_page_size: 1000, null: true do + argument :name_includes, String, required: false + end + + field :shipsByResolver, resolver: ShipsByResolver, connection: true + + def ships(name_includes: nil) + all_ships = object.ships.map {|ship_id| StarWars::DATA["Ship"][ship_id] } + if name_includes + case name_includes when "error" all_ships = GraphQL::ExecutionError.new("error from within connection") when "raisedError" raise GraphQL::ExecutionError.new("error raised from within connection") when "lazyError" @@ -130,33 +148,28 @@ all_ships = nil when "lazyObject" prev_all_ships = all_ships all_ships = LazyWrapper.new { prev_all_ships } else - all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])} + all_ships = all_ships.select { |ship| ship.name.include?(name_includes)} end end all_ships - } do - # You can define arguments here and use them in the connection - argument :nameIncludes, String, required: false end - field :shipsWithMaxPageSize, "Ships with max page size", max_page_size: 2, function: ShipsWithMaxPageSize.new + field :shipsWithMaxPageSize, "Ships with max page size", max_page_size: 2, resolver: ShipsWithMaxPageSize - field :bases, BasesConnectionWithTotalCountType, null: true, connection: true, resolve: ->(obj, args, ctx) { - all_bases = Base.where(id: obj.bases) - if args[:nameIncludes] - all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%") + field :bases, BasesConnectionWithTotalCountType, null: true, connection: true do + argument :name_includes, String, required: false + end + + def bases(name_includes: nil) + all_bases = Base.where(id: object.bases) + if name_includes + all_bases = all_bases.where("name LIKE ?", "%#{name_includes}%") end - if args[:complexOrder] - all_bases = all_bases.order("bases.name DESC") - end all_bases - } do - argument :nameIncludes, String, required: false - argument :complexOrder, Boolean, required: false end field :basesClone, BaseConnection, null: true field :basesByName, BaseConnection, null: true do argument :order, String, default_value: "name", required: false @@ -167,17 +180,25 @@ else @object.bases end end - field :basesWithMaxLimitRelation, BaseConnection, null: true, max_page_size: 2, resolve: Proc.new { Base.all} - field :basesWithMaxLimitArray, BaseConnection, null: true, max_page_size: 2, resolve: Proc.new { Base.all.to_a } - field :basesWithDefaultMaxLimitRelation, BaseConnection, null: true, resolve: Proc.new { Base.all } - field :basesWithDefaultMaxLimitArray, BaseConnection, null: true, resolve: Proc.new { Base.all.to_a } - field :basesWithLargeMaxLimitRelation, BaseConnection, null: true, max_page_size: 1000, resolve: Proc.new { Base.all } - field :basesWithoutNodes, BaseConnectionWithoutNodes, null: true, resolve: Proc.new { Base.all.to_a } + def all_bases + Base.all + end + def all_bases_array + all_bases.to_a + end + + field :basesWithMaxLimitRelation, BaseConnection, null: true, max_page_size: 2, method: :all_bases + field :basesWithMaxLimitArray, BaseConnection, null: true, max_page_size: 2, method: :all_bases_array + field :basesWithDefaultMaxLimitRelation, BaseConnection, null: true, method: :all_bases + field :basesWithDefaultMaxLimitArray, BaseConnection, null: true, method: :all_bases_array + field :basesWithLargeMaxLimitRelation, BaseConnection, null: true, max_page_size: 1000, method: :all_bases + field :basesWithoutNodes, BaseConnectionWithoutNodes, null: true, method: :all_bases_array + field :basesAsSequelDataset, BasesConnectionWithTotalCountType, null: true, connection: true, max_page_size: 1000 do argument :nameIncludes, String, required: false end def bases_as_sequel_dataset(name_includes: nil) @@ -186,11 +207,15 @@ all_bases = all_bases.where(Sequel.like(:name, "%#{name_includes}%")) end all_bases end - field :basesWithCustomEdge, CustomEdgeBaseConnectionType, null: true, connection: true, resolve: ->(o, a, c) { LazyNodesWrapper.new(o.bases) } + field :basesWithCustomEdge, CustomEdgeBaseConnectionType, null: true, connection: true, method: :lazy_bases + + def lazy_bases + LazyNodesWrapper.new(object.bases) + end end class IntroduceShipMutation < GraphQL::Schema::RelayClassicMutation description "Add a ship to this faction" @@ -202,63 +227,36 @@ field :ship_edge, Ship.edge_type, null: true field :faction, Faction, null: true field :aliased_faction, Faction, hash_key: :aliased_faction, null: true def resolve(ship_name: nil, faction_id:) - IntroduceShipFunction.new.call(object, {ship_name: ship_name, faction_id: faction_id}, context) - end - end - - class IntroduceShipFunction < GraphQL::Function - description "Add a ship to this faction" - - argument :shipName, GraphQL::STRING_TYPE - argument :factionId, !GraphQL::ID_TYPE - - type(GraphQL::ObjectType.define do - name "IntroduceShipFunctionPayload" - field :shipEdge, Ship.edge_type, hash_key: :shipEdge - field :faction, Faction, hash_key: :shipEdge - end) - - def call(obj, args, ctx) - # support old and new args - ship_name = args["shipName"] || args[:ship_name] - faction_id = args["factionId"] || args[:faction_id] if ship_name == 'Millennium Falcon' GraphQL::ExecutionError.new("Sorry, Millennium Falcon ship is reserved") elsif ship_name == 'Leviathan' raise GraphQL::ExecutionError.new("🔥") elsif ship_name == "Ebon Hawk" LazyWrapper.new { raise GraphQL::ExecutionError.new("💥")} else ship = DATA.create_ship(ship_name, faction_id) faction = DATA["Faction"][faction_id] connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(faction.ships) - ships_connection = connection_class.new(faction.ships, args) + ships_connection = connection_class.new(faction.ships, {ship_name: ship_name, faction: faction}) ship_edge = GraphQL::Relay::Edge.new(ship, ships_connection) result = { - shipEdge: ship_edge, ship_edge: ship_edge, # support new-style, too faction: faction, aliased_faction: faction, } - if args["shipName"] == "Slave II" + if ship_name == "Slave II" LazyWrapper.new(result) else result end end end end - IntroduceShipFunctionMutation = GraphQL::Relay::Mutation.define do - # Used as the root for derived types: - name "IntroduceShipFunction" - function IntroduceShipFunction.new - end - # GraphQL-Batch knockoff class LazyLoader def self.defer(ctx, model, id) ids = ctx.namespace(:loading)[model] ||= [] ids << id @@ -316,39 +314,80 @@ GraphQL::Relay::BaseConnection.register_connection_implementation(LazyNodesWrapper, LazyNodesRelationConnection) class QueryType < GraphQL::Schema::Object graphql_name "Query" - field :rebels, Faction, null: true, resolve: ->(obj, args, ctx) { StarWars::DATA["Faction"]["1"]} + field :rebels, Faction, null: true + def rebels + StarWars::DATA["Faction"]["1"] + end - field :empire, Faction, null: true, resolve: ->(obj, args, ctx) { StarWars::DATA["Faction"]["2"]} + field :empire, Faction, null: true + def empire + StarWars::DATA["Faction"]["2"] + end - field :largestBase, BaseType, null: true, resolve: ->(obj, args, ctx) { Base.find(3) } + field :largestBase, BaseType, null: true - field :newestBasesGroupedByFaction, BaseConnection, null: true, resolve: ->(obj, args, ctx) { + def largest_base + Base.find(3) + end + + field :newestBasesGroupedByFaction, BaseConnection, null: true + + def newest_bases_grouped_by_faction Base .having('id in (select max(id) from bases group by faction_id)') .group(:id) .order('faction_id desc') - } + end - field :basesWithNullName, BaseConnection, null: false, resolve: ->(obj, args, ctx) { + field :basesWithNullName, BaseConnection, null: false + + def bases_with_null_name [OpenStruct.new(id: nil)] - } + end - field :node, field: GraphQL::Relay::Node.field + if TESTING_INTERPRETER + add_field(GraphQL::Types::Relay::NodeField) + else + field :node, field: GraphQL::Relay::Node.field + end - custom_node_field = GraphQL::Relay::Node.field do - resolve ->(_, _, _) { StarWars::DATA["Faction"]["1"] } + if TESTING_INTERPRETER + field :node_with_custom_resolver, GraphQL::Types::Relay::Node, null: true do + argument :id, ID, required: true + end + def node_with_custom_resolver(id:) + StarWars::DATA["Faction"]["1"] + end + else + custom_node_field = GraphQL::Relay::Node.field do + resolve ->(_, _, _) { StarWars::DATA["Faction"]["1"] } + end + field :nodeWithCustomResolver, field: custom_node_field end - field :nodeWithCustomResolver, field: custom_node_field - field :nodes, field: GraphQL::Relay::Node.plural_field - field :nodesWithCustomResolver, field: GraphQL::Relay::Node.plural_field( - resolve: ->(_, _, _) { [StarWars::DATA["Faction"]["1"], StarWars::DATA["Faction"]["2"]] } - ) + if TESTING_INTERPRETER + add_field(GraphQL::Types::Relay::NodesField) + else + field :nodes, field: GraphQL::Relay::Node.plural_field + end + if TESTING_INTERPRETER + field :nodes_with_custom_resolver, [GraphQL::Types::Relay::Node, null: true], null: true do + argument :ids, [ID], required: true + end + def nodes_with_custom_resolver(ids:) + [StarWars::DATA["Faction"]["1"], StarWars::DATA["Faction"]["2"]] + end + else + field :nodesWithCustomResolver, field: GraphQL::Relay::Node.plural_field( + resolve: ->(_, _, _) { [StarWars::DATA["Faction"]["1"], StarWars::DATA["Faction"]["2"]] } + ) + end + field :batchedBase, BaseType, null: true do argument :id, ID, required: true end def batched_base(id:) @@ -357,11 +396,10 @@ end class MutationType < GraphQL::Schema::Object graphql_name "Mutation" field :introduceShip, mutation: IntroduceShipMutation - field :introduceShipFunction, field: IntroduceShipFunctionMutation.field end class ClassNameRecorder def initialize(context_key) @context_key = context_key @@ -384,9 +422,13 @@ class Schema < GraphQL::Schema query(QueryType) mutation(MutationType) default_max_page_size 3 + + if TESTING_INTERPRETER + use GraphQL::Execution::Interpreter + end def self.resolve_type(type, object, ctx) if object == :test_error :not_a_type elsif object.is_a?(Base)