lib/key_vortex/limitation.rb in key-vortex-0.2.5 vs lib/key_vortex/limitation.rb in key-vortex-1.0.0

- old
+ new

@@ -1,16 +1,39 @@ # frozen_string_literal: true class KeyVortex + # Represents a collection of {KeyVortex::Constraint constraints} + # which apply to a given class. While these can be constructed + # directly, the intended mechanism for applying these to a record is + # through {KeyVortex::Record.field}. + # + # Two independent concepts which commonly use the same terminology + # exist in this project. Consider the term "allows", is that + # referring to what values are allowed or what constraints are + # allowed? To help navigate these two concepts, the following + # terminology convention is used throughout this codebase: + # * Encompass/Within: Used when comparing limitations and constraints to each other + # * Accepts/Rejects: Used when determining if a value is valid for constraints class Limitation - attr_reader :type, :constraints + # @return [Class] The class these constraints applies to. + attr_reader :type + # @return [Array] The constraints which apply to this class. + attr_reader :constraints + + # @param type [Class] + # @param constraints [KeyValue::Constraint] def initialize(type, *constraints) @type = type - @constraints = constraints + @constraints = [] + add_constraint(*constraints) end + # Add constraints to this limitation. It is also possible to do + # this through the constructor, but it is sometimes easier to do + # it one at a time. + # @param constraints [KeyVortex::Constraint::Base] def add_constraint(*constraints) constraints.each do |constraint| unless constraint.is_a?(KeyVortex::Constraint::Base) raise KeyVortex::Error, "Not a constraint: #{constraint.class}" @@ -18,28 +41,46 @@ end @constraints += constraints end - def encompasses?(limitation) - @constraints.all? do |constraint| - limitation.encompasses_constraint?(constraint) + # Determine if any of the constraints in the provided limitation + # exceed this limitation's constraints. + # @param limitation [KeyVortex::Limitation] + # @return [Boolean] + def within?(limitation) + limitation.constraints.all? do |constraint| + within_constraint?(constraint) end end - def encompasses_constraint?(constraint) - applicable_constraints(constraint).any? do |con| - con.within?(constraint) - end + # Determine if a given value meets all of the constraints. + # @param value [type] + # @return [Boolean] + def accepts?(value) + value.is_a?(type) && @constraints.all? { |constraint| constraint.accepts?(value) } end - def within?(limitation) - limitation.constraints.all? do |constraint| - within_constraint?(constraint) - end + # Ensure that JSON additions for {type} are loaded in case the + # record needs to be serialized. + def enable_json_additions + path = JSON_ADDITIONS[@type.class.name] + require path if path end + # Return information about this limitation. The information will + # be formatted as follows: + # Limitation: String + # minimum: 10 + # maximum: 100 + # @return [String] + def to_s + "Limitation: #{@type}\n\t#{@constraints.join('\n\t')}" + end + + private + def within_constraint?(constraint) applicable_constraints(constraint).any? do |con| con.within?(constraint) end end @@ -48,14 +89,10 @@ @constraints.select do |con| con.applies_to?(constraint) end end - def accepts?(value) - value.is_a?(type) && @constraints.all? { |constraint| constraint.accepts?(value) } - end - JSON_ADDITIONS = { BigDecimal: "json/add/bigdecimal", Complex: "json/add/complex", Date: "json/add/date", DateTime: "json/add/date_time", @@ -67,16 +104,7 @@ Set: "json/add/set", Struct: "json/add/struct", Symbol: "json/add/symbol", Time: "json/add/time" }.freeze - - def enable_json_additions - path = JSON_ADDITIONS[@type.class.name] - require path if path - end - - def to_s - "Limitation: #{@type}\n\t#{@constraints.join('\n\t')}" - end end end