Module: Constrain
- Defined in:
- lib/constrain.rb,
lib/constrain/version.rb
Defined Under Namespace
Modules: ClassMethods Classes: MatchError
Constant Summary collapse
- VERSION =
"0.10.0"
Class Method Summary collapse
-
.constrain(value, *exprs, **opts) ⇒ Object
:call-seq: constrain(value, *class-expressions, unwind: 0) constrain(value, *values, unwind: 0).
-
.constrain?(value, *exprs, **opts) ⇒ Boolean
Like #constrain but returns true/false to indicate the result instead of raising an exception.
-
.do_constrain(value, *exprs, unwind: 0, message: nil) ⇒ Object
:call-seq: do_constrain(value, *exprs, unwind: 0, message: nil, not: nil).
- .do_constrain? ⇒ Boolean
- .do_constrain_value?(value, expr) ⇒ Boolean
-
.fmt_expr(expr) ⇒ Object
Render a class expression as a String.
-
.fmt_exprs(exprs) ⇒ Object
Render a class expression as a String.
- .included(base) ⇒ Object
Instance Method Summary collapse
-
#constrain ⇒ Object
See Constrain.constrain.
-
#constrain? ⇒ Boolean
See Constrain.constrain?.
Class Method Details
.constrain(value, *exprs, **opts) ⇒ Object
:call-seq:
constrain(value, *class-expressions, unwind: 0)
constrain(value, *values, unwind: 0)
Check that value matches one of the class expressions. Raises a ArgumentError if the expression is invalid and a Constrain::MatchError if the value doesn’t match. The exception’s backtrace skips :unwind number of entries
27 28 29 |
# File 'lib/constrain.rb', line 27 def self.constrain(value, *exprs, **opts) do_constrain(value, *exprs, **opts) end |
.constrain?(value, *exprs, **opts) ⇒ Boolean
Like #constrain but returns true/false to indicate the result instead of raising an exception
36 37 38 |
# File 'lib/constrain.rb', line 36 def self.constrain?(value, *exprs, **opts) do_constrain?(value, *exprs, **opts) end |
.do_constrain(value, *exprs, unwind: 0, message: nil) ⇒ Object
:call-seq:
do_constrain(value, *exprs, unwind: 0, message: nil, not: nil)
unwind is automatically incremented by one because ::do_constrain is always called from one of the other constrain methods
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/constrain.rb', line 57 def self.do_constrain(value, *exprs, unwind: 0, message: nil) unwind += 1 begin if exprs.empty? value or raise MatchError.new(value, [], message: , unwind: unwind) else exprs.any? { |expr| Constrain.do_constrain_value?(value, expr) } or raise MatchError.new(value, exprs, message: , unwind: unwind) end rescue ArgumentError, Constrain::MatchError => ex ex.set_backtrace(caller[1 + unwind..-1]) raise end value end |
.do_constrain? ⇒ Boolean
73 74 75 76 77 78 79 80 |
# File 'lib/constrain.rb', line 73 def self.do_constrain?(...) begin do_constrain(...) rescue MatchError return false end true end |
.do_constrain_value?(value, expr) ⇒ Boolean
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/constrain.rb', line 82 def self.do_constrain_value?(value, expr) case expr when Class, Module expr === value when Array !expr.empty? or raise ArgumentError, "Empty array in constraint" value.is_a?(Array) && value.all? { |elem| expr.any? { |e| Constrain.constrain?(elem, e) } } when Hash value.is_a?(Hash) && value.all? { |key, value| expr.any? { |key_expr, value_expr| [[key, key_expr], [value, value_expr]].all? { |value, expr| if expr.is_a?(Array) && (expr.size > 1 || expr.first.is_a?(Array)) expr.any? { |e| Constrain.do_constrain?(value, e) } else Constrain.constrain?(value, expr) end } } } when Proc expr.call(value) else expr === value end end |
.fmt_expr(expr) ⇒ Object
Render a class expression as a String. Same as expr.inspect
except that Proc objects are rendered as “Proc@<sourcefile>>:<linenumber>”
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/constrain.rb', line 117 def self.fmt_expr(expr) case expr when Class, Module; expr.to_s when Regexp; expr.to_s when Array; "[" + expr.map { |expr| fmt_expr(expr) }.join(", ") + "]" when Hash; "{" + expr.map { |k,v| "#{fmt_expr(k)} => #{fmt_expr(v)}" }.join(", ") + "}" when Proc; "Proc@#{expr.source_location.first}:#{expr.source_location.last}" else expr.inspect end end |
.fmt_exprs(exprs) ⇒ Object
Render a class expression as a String. Same as exprs.map(&:inspect).join(", ")
except that Proc objects are rendered as “Proc@<sourcefile>:<linenumber>”
111 112 113 |
# File 'lib/constrain.rb', line 111 def self.fmt_exprs(exprs) exprs.map { |expr| fmt_expr(expr) }.join(", ") end |
.included(base) ⇒ Object
15 16 17 |
# File 'lib/constrain.rb', line 15 def self.included base base.extend ClassMethods end |
Instance Method Details
#constrain ⇒ Object
See Constrain.constrain
32 |
# File 'lib/constrain.rb', line 32 def constrain(...) = Constrain.do_constrain(...) |
#constrain? ⇒ Boolean
See Constrain.constrain?
41 |
# File 'lib/constrain.rb', line 41 def constrain?(...) = Constrain.do_constrain?(...) |