Presenter: Anthony Lewis
This is a training session @ 2013 Lone Star Ruby Conference
This training covers the following topics:
- Ruby Object model
- Modules/ Mixing
- Metaprogramming
- In Ruby, everything is an object, you can define methods on class level and instance level.
inlcude
is for instance methods andextend
is for class methods, you can also useinclude
to doextend
- learn how to use
prepend
to effeciently do Fiboniacci method method missing
is powerful and dangerous (see example)
- "The wifi really sucks..."
- "Usually people don't do live coding as a presentation, but I'd like to try to get my hands dirty."
send
: calling a method is also sending a message
Person.new.send :greet
Singleton Class (Eigenclass): a singleton method is a method defined on an instance
superman = Person.new("Clark")
def superman.fly
puts "Up, up, and high"
end
superman.singleton_class
> #<Class:#<Person:0x007fa0eb03c6c0>>
include: instance methods, extend class methods. Prep a module: include module methods before methods defined in the class
module Memoize
def calc(n)
@@memo || = {}
@@memo[n] || = super
end
end
class Fib
# without prepend, it's not fast.
def calc(n)
return n if n < 2
return calc(n-1) + calc(n-2)
end
end
class_eval
: creates instance method, evaulate a code string (type is String) as if it were typed directly into the class definition
> p.name
> NoMethodError: undefined method 'name'
class Class
def get_attr(attr)
self.class_eval "
def #{attr}
@#{attr}
end
"
end
end
class Person
get_attr :name
end
define_method
: create a method at runtime
class Person
define_method :punch do |arg|
"Ouch!"*arg
end
end
method_missing
: invoked when a method is not found
class method_missing(method, *args)
# do something
end
def method_missing(meth, *args)
if metho.to_s =~ /^find_by_(.+)$/
find_by_attributes(attr, *args)
else
super
end
end
def find_by_attributes(attr, *args)
conditions = Hash[attr.map {|a| [a, args[attr.index(a)]]}]
where(condition, args)
end
module TrackMethod
def track(meth)
self.class_eval do
alias_method "old_#{meth}", meth
define_mthod meth do |*args|
puts "logging #{meth} with #{args.join(',')}"
self.send "old_#{meth}", args
end
end
end
end
# in the class where you want to use the tracking
class Person
extend TrackMethod
track :greeting
def greeting
# something
end
end
````
> p = Person.new
> p.class.instance.instance_methods(false)
###Use Ruby Set require 'set'
class User
def initialize
@features = Set.new
end
def method_missing(meth, *args)
if meth.to_s =~ /^can_(.*)\?$/
@features.include? $1.to_s
elsif meth.to_s =~ /^can_(.*)$/
@features << $1.to_s
else
super
end
end
end
Define new instance method as we go..
# define a new method inside that class
def method_missing(meth, *args)
if meth.to_s =~ /^can_(.*)\?$/
self.class.class_eval do
define_method meth.to_sym do
@features.include? $1.to_s
end
end
elsif meth.to_s =~ /^can_(.*)$/
self.class.class_eval do
define_meth meth.to_sym do
@features << $1.to_s
end
end
else
super
end
end