class KeywordBuilder
Abstract builder interface for types with keyword argument constructors.
Constants
- VERSION
Attributes
attrs[R]
Public Class Methods
build!(**initial_attrs, &block)
click to toggle source
# File lib/keyword_builder.rb, line 26 def build!(**initial_attrs, &block) builder = self.new(initial_attrs) builder.instance_eval(&block) if block_given? clazz.public_send(constructor, **builder.attrs) end
create(clazz, constructor: :new)
click to toggle source
# File lib/keyword_builder.rb, line 8 def create(clazz, constructor: :new) keywords, wildcard = parse_constructor_parameters(clazz, constructor) Class.new(self) do define_singleton_method(:clazz) { clazz } define_singleton_method(:constructor) { constructor } define_singleton_method(:keywords) { keywords } define_singleton_method(:wildcard?) { wildcard } keywords.each do |keyword| define_method(keyword) { |*args, &block| _set_attribute(keyword, *args, &block) } end end end
new(initial_attrs)
click to toggle source
# File lib/keyword_builder.rb, line 64 def initialize(initial_attrs) @attrs = initial_attrs.dup end
valid_keyword?(param)
click to toggle source
# File lib/keyword_builder.rb, line 22 def valid_keyword?(param) wildcard? || keywords.include?(param) end
Private Class Methods
parse_constructor_parameters(clazz, constructor)
click to toggle source
# File lib/keyword_builder.rb, line 34 def parse_constructor_parameters(clazz, constructor) parameters = if constructor == :new clazz.instance_method(:initialize).parameters else clazz.method(constructor).parameters end keywords = Set.new wildcard = false parameters.each do |type, name| case type when :opt, :rest next when :key, :keyreq keywords << name when :keyrest wildcard = true else raise ArgumentError.new("Invalid builder method, contains required non-keyword parameter #{name}") end end [keywords.freeze, wildcard] end
Public Instance Methods
_set_attribute(attr, *args, &block)
click to toggle source
# File lib/keyword_builder.rb, line 68 def _set_attribute(attr, *args, &block) if attrs.has_key?(attr) raise BuilderError.new("Invalid builder state: #{attr} already provided") end value = if block_given? raise ArgumentError.new('Cannot provide both immediate and block value') unless args.blank? block elsif args.size == 1 args[0] else raise ArgumentError.new('Wrong number of arguments: expected 1 or block') end attrs[attr] = value end
method_missing(attr, *args, &block)
click to toggle source
Calls superclass method
# File lib/keyword_builder.rb, line 87 def method_missing(attr, *args, &block) if self.class.wildcard? _set_attribute(attr, *args, &block) else super end end
respond_to_missing?(attr, _include_all = false)
click to toggle source
Calls superclass method
# File lib/keyword_builder.rb, line 95 def respond_to_missing?(attr, _include_all = false) self.class.wildcard? || super end