class Matchi::Predicate

Predicate matcher.

Public Class Methods

new(name, *args, **kwargs, &block) click to toggle source

Initialize the matcher with a name and arguments.

@example

require "matchi/predicate"

Matchi::Predicate.new(:be_empty)

@param name [#to_s] A matcher name. @param args [Array] A list of parameters. @param kwargs [Hash] A list of keyword parameters. @param block [Proc] A block of code.

# File lib/matchi/predicate.rb, line 17
def initialize(name, *args, **kwargs, &block)
  @name = String(name)

  raise ::ArgumentError unless valid_name?

  @args   = args
  @kwargs = kwargs
  @block  = block
end

Public Instance Methods

expected() click to toggle source

@return [Array] The method name with any arguments to send to the subject.

# File lib/matchi/predicate.rb, line 28
def expected
  [method_name, @args, @kwargs, @block]
end
inspect() click to toggle source

A string containing a human-readable representation of the matcher.

# File lib/matchi/predicate.rb, line 61
def inspect
  "#{self.class}(#{@name}, *#{@args.inspect}, **#{@kwargs.inspect}, &#{@block.inspect})"
end
matches?() { || ... } click to toggle source

Boolean comparison between the actual value and the expected value.

@example

require "matchi/predicate"

matcher = Matchi::Predicate.new(:be_empty)

matcher.expected        # => [:empty?, [], {}, nil]
matcher.matches? { [] } # => true

@example

require "matchi/predicate"

matcher = Matchi::Predicate.new(:have_key, :foo)

matcher.expected                 # => [:has_key?, [:foo], {}, nil]
matcher.matches? { { foo: 42 } } # => true

@yieldreturn [#object_id] The actual value to receive the method request.

@return [Boolean] A boolean returned by the actual value being tested.

# File lib/matchi/predicate.rb, line 53
def matches?
  value = yield.send(method_name, *@args, **@kwargs, &@block)
  return value if [false, true].include?(value)

  raise ::TypeError, "Boolean expected, but #{value.class} instance returned."
end
to_s() click to toggle source

Returns a string representing the matcher.

# File lib/matchi/predicate.rb, line 66
def to_s
  (
    "#{@name.tr('_', ' ')} " + [
      @args.map(&:inspect).join(", "),
      @kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", "),
      (@block.nil? ? "" : "&block")
    ].reject { |i| i.eql?("") }.join(", ")
  ).strip
end

Private Instance Methods

method_name() click to toggle source

The name of the method to send to the object.

# File lib/matchi/predicate.rb, line 79
def method_name
  if @name.start_with?("be_")
    :"#{@name.gsub("be_", "")}?"
  else
    :"#{@name.gsub("have_", "has_")}?"
  end
end
valid_name?() click to toggle source

Verify the matcher name structure.

# File lib/matchi/predicate.rb, line 88
def valid_name?
  return false if @name.end_with?("?", "!")

  @name.start_with?("be_", "have_")
end