Skip to content

Instantly share code, notes, and snippets.

@sbeam
Created April 2, 2020 14:19
Show Gist options
  • Save sbeam/06a3b5bb8a1e354b27ca0755c94d048c to your computer and use it in GitHub Desktop.
Save sbeam/06a3b5bb8a1e354b27ca0755c94d048c to your computer and use it in GitHub Desktop.
ruby mixin with callbacks demo
module Moo
def self.included(base)
base.extend(ClassMethods)
end
def jump!
trigger(:before_jump)
puts 'JUMP'
trigger(:after_jump)
end
def dance!
trigger(:before_dance)
puts 'BOOGIE DOWN'
trigger(:after_dance)
end
def trigger(phase)
self.class.class_variable_get(:@@__phases)[phase]&.call self
end
module ClassMethods
[:jump, :dance].each do |action|
[:before, :after].each do |phase|
self.class.send(:define_method, "#{phase}_#{action}") do |&b|
set_callback("#{phase}_#{action}".to_sym, b)
end
end
# define_method("after_#{phase}") do &block
# set_callback("after_#{phase}", &block)
# end
end
protected
def set_callback(phase, b)
class_variable_set(:@@__phases, {}) unless class_variables.include?(:@@__phases)
class_variable_set(
:@@__phases,
class_variable_get(:@@__phases).merge(
phase => b
)
)
end
end
end
class Foo
include Moo
before_jump do |foo|
puts 'mmmmilky!' unless foo.milked
end
after_jump { puts 'Bounce!' }
before_dance { puts '*taps feet*' }
attr_reader :milked
def initialize(milked: false)
@milked = milked
end
end
f = Foo.new
f.jump!
puts '===='
f2 = Foo.new(milked: true)
f2.jump!
f2.dance!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment