Credit: Maurice Codik
Problem
You want your methods to to validate their arguments, using techniques like duck typing and range validation, without filling your code with tons of conditions to test arguments.
Solution
Here's a Contracts module that you can mix in to your classes. Your methods can then define and enforce contracts.
	module Contracts
	 def valid_contract(input)
	 if @user_defined and @user_defined[input]
	 @user_defined[input]
	 else
	 case input
	 when :number
	 lambda { |x| x.is_a? Numeric }
	 when :string
	 lambda { |x| x.respond_to? :to_str }
	 when :anything
	 lambda { |x| true }
	 else
	 lambda { |x| false }
	 end
	 end
	 end
	 class ContractViolation < StandardError
	 end
	 def define_data(inputs={}.freeze)
	 @user_defined ||= {}
	 inputs.each do |name, contract|
	 @user_defined[name] = contract if contract.respond_to? :call
	 end
	 end
	 def contract(method, *inputs)
	 @contracts ||= {}
	 @contracts[method] = inputs
	 method_added(method)
	 end
	 def setup_contract(method, inputs)
	 @contracts[method] = nil
	 method_renamed = "__#{method}".intern
	 conditions = ""
	 inputs.flatten.each_with_index do |input, i|
	 conditions << %{
	 if not self.class.valid_contract(#{input.inspect}).call(args[#{i}])
	 raise ContractViolation, "argument #{i+1} of method '#{method}' must" +
	 "satisfy the '#{input}' contract", caller
	 end
	 }
	 end
	 class_eval %{
	 alias_method #{method_renamed.inspect}, #{method.inspect}
	 def #{method}(*args)
	 #{conditions}
	 return #{method_renamed}(*args)
	 end
	 }
	 end
	 def method_added(method)
	 inputs = @ 
contracts[method]
	 setup_contract(method, inputs) if inputs
	 end
	end
You can call the define_data method to define contracts, and call the contract method to apply these contracts to your methods. Here's an example:
	class TestContracts
	 def hello(n, s, f)
	 n.times { f.write "hello #{s}!
" }
	 end
The hello method takes as its arguments a positive number, a string, and a file-type object that can be written to. The Contracts module defines a :string contract for making sure an item is stringlike. We can define additional contracts as code blocks; these contracts make sure an object is a positive number, or an open object that supports the write method:
	extend Contracts
	writable_and_open = lambda do |x|
	 x.respond_to?('write') and x.respond_to?('closed?') and not x.closed?
	end
	define_data(:writable => writable_and_open,
	 :positive => lambda {|x| x >= 0 })
Now we can call the contract method to create a contract for the three arguments of the hello method:
contract :hello, [:positive, :string, :writable] end
Here it is in action:
	tc = 
TestContracts.new
	tc.hello(2, 'world', $stdout)
	# hello world!
	# hello world!
	tc.hello(-1, 'world', $stdout)
	# 
Contracts::ContractViolation: argument 1 of method 'hello' must satisfy the
	# 'positive' contract
	tc.hello(2, 3001, $stdout)
	# test-contracts.rb:22: argument 2 of method 'hello' must satisfy the
	# 'string' contract (Contracts::ContractViolation)
	closed_file = open('file.txt', 'w') { }
	tc.hello(2, 'world', closed_file)
	# Contracts::ContractViolation: argument 3 of method 'hello' must satisfy the
	# 'writable' contract
Discussion
The Contracts module uses many of Ruby's metaprogramming features to make these runtime checks possible. The line of code that triggers it all is this one:
contract :hello, [:positive, :string, :writable]
That line of code replaces the old implementation of hello with one that looks like this:
	def hello(n,s,f)
	 if not (n >= 0)
	 raise ContractViolation,
	 "argument 1 of method 'hello' must satisfy the 'positive' contract", caller
	 end
	 if not (s.respond_to? String)
	 raise ContractViolation,
	 "argument 2 of method 'hello' must satisfy the 'string' contract",
	 caller
	 end
	 if not (f.respond_to?('write') and f.respond_to?('closed?')
	 and not f.closed?)
	 raise ContractViolation,
	 "argument 3 of method 'hello' must satisfy the 'writable' contract",
	 caller
	 end
	 return __hello(n,s,f)
	end
	def __hello(n,s,f)
	 n.times { f.write "hello #{s}!
" }
	end
The body of define_data is simple: it takes a hash that maps contract names to Proc objects, and adds each new contract definition to the user_defined hash of custom contracts for this class.
The contract method takes a method symbol and an array naming the contracts to impose on that method's arguments. It registers a new set of contracts by sending them to the method symbol in the @contracts hash. When Ruby adds a method definition to the class, it automatically calls the Contracts::method_added hook, passing in the name of the method name as the argument. Contracts::method_added checks whether or not the newly added method has a contract defined for it. If it finds one, it calls setup_contract.
All of the heavy lifting is done in setup_contract. This is how it works, step by step:
See Also
 
Strings
Numbers
Date and Time
Arrays
Hashes
Files and Directories
Code Blocks and Iteration
Objects and Classes8
Modules and Namespaces
Reflection and Metaprogramming
XML and HTML
Graphics and Other File Formats
Databases and Persistence
Internet Services
Web Development Ruby on Rails
Web Services and Distributed Programming
Testing, Debugging, Optimizing, and Documenting
Packaging and Distributing Software
Automating Tasks with Rake
Multitasking and Multithreading
User Interface
Extending Ruby with Other Languages
System Administration