module GraphQL::Client::Schema::ObjectType
Constants
- FIELDS_CACHE
- METHOD_CACHE
- MODULE_CACHE
- PREDICATE_CACHE
Public Class Methods
define_cached_field(name, ctx)
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 92 def self.define_cached_field(name, ctx) key = name name = -name.to_s method_name = ActiveSupport::Inflector.underscore(name) ctx.send(:define_method, method_name, &METHOD_CACHE[key]) ctx.send(:define_method, "#{method_name}?", &PREDICATE_CACHE[name]) end
new(type, fields = {})
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 12 def self.new(type, fields = {}) Class.new(ObjectClass) do extend BaseType extend ObjectType define_singleton_method(:type) { type } define_singleton_method(:fields) { fields } end end
Public Instance Methods
cast(value, errors)
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 116 def cast(value, errors) case value when Hash new(value, errors) when NilClass nil else raise InvariantError, "expected value to be a Hash, but was #{value.class}" end end
define_class(definition, ast_nodes)
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 22 def define_class(definition, ast_nodes) # First, gather all the ast nodes representing a certain selection, by name. # We gather AST nodes into arrays so that multiple selections can be grouped, for example: # # { # f1 { a b } # f1 { b c } # } # # should be treated like `f1 { a b c }` field_nodes = {} ast_nodes.each do |ast_node| ast_node.selections.each do |selected_ast_node| gather_selections(field_nodes, definition, selected_ast_node) end end # After gathering all the nodes by name, prepare to create methods and classes for them. field_classes = {} field_nodes.each do |result_name, field_ast_nodes| # `result_name` might be an alias, so make sure to get the proper name field_name = field_ast_nodes.first.name field_definition = definition.client.schema.get_field(type.graphql_name, field_name) field_return_type = field_definition.type field_classes[result_name.to_sym] = schema_module.define_class(definition, field_ast_nodes, field_return_type) end klass = Class.new(self) klass.define_fields(field_classes) klass.instance_variable_set(:@source_definition, definition) klass.instance_variable_set(:@_spreads, definition.indexes[:spreads][ast_nodes.first]) if definition.client.enforce_collocated_callers keys = field_classes.keys.map { |key| ActiveSupport::Inflector.underscore(key) } Client.enforce_collocated_callers(klass, keys, definition.source_location[0]) end klass end
define_field(name, type)
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 101 def define_field(name, type) name = name.to_s method_name = ActiveSupport::Inflector.underscore(name) define_method(method_name) do @casted_data.fetch(name) do @casted_data[name] = type.cast(@data[name], @errors.filter_by_path(name)) end end define_method("#{method_name}?") do @data[name] ? true : false end end
define_fields(fields)
click to toggle source
# File lib/graphql/client/schema/object_type.rb, line 86 def define_fields(fields) const_set :FIELDS, FIELDS_CACHE[fields] mod = MODULE_CACHE[fields.keys.sort] include mod end
Private Instance Methods
gather_selections(fields, definition, selected_ast_node)
click to toggle source
Given an AST selection on this object, gather it into `fields` if it applies. If it's a fragment, continue recursively checking the selections on the fragment.
# File lib/graphql/client/schema/object_type.rb, line 131 def gather_selections(fields, definition, selected_ast_node) case selected_ast_node when GraphQL::Language::Nodes::InlineFragment continue_selection = if selected_ast_node.type.nil? true else schema = definition.client.schema type_condition = definition.client.get_type(selected_ast_node.type.name) applicable_types = schema.possible_types(type_condition) # continue if this object type is one of the types matching the fragment condition applicable_types.include?(type) end if continue_selection selected_ast_node.selections.each do |next_selected_ast_node| gather_selections(fields, definition, next_selected_ast_node) end end when GraphQL::Language::Nodes::FragmentSpread fragment_definition = definition.document.definitions.find do |defn| defn.is_a?(GraphQL::Language::Nodes::FragmentDefinition) && defn.name == selected_ast_node.name end schema = definition.client.schema type_condition = definition.client.get_type(fragment_definition.type.name) applicable_types = schema.possible_types(type_condition) # continue if this object type is one of the types matching the fragment condition continue_selection = applicable_types.include?(type) if continue_selection fragment_definition.selections.each do |next_selected_ast_node| gather_selections(fields, definition, next_selected_ast_node) end end when GraphQL::Language::Nodes::Field operation_definition_for_field = definition.indexes[:definitions][selected_ast_node] # Ignore fields defined in other documents. if definition.source_document.definitions.include?(operation_definition_for_field) field_method_name = selected_ast_node.alias || selected_ast_node.name ast_nodes = fields[field_method_name] ||= [] ast_nodes << selected_ast_node end else raise "Unexpected selection node: #{selected_ast_node}" end end