Skip to content

Instantly share code, notes, and snippets.

@sandofsky
Created June 2, 2011 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sandofsky/1004151 to your computer and use it in GitHub Desktop.
Save sandofsky/1004151 to your computer and use it in GitHub Desktop.
Alternatives to alias_method_chain
# 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