module BBLib::SimpleInit
Allows any public setter method to be called during initialization using keyword arguments. Add include BBLib::SimpleInit
or prepend BBLib::SimpleInit
to classes to add this behavior.
Constants
- INIT_TYPES
strict - Raise exceptions for unknown named attributes loose - Ignore unknown named attributes collect - Put unknown named attributes into the attribute
configured by collect_attribute
Attributes
_init_type[R]
Public Class Methods
included(base)
click to toggle source
# File lib/bblib/core/mixins/simple_init.rb, line 15 def self.included(base) base.extend ClassMethods base.class_eval do define_method(:initialize) do |*args, &block| send(:simple_setup) if respond_to?(:simple_setup, true) send(:simple_preinit, *args, &block) if respond_to?(:simple_preinit, true) _initialize(*args, &block) send(:simple_init, *args, &block) if respond_to?(:simple_init, true) if block && !_attrs.any? { |k, v| v[:options][:arg_at] == :block } result = instance_eval(&block) simple_init_block_result(result) if respond_to?(:simple_init_block_result, true) end send(:simple_postinit, *args, &block) if respond_to?(:simple_postinit, true) self end end if BBLib.in_opal? base.singleton_class.class_eval do alias __new new def new(*args, &block) named = BBLib.named_args(*args) if init_foundation && named[init_foundation_method] && ((named[init_foundation_method] != self.send(init_foundation_method)) rescue false) klass = [self, descendants].flatten.find do |k| if init_foundation_compare init_foundation_compare.call(k.send(init_foundation_method), named[init_foundation_method]) else k.send(init_foundation_method).to_s == named[init_foundation_method].to_s end end raise ArgumentError, "Unknown #{init_foundation_method} \"#{named[init_foundation_method]}\" for #{self}" unless klass klass == self ? __new(*args, &block) : klass.new(*args, &block) elsif named[init_foundation_method].nil? && init_foundation_default_class != self init_foundation_default_class.new(*args, &block) else __new(*args, &block) end end end end end
Public Instance Methods
new(*args, &block)
click to toggle source
# File lib/bblib/core/mixins/simple_init.rb, line 36 def new(*args, &block) named = BBLib.named_args(*args) if init_foundation && named[init_foundation_method] && ((named[init_foundation_method] != self.send(init_foundation_method)) rescue false) klass = [self, descendants].flatten.find do |k| if init_foundation_compare init_foundation_compare.call(k.send(init_foundation_method), named[init_foundation_method]) else k.send(init_foundation_method).to_s == named[init_foundation_method].to_s end end raise ArgumentError, "Unknown #{init_foundation_method} \"#{named[init_foundation_method]}\" for #{self}" unless klass klass == self ? __new(*args, &block) : klass.new(*args, &block) elsif named[init_foundation_method].nil? && init_foundation_default_class != self init_foundation_default_class.new(*args, &block) else __new(*args, &block) end end
Protected Instance Methods
_collect_attribute(method, value)
click to toggle source
# File lib/bblib/core/mixins/simple_init.rb, line 221 def _collect_attribute(method, value) inst_name = "@#{self.class.collect_method}" hash = instance_variable_get(inst_name) hash = instance_variable_set(inst_name, {}) unless hash.is_a?(Hash) hash[method] = value end
_initialize(*args, &block)
click to toggle source
# File lib/bblib/core/mixins/simple_init.rb, line 181 def _initialize(*args, &block) named = BBLib.named_args(*args) if self.class.respond_to?(:_attrs) set_v_arg = self.class._attrs.map do |method, details| next unless details[:options][:arg_at] && (details[:options][:arg_at].is_a?(Integer) || details[:options][:arg_at] == :block) if details[:options][:arg_at] == :block send("#{method}=", block) if block method else index = details[:options][:arg_at] if args.size > index accept = details[:options][:arg_at_accept] next if args[index].is_a?(Hash) && (accept.nil? || ![accept].flatten.include?(Hash)) if accept.nil? || [accept].flatten.any? { |a| a >= args[index].class } send("#{method}=", args[index]) method end end end end.compact missing = self.class._attrs.map do |method, details| next unless !set_v_arg.include?(method) && details[:options][:required] && !named.include?(method) && !send(method) method end.compact raise ArgumentError, "You are missing the following required #{BBLib.pluralize('argument', missing.size)} for #{self.class}: #{missing.join_terms}" unless missing.empty? end named.each do |method, value| next if method == self.class.init_foundation_method setter = "#{method}=" exists = respond_to?(setter) if !exists && self.class.init_type == :strict raise ArgumentError, "Undefined attribute #{setter} for class #{self.class}." elsif !exists && self.class.init_type == :collect _collect_attribute(method, value) end next unless exists send(setter, value) end end