module GraphQL::Define::InstanceDefinable
@api deprecated
Public Class Methods
# File lib/graphql/define/instance_definable.rb, line 23 def self.included(base) base.extend(ClassMethods) base.ensure_defined(:metadata) end
Public Instance Methods
@api deprecated
# File lib/graphql/define/instance_definable.rb, line 43 def define(**kwargs, &block) deprecated_define(**kwargs, &block) end
@api deprecated
# File lib/graphql/define/instance_definable.rb, line 34 def deprecated_define(**kwargs, &block) # make sure the previous definition_proc was executed: ensure_defined stash_dependent_methods @pending_definition = Definition.new(kwargs, block) nil end
# File lib/graphql/define/instance_definable.rb, line 55 def initialize_copy(other) super @metadata = other.metadata.dup end
@api deprecated
# File lib/graphql/define/instance_definable.rb, line 29 def metadata @metadata ||= {} end
@api deprecated
# File lib/graphql/define/instance_definable.rb, line 48 def redefine(**kwargs, &block) ensure_defined new_inst = self.dup new_inst.deprecated_define(**kwargs, &block) new_inst end
Private Instance Methods
Run the definition block if it hasn't been run yet. This can only be run once: the block is deleted after it's used. You have to call this before using any value which could come from the definition block. @return [void]
# File lib/graphql/define/instance_definable.rb, line 67 def ensure_defined if @pending_definition defn = @pending_definition @pending_definition = nil revive_dependent_methods begin defn_proxy = DefinedObjectProxy.new(self) # Apply definition from `define(...)` kwargs defn.define_keywords.each do |keyword, value| # Don't splat string hashes, which blows up on Rubies before 2.7 if value.is_a?(Hash) && !value.empty? && value.each_key.all? { |k| k.is_a?(Symbol) } defn_proxy.public_send(keyword, **value) else defn_proxy.public_send(keyword, value) end end # and/or apply definition from `define { ... }` block if defn.define_proc defn_proxy.instance_eval(&defn.define_proc) end rescue StandardError # The definition block failed to run, so make this object pending again: stash_dependent_methods @pending_definition = defn raise end end nil end
Take the pending methods and put them back on this object's singleton class. This reverts the process done by {#stash_dependent_methods} @return [void]
# File lib/graphql/define/instance_definable.rb, line 102 def revive_dependent_methods pending_methods = @pending_methods self.singleton_class.class_eval { pending_methods.each do |method| undef_method(method.name) if method_defined?(method.name) define_method(method.name, method) end } @pending_methods = nil end
Find the method names which were declared as definition-dependent, then grab the method definitions off of this object's class and store them for later.
Then make a dummy method for each of those method names which:
-
Triggers the pending definition, if there is one
-
Calls the same method again.
It's assumed that {#ensure_defined} will put the original method definitions back in place with {#revive_dependent_methods}. @return [void]
# File lib/graphql/define/instance_definable.rb, line 125 def stash_dependent_methods method_names = self.class.ensure_defined_method_names @pending_methods = method_names.map { |n| self.class.instance_method(n) } self.singleton_class.class_eval do method_names.each do |method_name| undef_method(method_name) if method_defined?(method_name) define_method(method_name) { |*args, &block| ensure_defined self.send(method_name, *args, &block) } end end end