Created
June 2, 2011 09:14
-
-
Save sandofsky/1004151 to your computer and use it in GitHub Desktop.
Alternatives to alias_method_chain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Different ways to hook into an action | |
class ExampleAPI | |
def foo | |
puts "Foo" | |
end | |
end | |
# Option 1: alias_method_chain | |
class ExampleAPI | |
alias_method_chain :foo, :bar | |
def foo_with_bar | |
foo_without_bar | |
puts "did foo" | |
end | |
end | |
# Pros: | |
# * gets the job done if there isn't an API | |
# | |
# Cons: | |
# * Makes code flow insane. | |
# * Brittle. | |
# * You get away with not defining an API. | |
# Option 2: Subclass | |
class SubclassThisAPI | |
def foo | |
puts "foo" | |
end | |
end | |
class MySubclass < SubclassThisAPI | |
def foo | |
super | |
puts "Did foo" | |
end | |
end | |
# Pro: | |
# * Override APIs without public APIs. Sane backtrace. | |
# | |
# Con: | |
# * You can only hook into public methods | |
# * Subclass bloat | |
# Option 3: Explicitely declare an API, through blocks | |
class BlockPoweredAPI | |
attr_accesor :afterFoo | |
def foo | |
if afterFoo | |
afterFoo.call(self) | |
end | |
puts "foo" | |
end | |
end | |
@blockpowered = BlockPoweredAPI.new | |
@blockpowered.afterFoo = {|api| puts "Just did foo" } | |
# Pro: | |
# * Well defined API | |
# * No subclass bloat | |
# Con: | |
# * Can't unit test blocks. Have to test at the unit test level. | |
# * Blocks are closures. Be careful. | |
class DelegatePoweredAPI | |
attr_accessor :delegate | |
def foo | |
puts "foo" | |
if delegate | |
delegate.didFoo(self) | |
end | |
end | |
end | |
class MyDelegate | |
def didFoo(api) | |
puts "Did foo." | |
end | |
end | |
@delegateAPI = DelegatePoweredAPI.new | |
@delegateAPI.delegate = MyDelegate.new | |
# Pro: | |
# * One class could act as a delegate to multiple classes | |
# * You can unit test the delegate | |
# Con: | |
# * Requires more setup than blocks. | |
# * Less common in Ruby |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment