module BuilderPattern
BuilderPattern
module
Public Class Methods
attr_mandatory(*fields)
click to toggle source
# File lib/builder_pattern.rb, line 10 def self.attr_mandatory(*fields) @__attr_mandatory ||= [] @__attr_mandatory |= fields.map { |field| "@#{field}".to_sym } end
attr_optional(*fields)
click to toggle source
# File lib/builder_pattern.rb, line 15 def self.attr_optional(*fields) @__attr_optional ||= [] @__attr_optional |= fields.map { |field| "@#{field}".to_sym } end
build(&block)
click to toggle source
# File lib/builder_pattern.rb, line 20 def self.build(&block) new.build(&block) end
included(klass)
click to toggle source
rubocop:disable Metrics/MethodLength because of class_eval
# File lib/builder_pattern.rb, line 6 def self.included(klass) klass.class_eval do private_class_method :new def self.attr_mandatory(*fields) @__attr_mandatory ||= [] @__attr_mandatory |= fields.map { |field| "@#{field}".to_sym } end def self.attr_optional(*fields) @__attr_optional ||= [] @__attr_optional |= fields.map { |field| "@#{field}".to_sym } end def self.build(&block) new.build(&block) end end end
Public Instance Methods
build() { |collector| ... }
click to toggle source
rubocop:disable Metrics/MethodLength desired single method, readable enough rubocop:disable Metrics/AbcSize desired single method, readable enough
# File lib/builder_pattern.rb, line 29 def build collector = OpenStruct.new yield collector mandatory = self.class.ancestors.map do |level| level.instance_variable_get(:@__attr_mandatory) end .compact.flatten.uniq allowed = self.class.ancestors.map do |level| level.instance_variable_get(:@__attr_optional) end .compact.flatten | mandatory # Migrate the state to instance variables collector.each_pair do |key, val| key = "@#{key}".to_sym unless allowed.include?(key) raise ArgumentError, "Unknown field #{key} used in build" end instance_variable_set(key, val) end fields = mandatory - instance_variables return self if fields.empty? raise ArgumentError, "Mandatory fields #{fields.join(', ')} not set" end