Class: GraphQL::Node
- Inherits:
-
Object
- Object
- GraphQL::Node
- Defined in:
- lib/graphql/node.rb
Overview
Node is the base class for your GraphQL nodes. It’s essentially a delegator that only delegates methods you whitelist with Node.field. To use it:
-
Extend ‘GraphQL::Node`
-
Declare what this node will wrap with Node.exposes
-
Declare fields with Node.field
-
Declare calls with Node.call
Direct Known Subclasses
Connection, Introspection::CallType, Introspection::FieldType, Introspection::RootCallArgumentNode, Introspection::RootCallType, Introspection::SchemaType, Introspection::TypeType, Types::ObjectType
Instance Attribute Summary collapse
-
#original_target ⇒ Object
readonly
The object wrapped by this ‘Node`, before calls are applied.
-
#query ⇒ Object
readonly
The query to which this ‘Node` belongs.
-
#syntax_fields ⇒ Object
readonly
Fields parsed from the query string.
-
#target ⇒ Object
readonly
The object wrapped by this ‘Node`, after calls are applied.
Class Method Summary collapse
-
.all_fields ⇒ Object
All accessible fields on this node (including those defined in parent classes).
-
.call(name, lambda) ⇒ Object
Define a call that can be made on nodes of this type.
- .calls ⇒ Object
-
.cursor(field_name) ⇒ Object
Declares what field will be used as the cursor for this node.
- .default_schema_name ⇒ Object
-
.desc(describe) ⇒ Object
Provide a description for this node which will be accessible from SCHEMA.
-
.description ⇒ Object
The description of this node.
- .exposes(*exposes_class_names) ⇒ Object
-
.exposes_class_names ⇒ Object
The names of the classes wrapped by this node.
-
.field ⇒ GraphQL::FieldDefiner
Definer.
- .own_calls ⇒ Object
-
.own_fields ⇒ Object
Fields defined by this class, but not its parents.
-
.remove_field(field_name) ⇒ Object
Un-define field with name ‘field_name`.
-
.respond_to_field?(field_name) ⇒ Boolean
Can the node handle a field with this name?.
-
.schema_name ⇒ Object
Returns the name of this node used by SCHEMA.
-
.type(type_name) ⇒ Object
Declares an alternative name to use in SCHEMA.
Instance Method Summary collapse
- #__type__ ⇒ Object
- #apply_calls(value) ⇒ Object
-
#as_result ⇒ Object
Looks up #syntax_fields against this node and returns the results.
-
#context ⇒ Object
The object passed to Query#initialize as ‘context`.
- #finished_value(raw_value) ⇒ Object
-
#initialize(target = nil, fields:, query:, calls: []) ⇒ Node
constructor
A new instance of Node.
-
#method_missing(method_name, *args, &block) ⇒ Object
If the target responds to ‘method_name`, send it to target.
Constructor Details
#initialize(target = nil, fields:, query:, calls: []) ⇒ Node
Returns a new instance of Node.
45 46 47 48 49 50 51 |
# File 'lib/graphql/node.rb', line 45 def initialize(target=nil, fields:, query:, calls: []) @query = query @calls = calls @syntax_fields = fields @original_target = target @target = apply_calls(target) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
If the target responds to ‘method_name`, send it to target.
54 55 56 57 58 59 60 |
# File 'lib/graphql/node.rb', line 54 def method_missing(method_name, *args, &block) if target.respond_to?(method_name) target.public_send(method_name, *args, &block) else super end end |
Instance Attribute Details
#original_target ⇒ Object (readonly)
The object wrapped by this ‘Node`, before calls are applied
37 38 39 |
# File 'lib/graphql/node.rb', line 37 def original_target @original_target end |
#query ⇒ Object (readonly)
The query to which this ‘Node` belongs. Used for accessing its Query#context.
43 44 45 |
# File 'lib/graphql/node.rb', line 43 def query @query end |
#syntax_fields ⇒ Object (readonly)
Fields parsed from the query string
41 42 43 |
# File 'lib/graphql/node.rb', line 41 def syntax_fields @syntax_fields end |
#target ⇒ Object (readonly)
The object wrapped by this ‘Node`, after calls are applied
39 40 41 |
# File 'lib/graphql/node.rb', line 39 def target @target end |
Class Method Details
.all_fields ⇒ Object
All accessible fields on this node (including those defined in parent classes)
165 166 167 168 169 |
# File 'lib/graphql/node.rb', line 165 def all_fields superclass.all_fields.merge(own_fields) rescue NoMethodError own_fields end |
.call(name, lambda) ⇒ Object
Define a call that can be made on nodes of this type. The ‘lambda` receives arguments:
-
1: ‘previous_value` – the value of this node
-
*: arguments passed in the query (as strings)
223 224 225 |
# File 'lib/graphql/node.rb', line 223 def call(name, lambda) own_calls[name.to_s] = GraphQL::Call.new(name: name.to_s, lambda: lambda) end |
.calls ⇒ Object
203 204 205 206 207 |
# File 'lib/graphql/node.rb', line 203 def calls superclass.calls.merge(own_calls) rescue NoMethodError {} end |
.cursor(field_name) ⇒ Object
Declares what field will be used as the cursor for this node.
157 158 159 160 161 162 |
# File 'lib/graphql/node.rb', line 157 def cursor(field_name) define_method "cursor" do field_mapping = self.class.all_fields[field_name.to_s] public_send(field_mapping.name).to_s end end |
.default_schema_name ⇒ Object
151 152 153 |
# File 'lib/graphql/node.rb', line 151 def default_schema_name name.split("::").last.sub(/(Node|Type)$/, '').underscore end |
.desc(describe) ⇒ Object
Provide a description for this node which will be accessible from SCHEMA
130 131 132 |
# File 'lib/graphql/node.rb', line 130 def desc(describe) @description = describe end |
.description ⇒ Object
The description of this node
135 136 137 |
# File 'lib/graphql/node.rb', line 135 def description @description || raise("#{name}.description isn't defined") end |
.exposes(*exposes_class_names) ⇒ Object
118 119 120 121 |
# File 'lib/graphql/node.rb', line 118 def exposes(*exposes_class_names) @exposes_class_names = exposes_class_names GraphQL::SCHEMA.add_type(self) end |
.exposes_class_names ⇒ Object
The names of the classes wrapped by this node
124 125 126 |
# File 'lib/graphql/node.rb', line 124 def exposes_class_names @exposes_class_names || [] end |
.field ⇒ GraphQL::FieldDefiner
Returns definer.
177 178 179 |
# File 'lib/graphql/node.rb', line 177 def field @field_definer ||= GraphQL::FieldDefiner.new(self) end |
.own_calls ⇒ Object
227 228 229 |
# File 'lib/graphql/node.rb', line 227 def own_calls @own_calls ||= {} end |
.own_fields ⇒ Object
Fields defined by this class, but not its parents
172 173 174 |
# File 'lib/graphql/node.rb', line 172 def own_fields @own_fields ||= {} end |
.remove_field(field_name) ⇒ Object
Un-define field with name ‘field_name`
183 184 185 |
# File 'lib/graphql/node.rb', line 183 def remove_field(field_name) own_fields.delete(field_name.to_s) end |
.respond_to_field?(field_name) ⇒ Boolean
Can the node handle a field with this name?
188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/graphql/node.rb', line 188 def respond_to_field?(field_name) if all_fields[field_name.to_s].blank? false elsif method_defined?(field_name) true elsif exposes_class_names.any? do |exposes_class_name| exposes_class = Object.const_get(exposes_class_name) exposes_class.method_defined?(field_name) || exposes_class.respond_to?(field_name) end true else false end end |
.schema_name ⇒ Object
Returns the name of this node used by SCHEMA
147 148 149 |
# File 'lib/graphql/node.rb', line 147 def schema_name @type_name || default_schema_name end |
Instance Method Details
#__type__ ⇒ Object
94 95 96 |
# File 'lib/graphql/node.rb', line 94 def __type__ self.class end |
#apply_calls(value) ⇒ Object
98 99 100 |
# File 'lib/graphql/node.rb', line 98 def apply_calls(value) finished_value(value) end |
#as_result ⇒ Object
Looks up #syntax_fields against this node and returns the results
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/graphql/node.rb', line 63 def as_result @as_result ||= begin json = {} syntax_fields.each do |syntax_field| key_name = syntax_field.alias_name || syntax_field.identifier if key_name == 'node' clone_node = self.class.new(target, fields: syntax_field.fields, query: query, calls: syntax_field.calls) json[key_name] = clone_node.as_result elsif key_name == 'cursor' json[key_name] = cursor elsif key_name[0] == "$" fragment = query.fragments[key_name] # execute the fragment and merge it into this result clone_node = self.class.new(target, fields: fragment.fields, query: query, calls: @calls) json.merge!(clone_node.as_result) else field = get_field(syntax_field) new_target = public_send(field.name) new_node = field.type_class.new(new_target, fields: syntax_field.fields, query: query, calls: syntax_field.calls) json[key_name] = new_node.as_result end end json end end |
#context ⇒ Object
The object passed to Query#initialize as ‘context`.
90 91 92 |
# File 'lib/graphql/node.rb', line 90 def context query.context end |
#finished_value(raw_value) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/graphql/node.rb', line 102 def finished_value(raw_value) @finished_value ||= begin val = raw_value @calls.each do |call| registered_call = self.class.calls[call.identifier] if registered_call.nil? raise "Call not found: #{self.class.name}##{call.identifier}" end val = registered_call.lambda.call(val, *call.arguments) end val end end |