Skip to content

Instantly share code, notes, and snippets.

@robuye
Created May 4, 2013 10:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robuye/5517023 to your computer and use it in GitHub Desktop.
Save robuye/5517023 to your computer and use it in GitHub Desktop.
module Spec
module Generic
class And
def initialize(specs)
@specifications = specs
end
def is_satisfied_by?(subject)
@specifications.all? do |spec|
spec.is_satisfied_by?(subject)
end
end
end
class Or
def initialize(specs)
@specifications = specs
end
def is_satisfied_by?(subject)
@specifications.any? do |spec|
spec.is_satisfied_by?(subject)
end
end
end
class Not
def initialize(spec)
@spec = spec
end
def is_satisfied_by?(subject)
!@spec.is_satisfied_by?(subject)
end
end
end
class DividableBy
def initialize(divisor)
@divisor = divisor
end
def is_satisfied_by?(subject)
subject % @divisor == 0
end
end
class IsInteger
def is_satisfied_by?(subject)
subject.is_a?(Integer)
end
end
#example of custom composite specification.
#subject must be dividable by 4 and not be an integer
#or is dividable by 3
class MyMagicSpecification
def initialize(divisor, alt_divisor)
@divisor = divisor
@alt_divisor = alt_divisor
end
def is_satisfied_by?(subject)
specification.is_satisfied_by?(subject)
end
private
def specification
Generic::Or.new([dividable_not_integer, alt_dividable])
end
def dividable_not_integer
Generic::And.new([DividableBy.new(@divisor),
Generic::Not.new(IsInteger.new)])
end
def alt_dividable
DividableBy.new(@alt_divisor)
end
end
end
my_magic_spec = Spec::MyMagicSpecification.new(4,3)
my_magic_spec.is_satisfied_by?(4) # => false
my_magic_spec.is_satisfied_by?(4.0) # => true
my_magic_spec.is_satisfied_by?(12) # => true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment