module Praxis::Mapper::Resources::TypedMethods
Constants
- CREATE_LOADER_METHOD
Attributes
signatures[R]
Public Class Methods
_finalize!()
click to toggle source
Calls superclass method
# File lib/praxis/mapper/resources/typed_methods.rb, line 25 def _finalize! if @signatures # Build the around callbacks for coercing the params for the methods with types defined # Also, this needs to be before, so that we hit the coercion code before any other around callback const_set(:MethodSignatures, Module.new) @signatures.each do |method, type| # Also add a constant pointing to the signature type inside Signatures (and substitute ! for Bang, as that's not allowed in a constant) # For class Methods, also substitute .self for Self # This helps with debugging, as we won't get anonymous struct classes, but we'll see these better names cleaned_name = method.to_s.gsub(/!/, '_bang').to_s.gsub(/^self./, 'self_') self::MethodSignatures.const_set(cleaned_name.camelize.to_sym, type) coerce_params_for method, type end end super end
coerce_params_for(method, type)
click to toggle source
Sets up a specific around callback to a given method, where it’d pass the loaded/coerced type from the input
# File lib/praxis/mapper/resources/typed_methods.rb, line 68 def coerce_params_for(method, type) raise "Argument type for #{method} could not be found. Did you define a `signature` stanza for it?" unless type if method.start_with?('self.') simple_name = method.to_s.gsub(/^self./, '').to_sym # Look for a Class method raise "Error building typed method signature: Method #{method} is not defined in class #{name}" unless methods.include?(simple_name) coerce_params_for_class(method(simple_name), type) else # Look for an instance method raise "Error building typed method signature: Method #{method} is not defined in class #{name}" unless method_defined?(method) coerce_params_for_instance(instance_method(method), type) end end
coerce_params_for_class(method, type)
click to toggle source
# File lib/praxis/mapper/resources/typed_methods.rb, line 97 def coerce_params_for_class(method, type) around_method_name = "_coerce_params_for_class_#{method.name}" # Define an instance method in the eigenclass singleton_class.instance_exec around_method_name: around_method_name, orig_method: method, type: type, ctx: [to_s, method.name].freeze, &CREATE_LOADER_METHOD # Set an around callback to call the defined method above (the callbacks need self. for class interceptors) class_method_name = "self.#{method.name}" around class_method_name.to_sym, around_method_name end
coerce_params_for_instance(method, type)
click to toggle source
# File lib/praxis/mapper/resources/typed_methods.rb, line 85 def coerce_params_for_instance(method, type) around_method_name = "_coerce_params_for_#{method.name}" instance_exec around_method_name: around_method_name, orig_method: method, type: type, ctx: [to_s, method.name].freeze, &CREATE_LOADER_METHOD # Set an around callback to call the defined method above around method.name, around_method_name end
signature(method_name, same_as_type = nil, **opts, &block)
click to toggle source
It can take options to be passed to the attribute’s block of the constructed struct It can take an already existing struct instead of a block/options
# File lib/praxis/mapper/resources/typed_methods.rb, line 45 def signature(method_name, same_as_type = nil, **opts, &block) method = method_name.to_sym @signatures ||= {} raise "signature definition for #{method_name}: need to pass either an existing type or a block, not both" if block_given? && same_as_type if block_given? type = Class.new(Attributor::Struct) do attributes(**opts) do instance_eval(&block) end end @signatures[method] = type elsif same_as_type raise "Options for signature definition for #{method_name} are not supported when passing an already existing type" unless opts.empty? @signatures[method] = same_as_type else @signatures[method] end end