Skip to content

Instantly share code, notes, and snippets.

@trestrantham
Last active January 1, 2016 18:59
Show Gist options
  • Save trestrantham/8187727 to your computer and use it in GitHub Desktop.
Save trestrantham/8187727 to your computer and use it in GitHub Desktop.
Adding a before filter to module instance methods
# All Walkman commands require the Player to be running so
# let's raise an error if it's not
class Walkman
module Commands
def self.included(base)
base.extend ClassMethods
base.instance_methods(false).each do |method_name|
base.add_player_check(method_name)
end
# check every method added to see if we need to create
# a before filter for it or not
base.instance_eval do
def method_added(name)
# remove our prefix(es)
name = name.to_s
name.slice!("old_")
# check if we've already defined new methods
if !method_defined?("old_#{name}")
add_player_check(name.to_sym)
end
end
end
end
module ClassMethods
# create a before filter that checks if the player is running
# by creating a new method with our filter and aliasing the old
def add_player_check(name)
class_eval do
unless method_defined?("old_#{name}")
alias_method "old_#{name}".to_sym, name
original_method = instance_method(name)
define_method(name) do |*args, &block|
raise "Player is not running" unless player.running?
original_method.bind(self).call(*args, &block)
end
end
end
end
end
end
end
class Walkman
module Commands
module Controls
include Walkman::Commands
def play
puts "play"
end
end
end
end
class Walkman
include Commands::Controls
end
walkman = Walkman.new
walkman.player.running? # => false
walkman.play # => RuntimeError: Player is not running
# start player
walkman.player.running? # => true
walkman.play # => "play"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment