module ORMivore::Entity::ClassMethods
Constants
- ALLOWED_ATTRIBUTE_TYPES
Attributes
attributes_declaration[R]
optional_attributes_list[R]
Public Instance Methods
attributes_list()
click to toggle source
# File lib/ormivore/entity.rb, line 10 def attributes_list attributes_declaration.keys end
coerce(attrs)
click to toggle source
# File lib/ormivore/entity.rb, line 55 def coerce(attrs) attrs.each do |name, type| attr_value = attrs[name] declared_type = attributes_declaration[name] if declared_type && !attr_value.is_a?(declared_type) attrs[name] = Kernel.public_send(declared_type.name.to_sym, attr_value) end end rescue ArgumentError => e raise ORMivore::BadArgumentError.new(e) end
construct(attrs, id)
click to toggle source
# File lib/ormivore/entity.rb, line 14 def construct(attrs, id) id = coerce_id(id) coerced_attrs = attrs.symbolize_keys.tap { |h| coerce(h) }.freeze base_attributes = coerced_attrs dirty_attributes = {}.freeze validate_presence_of_proper_attributes(base_attributes, dirty_attributes) obj = allocate obj.instance_variable_set(:@id, id) obj.instance_variable_set(:@base_attributes, base_attributes) obj.instance_variable_set(:@dirty_attributes, dirty_attributes) # TODO how to do custom validation? # validate obj end
validate_presence_of_proper_attributes(base, dirty)
click to toggle source
# File lib/ormivore/entity.rb, line 36 def validate_presence_of_proper_attributes(base, dirty) # doing complicated way first because it is much more memory efficient # but it does not allow for good error messages, so if something is # wrong, need to proceed to inefficient validation that produces nice # messages missing = 0 known_counts = attributes_list.each_with_object([0, 0]) { |attr, acc| acc[0] += 1 if base[attr] acc[1] += 1 if dirty[attr] missing +=1 unless optional_attributes_list.include?(attr) || base[attr] || dirty[attr] } if missing > 0 || [base.length, dirty.length] != known_counts expensive_validate_presence_of_proper_attributes( base.merge(dirty) ) end end
Private Instance Methods
attributes(declaration)
click to toggle source
# File lib/ormivore/entity.rb, line 69 def attributes(declaration) @attributes_declaration = declaration.symbolize_keys.freeze validate_attributes_declaration # @attributes_list = methods.map(&:to_sym) @optional_attributes_list ||= [] attributes_list.map(&:to_s).each do |attr| module_eval(<<-EOS) def #{attr} @dirty_attributes[:#{attr}] || @base_attributes[:#{attr}] end EOS self::Builder.module_eval(<<-EOS) def #{attr} attributes[:#{attr}] end def #{attr}=(value) attributes[:#{attr}] = value end EOS end end
coerce_id(value)
click to toggle source
# File lib/ormivore/entity.rb, line 118 def coerce_id(value) value ? Integer(value) : nil rescue ArgumentError raise ORMivore::BadArgumentError, "Not a valid id: #{value.inspect}" end
expensive_validate_presence_of_proper_attributes(attrs)
click to toggle source
TODO figure out how to differenciate private methods that are part of ORMivore
API from those that are NOT
# File lib/ormivore/entity.rb, line 100 def expensive_validate_presence_of_proper_attributes(attrs) attributes_list.each do |attr| unless attrs.delete(attr) || optional_attributes_list.include?(attr) raise BadAttributesError, "Missing attribute '#{attr}'" end end raise BadAttributesError, "Unknown attributes #{attrs.inspect}" unless attrs.empty? end
optional(*methods)
click to toggle source
# File lib/ormivore/entity.rb, line 92 def optional(*methods) @optional_attributes_list = methods.map(&:to_sym) end
validate_attributes_declaration()
click to toggle source
# File lib/ormivore/entity.rb, line 110 def validate_attributes_declaration attributes_declaration.each do |name, type| unless ALLOWED_ATTRIBUTE_TYPES.include?(type) raise ORMivore::BadArgumentError, "Invalid attribute type #{type.inspect}" end end end