RConditions

RConditions generates a bang method (for example, Array#empty!) for each predicate method (for example, Array#empty?). The bang method will pass if the predicate method passes, otherwise it will throw an exception. The exception will include auto-generated modules that give information which predicate methods passed or failed in the bang method’s execution.

Download

RConditions is hosted on RubyForge, and published as a gem. Installation is straightforward:

  1. Install RubyGems

  2. gem install rconditions

You may also download the gem on RConditions’s RubyForge project page.

Example

require "rconditions"

class Posting
  attr_writer :spam, :active

  def spam?
    @spam
  end

  def active?
    @active
  end

  def visible?
    !spam? && active? 
  end  
end

class User
  attr_writer :admin

  def admin?
    @admin
  end

  def can_view_posting?(posting)
     admin? || posting.visible?
  end
end

user = User.new
user.admin = false

posting = Posting.new
posting.active = false
posting.spam = true

begin
  user.can_view_posting!(posting)
rescue Posting::SpamError => e
  p e
rescue Posting::NotActiveError
  puts "should not get here"
end

# => #<Exception: User::NotAdminError, Posting::SpamError,
#      Posting::NotVisibleError, User::NotCanViewPostingError>

As you can see, the raised exception includes modules for each of the evaluated predicate methods: User#can_view_posting!(posting) in the context above called User#can_view_posting?(posting), which called User#admin? and Posting#visible?, which called Posting#spam?.

The results were

  • User#admin? # => false

  • Posting#spam? # => true

  • Posting#visible? # => false

  • User#can_view_posting? # => false

The names of the included exception modules are derived from the names of the predicate methods:

  • User::NotAdminError

  • Posting::SpamError

  • Posting::NotVisibleError

  • User::NotCanViewPostingError

Performance

As almost all predicate methods are extended by default, RConditions carries a performance penalty which varies with the number of calls to predicate methods. A simple test setup using mongrel/rails was slowed down by more than 30% by adding require "rconditions" to the bottom of its enviroment.rb.

The performance penalty can be avoided by applying RConditions only to new methods, that is, methods defined after require "rconditions". To achieve this, set ::RCONDITIONS_ONLY_FOR_NEW_METHODS = true before the require call. Our test setup had no measurable slowdown afterwards.

Supported Ruby Versions

The test suite of RConditions passes for

  • ruby 1.8.6

  • ruby 1.9.0 (tested with revision 13680)

  • jruby 1.1 (tested with revision 4574)

If you use another ruby version, please check whether the tests pass.

Limitations

  • RConditions only processes predicate methods starting with a letter and containing only word characters except the question mark at the end.

  • Kernel#block_given? is not processed.

  • Singleton methods on classes and modules are not processed.

License

RConditions is released under the MIT license.

Authors

RConditions is written by Norman Timmler and Tammo Freese.