Loverload
DSL for building method overloading in Ruby.
Rigid language like Java allow you to create method overloading:
public void draw(String s) {
...
}
public void draw(int i) {
...
}
public void draw(double f) {
...
}
public void draw(int i, double f) {
...
}
However, in Ruby, we don't have this kind of thing, do we?
before_save NameSayer.new
before_save :say_my_name
before_save {|record| puts "My name is #{record.name}" }
before_save 'puts "My name is #{self.name}"'
An Intervention for ActiveRecord by Ernie Miller
Installation
Add this line to your application's Gemfile:
gem 'loverload'
And then execute:
$ bundle
Or install it yourself as:
$ gem install loverload
Usage
Simple
class Dummy
include Loverload
def_overload :hello do
with_params do
"Hello Nobody"
end
with_params do |name|
"Hello #{ name }"
end
with_params do |name, age|
"Hello #{ name } Age #{ age }"
end
end
end
dummy = Dummy.new
dummy.hello #=> 'Hello Nobody'
dummy.hello('Teja') #=> 'Hello Teja'
dummy.hello('Teja', 21) #=> 'Hello Teja Age 21'
Strict
class Dummy
include Loverload
def_overload :hello do
with_params String do |name|
"Hello Name: #{ name }"
end
with_params Fixnum do |age|
"Hello Age: #{ age }"
end
with_params String, Fixnum do |name, age|
"Hello Name: #{ name } Age: #{ age }"
end
with_params Fixnum, String do |age, name|
"Hello Age: #{ age } Name: #{ name }"
end
end
end
dummy = Dummy.new
dummy.hello('Teja') #=> 'Hello Name: Teja'
dummy.hello(21) #=> 'Hello Age: 21'
dummy.hello('Teja', 21) #=> 'Hello Name: Teja Age: 21'
dummy.hello(21, 'Teja') #=> 'Hello Age: 21 Name: Teja'
dummy.hello('Teja', 21, true) #=> NoMethodError
This is how you do :before_save
class Dummy
include Loverload
def_overload :before_save do
with_params Dummy do |dummy|
"Puke rainbow"
end
with_params Symbol do |symbol|
"Puke more rainbow"
end
with_params Proc do |proc|
"Puke rainbow and leprechaun"
end
with_params String do |string|
"Puke rainbow, leprechaun, and gold"
end
end
end
dummy = Dummy.new
dummy.before_save(Dummy.new) #=> "Puke rainbow"
dummy.before_save(:symbol) #=> "Puke more rainbow"
dummy.before_save(proc{|this| is proc}) #=> "Puke rainbow and leprechaun"
dummy.before_save('string') #=> "Puke rainbow, leprechaun, and gold"
It also support functor 'guard' arguments
class Dummy
include Loverload
def_overload :hello do
with_params ->(num){ num.odd? } do |num|
"Odd"
end
with_params ->(num){ num.even? } do |num|
"Even"
end
end
end
dummy = Dummy.new
dummy.hello(1) #=> 'Odd'
dummy.hello(2) #=> 'Even'
dummy.hello(100) #> 'Even'
It also support functor fibonnaci with recursive method, but kinda reversed on method definition.
class Dummy
include Loverload
def_overload :fibonnaci do
with_params 1 do |n|
1
end
with_params 0 do |n|
0
end
with_params Integer do |n|
fibonnaci(n - 1) + fibonnaci(n - 2)
end
end
end
dummy = Dummy.new
[*0..10].map(&dummy.method(:fibonnaci)) #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
TODO
- Cache?
NOTES
Couple weeks ago, while searching for the same library, I found yanked gem called overload from 2009, it's such an coincidence that we used similar implementation, inside it's readme, the author mentioned functor, similar gem with different approach. Then I decided to change loverload implementation using functor approach, an simple but expensive approach.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request