Skip to content

Instantly share code, notes, and snippets.

@dbrady
Created April 4, 2017 16:44
Show Gist options
  • Save dbrady/08a5be3ebccd76c95113744cfab468e7 to your computer and use it in GitHub Desktop.
Save dbrady/08a5be3ebccd76c95113744cfab468e7 to your computer and use it in GitHub Desktop.
Yo Dawg, Herd U Like DSLs
class Person
def poop
puts "I pooped today!"
end
# One common way to make a class method is to declare it amongst the instance
# methods prefixed with self...
def self.poop!
puts "Everybody pooped today!"
end
class << self
# The other common way is to open Class:Person "with class << self" declare
# it as an instance method in there.
def poo!
puts "Everybody went poo today!"
end
# But what happens if you declare a self. method inside << self?
def self.poopy
puts "Something just went poopy. I have no idea what, or where, but I suspect it was messy."
end
end
end
Person.new.poop
# => I pooped today!
Person.poop!
# => Everybody pooped today!
Person.poo!
# => Everybody went poo today!
# But where is "poopy"?
# No idea how to call the "poopy" method directly. If I evaluate self from
# inside the << self scope, it is #<Class:Person> but the method does not appear
# on the class interface of Person or Class. Is #<Class:Person> the
# meta/eigen/wotsitclass?
# Hmm... let's try to see where we are at each point:
# 2.2.2 :063 > class Person
# 2.2.2 :064?> puts "Hello from #{self}"
# 2.2.2 :065?> class << self
# 2.2.2 :066?> puts "Hello from #{self}"
# 2.2.2 :067?> class << self
# 2.2.2 :068?> puts "Hello from #{self}"
# 2.2.2 :069?> end
# 2.2.2 :070?> end
# 2.2.2 :071?> end
# Hello from Person
# Hello from #<Class:Person>
# Hello from #<Class:#<Class:Person>>
# AH-HA! Okay, I still don't know exactly what's going on, BUT I do know that
# instance methods declared on self inside a class become class methods on that
# class:
# 2.2.2 :077 > class Person
# 2.2.2 :078?> poop!
# 2.2.2 :079?> end
# Everybody pooped today!
# Okay. So again, I still don't know the WHY, but I now at least know HOW to
# call that method: as a DSL/class method from INSIDE the superclass:
# 2.2.2 :080 > class Person
# 2.2.2 :081?> class << self
# 2.2.2 :082?> poopy
# 2.2.2 :083?> end
# 2.2.2 :084?> end
# Something just went poopy. I have no idea what, or where, but I suspect it was
# messy.
# AND BOOM.
# I don't know why I would ever need this skill, and I pray that I never use it
# in anger. I'm putting this in my satchel full of rusty shivs: Sometimes I get
# cornered in a dark alley at night, and when that happens I'd rather have a
# rusty shiv than empty hands.
# TL;DR This should be called "Yo Dawg, Herd U Like DSLs, So we put a DSL in yo
# DSL so you can DSL while you DSL."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment