Skip to content

Instantly share code, notes, and snippets.

@chrisarcand
Last active February 23, 2016 16:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisarcand/b425bcbd0b7bfd27addd to your computer and use it in GitHub Desktop.
Save chrisarcand/b425bcbd0b7bfd27addd to your computer and use it in GitHub Desktop.
Dynamic module lookup in Ruby
# What do you suppose the output of the examples are?
# Note: If you want to tinker executing these, don't just copy paste the entire file
# as defining everything in the same file acts differently (expected effects of reopening constants)
############## EXAMPLE 1 ##############
module NameHelper
def full_name
"#{first_name} #{last_name}"
end
end
class Person
include NameHelper
def first_name
"Abe"
end
def last_name
"Lincoln"
end
end
module NameHelper
def full_name
"George Washington"
end
end
puts Person.new.full_name
############## EXAMPLE 2 ##############
module NameHelper
def full_name
"#{first_name} #{last_name}"
end
end
class Person
include NameHelper
def first_name
"Abe"
end
def last_name
"Lincoln"
end
end
module NameHelper
prepend(Module.new {
def full_name
"George Washington"
end
})
end
puts Person.new.full_name
############## EXAMPLE 3 ##############
module NameHelper
def full_name
"#{first_name} #{last_name}"
end
end
class Person
include NameHelper
def first_name
"Abe"
end
def last_name
"Lincoln"
end
end
module NameHelper
include(Module.new {
def full_name
"George Washington"
end
})
end
puts Person.new.full_name
# Don't open this until you've guessed the outputs!
# https://bugs.ruby-lang.org/issues/9112
@bdunne
Copy link

bdunne commented Feb 23, 2016

The last one is the worst me

@krbullock
Copy link

This gist doesn't demonstrate the same thing as the bug you referenced. This behaves as one would expect if you remember that including a module just inserts it into the module's/class' inheritance chain. So in example 1, you just reopen NameHelper and redefine full_name, but in 2 and 3 you include a module in NameHelper that implements full_name. Since you end up with Person < NameHelper < #<Module:0xdeadbeef>, and NameHelper overrides full_name, method lookup stops with the "#{first_name} #{last_name}" implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment