say_age class Person attr_attribute :name, :age def initialize(name, age) @name, @age = name, age end def say_name "Hi, my name is #{name}." end def say_age "I'm #{@age} years old." end end Class Definition Tuesday, July 24, 12
say_name + say_age class Person attr_attribute :name, :age def initialize(name, age) @name, @age = name, age end def say_name "Hi, my name is #{name}." end def say_age "I'm #{@age} years old." end end Class Definition superclass class methods: Class + name + ancestors - include Tuesday, July 24, 12
say_name + say_age class Person attr_attribute :name, :age def initialize(name, age) @name, @age = name, age end def say_name "Hi, my name is #{name}." end def say_age "I'm #{@age} years old." end end Class Definition superclass class methods: Class + name + ancestors - include (Trippy.) Tuesday, July 24, 12
say_name + say_age class Person attr_attribute :name, :age def initialize(name, age) @name, @age = name, age end def say_name "Hi, my name is #{name}." end def say_age "I'm #{@age} years old." end end Class Definition superclass class methods: Class + name + ancestors - include Tuesday, July 24, 12
say_name + say_age class Person attr_attribute :name, :age def initialize(name, age) @name, @age = name, age end def say_name "Hi, my name is #{name}." end def say_age "I'm #{@age} years old." end end Class Definition superclass class methods: Class + name + ancestors - include (Ruby is an asshole.) Tuesday, July 24, 12
Person.new('Jeff', 31) jeff.say_age #=> "I'm 31 years old." jeff.say_name #=> "Hi, my name is Jeff." Class Definition name: “Jeff” age: 31 jeff Tuesday, July 24, 12
Person.new('Jeff', 31) jeff.say_age #=> "I'm 31 years old." jeff.say_name #=> "Hi, my name is Jeff." jeff.to_s #=> "#<Person:0x007ff52a14df80>" Class Definition name: “Jeff” age: 31 jeff Tuesday, July 24, 12
age: 31 jeff Where did that come from? jeff = Person.new('Jeff', 31) jeff.say_age #=> "I'm 31 years old." jeff.say_name #=> "Hi, my name is Jeff." jeff.to_s #=> "#<Person:0x007ff52a14df80>" Class Definition Tuesday, July 24, 12
class Instructor < Person def to_s "Instructor #{name}." end end jeff = Instructor.new('Jeff', 31) jeff.to_s #=> "Instructor Jeff" Tuesday, July 24, 12
Instructor.new('Jeff', 31) jeff.to_s superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Tuesday, July 24, 12
Instructor.new('Jeff', 31) jeff.say_name superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Tuesday, July 24, 12
Instructor.new('Jeff', 31) jeff.say_name superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! Tuesday, July 24, 12
Instructor.new('Jeff', 31) jeff.say_name #=> "Hi, my name is Jeff." superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Yep! Tuesday, July 24, 12
write_code module Rubyist def write_code "Ruby!" end end class Person include Rubyist end Module Instance Methods superclass class methods: Module + name + ancestors - include Tuesday, July 24, 12
include Rubyist end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... Tuesday, July 24, 12
include Rubyist end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code Including a module inserts it into the classe’s superclass chain. Tuesday, July 24, 12
include Rubyist end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code Nope! Tuesday, July 24, 12
include Rubyist end chad = Person.new chad.write_code #=> "Ruby!" superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code Yep! Tuesday, July 24, 12
include Rubyist include Lisper end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code superclass class methods: Lisper + write_code Tuesday, July 24, 12
include Rubyist include Lisper end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code Tuesday, July 24, 12
include Rubyist include Lisper end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Rubyist + write_code superclass class methods: Lisper + write_code Tuesday, July 24, 12
include Rubyist include Lisper end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Rubyist + write_code superclass class methods: Lisper + write_code Nope! Tuesday, July 24, 12
include Rubyist include Lisper end chad = Person.new chad.write_code #=> "Lithp!" superclass class methods: Person + say_name superclass class methods: Rubyist + write_code superclass class methods: Lisper + write_code Yep! Tuesday, July 24, 12
+ write_code superclass class methods: Object ... class Person def write_code "Type, type, type." end end chad = Person.new chad.write_code #=> "Type, type, type." Tuesday, July 24, 12
write_code superclass class methods: Object ... superclass class methods: Rubyist + write_code class Person def write_code "Type, type, type." end end Person.send(:include, Rubyist) chad = Person.new chad.write_code #=> Which? Precedence Tuesday, July 24, 12
write_code superclass class methods: Object ... superclass class methods: Rubyist + write_code class Person def write_code "Type, type, type." end end Person.send(:include, Rubyist) chad = Person.new chad.write_code #=> "Type, type, type." Precedence Yep! Tuesday, July 24, 12
write_code "Type, type, type." end end include Person::Coder end chad = Person.new chad.write_code superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: P::Coder + write_code Precedence Tuesday, July 24, 12
write_code "Type, type, type." end end include Person::Coder end Person.send(:include, Rubyist) chad = Person.new chad.write_code superclass class methods: Person + say_name Precedence superclass class methods: Rubyist + write_code superclass class methods: P::Coder + write_code Tuesday, July 24, 12
matt superclass class methods: Object ... Singleton Classes def matt.say_name "I'm Batman." end matt.say_name superclass class methods: Person’ + say_name Tuesday, July 24, 12
superclass class methods: Class ... superclass class methods: Person + say_name Class Methods class Person def self.fess_up "There are no class methods." end end Person.fess_up #=> "There are no class methods." Tuesday, July 24, 12
superclass class methods: Class ... superclass class methods: Class’ + fess_up superclass class methods: Person + say_name Class Methods class Person def self.fess_up "There are no class methods." end end Person.fess_up #=> "There are no class methods." “Class” methods are methods defined on the class’s singleton class. name: “chad” age: 33 chad Tuesday, July 24, 12
methods: Person + say_name superclass class methods: Object ... class Person end module Rubyist def write_code "Ruby!" end end chad = Person.new chad.extend Rubyist chad.write_code Tuesday, July 24, 12
say_name superclass class methods: Object ... superclass class methods: Rubyist + write_code Extending a module inserts it into your class’s superclass chain. Instance extends Module class Person end module Rubyist def write_code "Ruby!" end end chad = Person.new chad.extend Rubyist chad.write_code Tuesday, July 24, 12
superclass class methods: Class ... superclass class methods: Person + say_name Class extends Module module Rubyist def write_code "Ruby!" end end class Person extend Rubyist end Person.write_code Tuesday, July 24, 12
superclass class methods: Class ... superclass class methods: Person + say_name Class extends Module module Rubyist def write_code "Ruby!" end end class Person extend Rubyist end Person.write_code superclass class methods: Class’ ... Tuesday, July 24, 12
superclass class methods: Person + say_name Class extends Module module Rubyist def write_code "Ruby!" end end class Person extend Rubyist end Person.write_code superclass class methods: Class’ ... superclass class methods: Rubyist + write_code Tuesday, July 24, 12
[:width, :height, :length].each do |dim| # Fetch value from the dimensions hash define_method(dim) do return dimensions[dim] end end end define_method Tuesday, July 24, 12
end def self.end_pomodoro puts "RINNGGGGG" end def give_lecture "Pomodoro, pomodoro, pomodoro." end end instance_eval and class_eval superclass class methods: Object ... superclass class methods: Object ... superclass class methods: Class ... superclass class methods: Class’ + start_pomo + end_pomo superclass class methods: Instructor + to_s Tuesday, July 24, 12
end def self.end_pomodoro puts "RINNGGGGG" end def give_lecture "Pomodoro, pomodoro, pomodoro." end end Instructor.class_eval do def give_advice "Bonnie will take care of it!" end end superclass class methods: Object ... superclass class methods: Object ... superclass class methods: Class ... superclass class methods: Class’ + start_pomo + end_pomo instance_eval and class_eval superclass class methods: Instructor + give_lecture + give_advice Tuesday, July 24, 12
end def self.end_pomodoro puts "RINNGGGGG" end def give_lecture "Pomodoro, pomodoro, pomodoro." end end Instructor.instance_eval do def restart_pomodoro end_pomodoro start_pomodoro end end superclass class methods: Object ... superclass class methods: Instructor + to_s superclass class methods: Object ... superclass class methods: Class ... superclass class methods: Class’ + start_pomo + end_pomo + restart_pomo instance_eval and class_eval Tuesday, July 24, 12
end def self.end_pomodoro puts "RINNGGGGG" end def give_lecture "Pomodoro, pomodoro, pomodoro." end end Instructor.class_eval <<-MET, __FILE__, __LINE__ def advise_student "Bonnie will take care of it!" end MET superclass class methods: Object ... superclass class methods: Object ... superclass class methods: Class ... superclass class methods: Class’ + start_pomo + end_pomo instance_eval and class_eval superclass class methods: Instructor + give_lecture + give_advice Tuesday, July 24, 12
end define_method("#{name}=") do |value| instance_variable_set("@#{name}", value) end end end Creating a module that generates methods allows it to be extended into an existing class to provide macro abilities. class Feed extend AccessibleAttributes end Tuesday, July 24, 12
before(:each) do klass.extend AccessibleAttributes klass.accessible_attribute :foo end describe ".accessible_attribute" do it "allows writing and reading" do k = klass.new.tap{|k| k.foo = "bar" } k.foo.should == "bar" end end end Extending into a new class for each spec prevents specs from interacting with one another. Tuesday, July 24, 12
instead of the normal defs. Rewrite it again using a form of eval and a string with interpolation. For either version, add the corresponding reader methods. class Player def name=(name) @name = name end def score=(score) @score = score end def paddle=(paddle) @paddle = paddle end end Task: Define methods dynamically Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! #hand_out_contracts Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! #hand_out_contracts Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! #hand_out_contracts Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! #method_missing Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s Nope! #method_missing Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s #method_missing Yep! Tuesday, July 24, 12
end jeff = Instructor.new jeff.hand_out_contracts #NoMethodError: undefined method `hand_out_contracts' for Instructor Jeff Method Missing name: “Jeff” age: 31 jeff superclass class methods: Person + say_name superclass class methods: Object ... superclass class methods: Instructor + to_s #method_missing Yep! Tuesday, July 24, 12
is included into another class. It can be used to implement a pattern that gives the appearance that inclusion also imports “class” methods. module AccessibleAttributes def self.included(base) base.extend(ClassMethods) end module ClassMethods def accessible_attribute(name) define_method(name) do instance_variable_get("@#{name}") end define_method("#{name}=") do |value| instance_variable_set("@#{name}", value) end end end end Hooks Tuesday, July 24, 12
is included into another class. It can be used to implement a pattern that gives the appearance that inclusion also imports “class” methods. module AccessibleAttributes def self.included(base) base.extend(ClassMethods) end module ClassMethods def accessible_attribute(name) define_method(name) do instance_variable_get("@#{name}") end define_method("#{name}=") do |value| instance_variable_set("@#{name}", value) end end end end Hooks Other hooks methods include: • extended • method_defined • method_undefined • inherited Tuesday, July 24, 12
.setting that takes a name, “foo” and creates #foo_on, #foo_off, and also #foo_on?, #foo_off? instance methods. Next, let .setting take a list of setting names. class Configurator include Settings setting :power end c = Configurator.new c.power_on? #=> false c.power_off? #=> true c.power_on c.power_off? #=> false Task: Define a macro method Tuesday, July 24, 12
block. It creates an instance method of that name, the body of which is the block, but that block should be dynamically evaluated in the context of the instance. Super duper bonus: define a let! that memoizes the result of the block after the first call. Bonus: Macro with instance scope class Computor let(:quotient) { dividend / divisor } def dividend; 1; end def divisor; 0; end end c = Computor.new c.quotient # ZeroDivisionError: divided by 0 Tuesday, July 24, 12