metaprogramming 101
TRANSCRIPT
![Page 1: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/1.jpg)
Metaprogramming 101Nando Vieira
![Page 2: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/2.jpg)
![Page 3: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/3.jpg)
codeplane.com.br
![Page 4: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/4.jpg)
howtocode.com.br
![Page 5: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/5.jpg)
O que veremosobject model, method dispatching, evaluation, hooks, DSLs.
![Page 6: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/6.jpg)
selfsempre será o receiver padrão.
![Page 7: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/7.jpg)
person.name
!"#"$%"!
![Page 8: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/8.jpg)
class User attr_accessor :first_name, :last_name def fullname "#{first_name} #{last_name}" endend
![Page 9: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/9.jpg)
class User attr_accessor :first_name, :last_name def initialize(options = {}) options.each do |name, value| send("#{name}=", value) end endend
User.new({ :first_name => "John", :last_name => "Doe"})
![Page 10: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/10.jpg)
selfarmazena as variáveis de instância.
![Page 11: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/11.jpg)
class User attr_accessor :first_name, :last_nameend
user = User.newuser.first_name = "John"user.last_name = "Doe"
user.instance_variables#=> ["@last_name", "@first_name"]
![Page 12: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/12.jpg)
variáveis de instânciaisso se aplica a todos os objetos.
![Page 13: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/13.jpg)
class Config @directory = "/some/directory" @environment = :productionend
Config.instance_variables#=> ["@environment", "@directory"]
![Page 14: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/14.jpg)
singleton_classmetaclasse, eigenclass, ghostclass.
![Page 15: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/15.jpg)
class Config class << self endend
![Page 16: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/16.jpg)
class Config singleton_class.class do # your code here endend
RUBY 1.9
![Page 17: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/17.jpg)
class Object unless Object.respond_to?(:singleton_class) def singleton_class class << self; self; end end endend
RUBY 1.8
![Page 18: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/18.jpg)
class Config def self.root_dir @root_dir end def self.root_dir=(dir) @root_dir = dir endend
![Page 19: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/19.jpg)
class Config class << self attr_accessor :root_dir endend
![Page 20: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/20.jpg)
estendendo o selfadicionando novos métodos.
![Page 21: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/21.jpg)
person = Object.new
def person.name "John Doe"end
person.name#=> "John Doe"
![Page 22: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/22.jpg)
person.singleton_methods#=> ["name"]
![Page 23: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/23.jpg)
estendendo o selfadicionando novos métodos em classes.
![Page 24: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/24.jpg)
class Config def Config.root_dir "/some/path" endend
Config.root_dir#=> "/some/path"
![Page 25: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/25.jpg)
Config.singleton_methods#=> ["root_dir"]
![Page 26: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/26.jpg)
class Config puts self == Configend
#=> true
![Page 27: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/27.jpg)
class Config def Config.root_dir "/some/path" endend
Config.root_dir#=> "/some/path"
![Page 28: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/28.jpg)
métodos de classeeles não existem no Ruby.
![Page 29: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/29.jpg)
métodoslookup + dispatching.
![Page 30: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/30.jpg)
method lookupup and right.
![Page 31: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/31.jpg)
person.name
person class << person
Person class << Person
Class class << Class
Module class << Module
Object class << Object
BasicObject class << BasicObject
![Page 32: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/32.jpg)
NoMethodError
![Page 33: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/33.jpg)
method dispatchingexecução de métodos.
![Page 34: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/34.jpg)
person.name
![Page 35: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/35.jpg)
person.send :name
![Page 36: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/36.jpg)
person.send :say, "hello"
![Page 37: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/37.jpg)
person.__send__ :name
![Page 38: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/38.jpg)
person.public_send :name
![Page 39: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/39.jpg)
class Person attr_accessor :name, :age, :email def initialize(options = {}) options.each do |name, value| send("#{name}=", value) end endend
"#{name}="
![Page 40: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/40.jpg)
evaluationclass_eval, instance_eval, instance_exec, eval.
![Page 41: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/41.jpg)
class_evala.k.a. module_eval.
![Page 42: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/42.jpg)
class Person; end
Person.class_eval do puts self == Personend
#=> true
![Page 43: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/43.jpg)
class Person; end
Person.class_eval <<-RUBY puts self == PersonRUBY
#=> true
![Page 44: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/44.jpg)
class Person; end
Person.class_eval do def self.some_class_method end def some_instance_method endend
![Page 45: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/45.jpg)
class Person; end
module Helpers # some code hereend
Person.class_eval do include Helpersend
Person.class_eval do include Helpersend
![Page 46: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/46.jpg)
class Person class_eval <<-RUBY, __FILE__, __LINE__ def some_method # some code end RUBYend
__FILE__, __LINE__
![Page 47: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/47.jpg)
class Person class_eval <<-RUBY, __FILE__, __LINE__ def some_method raise "ffffuuuuuuuuuu" end RUBYend
begin Person.new.some_methodrescue Exception => error error.backtrace # ["person.rb:3:in `some_method'", "person.rb:10"]end # ["person.rb:3:in `some_method'", "person.rb:10"]
![Page 48: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/48.jpg)
instance_evala.k.a. class_eval para instâncias.
![Page 49: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/49.jpg)
Person = Class.newperson = Person.new
Person.respond_to?(:class_eval) #=> truePerson.respond_to?(:instance_eval) #=> true
person.respond_to?(:class_eval) #=> falseperson.respond_to?(:instance_eval) #=> true
![Page 50: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/50.jpg)
instance_execa.k.a. instance_eval on redbull.
![Page 51: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/51.jpg)
require "ostruct"
john = OpenStruct.new(:name => "John Doe")
block = proc do |time = nil| puts name puts timeend
john.instance_eval(&block)#=> John Doe#=> #<OpenStruct name="John Doe">
john.instance_exec(Time.now, &block)#=> John Doe#=> 2011-07-08 11:44:01 -0300
![Page 52: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/52.jpg)
evalevaluation com contexto configurável.
![Page 53: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/53.jpg)
def get_binding name = "John Doe" bindingend
eval("defined?(name)")#=> nil
eval("defined?(name)", get_binding)#=> "local-variable"
eval("name", get_binding)#=> "John Doe"
![Page 54: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/54.jpg)
hooksinterceptando eventos do Ruby.
![Page 55: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/55.jpg)
módulos & classesincluded, const_missing, extended, inherited, initialize_clone, initialize_copy, initialize_dup.
![Page 56: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/56.jpg)
includedexecutado toda vez que um módulo é incluído.
![Page 57: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/57.jpg)
module Ffffffuuu def self.included(base) base.class_eval do include InstanceMethods extend ClassMethods end end module InstanceMethods # some instance methods end module ClassMethods # some class methods endend
base.class_eval do include InstanceMethods extend ClassMethods end
![Page 58: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/58.jpg)
class Person include Ffffffuuuend
Person.singleton_class.included_modules#=> [Ffffffuuu::ClassMethods, Kernel]
Person.included_modules#=> [Ffffffuuu::InstanceMethods, Ffffffuuu, Kernel]
![Page 59: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/59.jpg)
métodosmethod_added, method_missing, method_removed, method_undefined, singleton_method_added, singleton_method_removed, singleton_method_undefined
![Page 60: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/60.jpg)
method_missingexecutado toda vez que um método não for encontrado.
![Page 61: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/61.jpg)
class Logger attr_accessor :output LEVELS = [ :debug, :info, :warn, :error, :critical ] def initialize(output) @output = output end def log(level, message) output << "[#{level}] #{message}\n" endend
![Page 62: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/62.jpg)
logger = Logger.new(STDOUT)logger.log :debug, "Fffffuuuuu"
![Page 63: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/63.jpg)
class Logger attr_accessor :output LEVELS = [ :debug, :info, :warn, :error, :critical ] def initialize(output) @output = output end def log(level, message) output << "[#{level}] #{message}\n" end def method_missing(name, *args, &block) return send(:log, name, args.first) if LEVELS.include?(name) super endend
![Page 64: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/64.jpg)
def respond_to?(method, include_private = false) return true if LEVELS.include?(method.to_sym) superend
![Page 65: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/65.jpg)
DSLsfuckyeah.
![Page 66: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/66.jpg)
interfaces fluenteschaining.
![Page 67: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/67.jpg)
@message = [email protected]("john").from("mary").text("bring milk.")@message.deliver#=> "mary said: john, bring milk."
![Page 68: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/68.jpg)
class Message def to(name) @to = name self end
def from(name) @from = name self end
def text(message) @text = message self endend
![Page 69: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/69.jpg)
![Page 70: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/70.jpg)
module FluentAttribute def fluent_attr(*names) names.each do |name| class_eval <<-RUBY, __FILE__, __LINE__ def #{name}(value) # def to(value) @#{name} = value # @to = value self # self end # end RUBY end endend
![Page 71: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/71.jpg)
class Message extend FluentAttribute fluent_attr :from, :to, :textend
![Page 72: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/72.jpg)
dúvidas?
![Page 73: Metaprogramming 101](https://reader034.vdocuments.us/reader034/viewer/2022052301/554bc307b4c90594278b52a9/html5/thumbnails/73.jpg)
obrigadohttp://nandovieira.com.br.