Ruby Metaprogramming

85
RUBY META PROGRAMMING.

Transcript of Ruby Metaprogramming

Page 1: Ruby Metaprogramming

RUBY METAPROGRAMMING.

Page 2: Ruby Metaprogramming

@fnando

Page 3: Ruby Metaprogramming

AVISOS.

Page 4: Ruby Metaprogramming

TUDO É OBJETO.INCLUINDO CLASSES.

Page 5: Ruby Metaprogramming

MUITO CÓDIGO.

Page 6: Ruby Metaprogramming

VARIÁVEIS DE CLASSE.

Page 7: Ruby Metaprogramming

class MyLib @@name = "mylib" def self.name @@name endend

Page 8: Ruby Metaprogramming

MyLib.name#=> “mylib”

Page 9: Ruby Metaprogramming

class MyOtherLib < MyLib @@name = "myotherlib"end

Page 10: Ruby Metaprogramming

MyOtherLib.name#=> “myotherlib”

MyLib.name#=> “myotherlib”

Page 11: Ruby Metaprogramming

VARIÁVEIS DE CLASSE SÃO

COMPARTILHADAS.

Page 12: Ruby Metaprogramming

VARIÁVEIS DE INSTÂNCIA.

Page 13: Ruby Metaprogramming

class MyLib @name = "mylib" def self.name @name endend

Page 14: Ruby Metaprogramming

MyLib.name#=> “mylib”

Page 15: Ruby Metaprogramming

class MyOtherLib < MyLib @name = "myotherlib"end

Page 16: Ruby Metaprogramming

MyOtherLib.name#=> “myotherlib”

MyLib.name#=> “mylib”

Page 17: Ruby Metaprogramming

VARIÁVEIS DE INSTÂNCIA

PERTENCEMAO OBJETO.

Page 18: Ruby Metaprogramming

METACLASSE.

Page 19: Ruby Metaprogramming

class MyLib class << self endend

Page 20: Ruby Metaprogramming

class MyLib # ruby 1.9.2+ singleton_class.class_eval do endend

Page 21: Ruby Metaprogramming

class Object def singleton_class class << self; self; end endend unless Object.respond_to?(:singleton_class)

Page 22: Ruby Metaprogramming

class MyLib class << self attr_accessor :name endend

Page 23: Ruby Metaprogramming

MyLib.name = "mylib"MyLib.name#=> mylib

Page 24: Ruby Metaprogramming

BLOCOS.

Page 25: Ruby Metaprogramming

MÉTODOS PODEM RECEBER BLOCOS.

Page 26: Ruby Metaprogramming

def run(&block)end

Page 27: Ruby Metaprogramming

BLOCOS PODEMSER EXECUTADOS.

Page 28: Ruby Metaprogramming

def run(&block) yield arg1, arg2end

Page 29: Ruby Metaprogramming

def run(&block) block.call(arg1, arg2)end

Page 30: Ruby Metaprogramming

def run(&block) block[arg1, arg2]end

Page 31: Ruby Metaprogramming

def run(&block) block.(arg1, arg2)end

# ruby 1.9+

Page 32: Ruby Metaprogramming

METACLASSE, BLOCOS E

VARIÁVEL DE INSTÂNCIA.

Page 33: Ruby Metaprogramming

MyLib.configure do |config| config.name = "mylib"end

Page 34: Ruby Metaprogramming

class MyLib class << self attr_accessor :name end def self.configure(&block) yield self endend

Page 35: Ruby Metaprogramming

EVALUATION.

Page 36: Ruby Metaprogramming

eval, class_eval, e instance_eval

Page 37: Ruby Metaprogramming

MyLib.class_eval <<-RUBY "running inside class"RUBY#=> “running inside class”

Page 38: Ruby Metaprogramming

MyLib.class_eval do "running inside class"end#=> “running inside class”

Page 39: Ruby Metaprogramming

handler = proc { self.kind_of?(MyLib)}

handler.call#=> false

Page 40: Ruby Metaprogramming

handler = proc { self.kind_of?(MyLib)}

lib.instance_eval(&handler)#=> true

Page 41: Ruby Metaprogramming

BLOCOS, METACLASSE, VARIÁVEIS DE

INSTÂNCIA, EVALUATION.

Page 42: Ruby Metaprogramming

MyLib.configure do self.name = "mylib" name #=> “mylib”end

Page 43: Ruby Metaprogramming

class MyLib class << self attr_accessor :name end def self.configure(&block) instance_eval(&block) endend

Page 44: Ruby Metaprogramming

DEFINIÇÃO DE MÉTODOS.

Page 45: Ruby Metaprogramming

MONKEY PATCHING.

Page 46: Ruby Metaprogramming

class Integer def kbytes self * 1024 endend

128.kbytes#=> 131072

Page 47: Ruby Metaprogramming

define_method.

Page 48: Ruby Metaprogramming

MyLib.class_eval do define_method "name" do @name end

define_method "name=" do |name| @name = name endend

Page 49: Ruby Metaprogramming

lib = MyLib.newlib.name = "mynewname"lib.name#=> “mynewname”

Page 50: Ruby Metaprogramming

EVALUATION.

Page 51: Ruby Metaprogramming

MyLib.class_eval <<-RUBY def self.name "mylib" end

def name "mylib's instance" endRUBY

Page 52: Ruby Metaprogramming

MyLib.class_eval do def self.name "mylib" end def name "mylib's instance" endend

Page 53: Ruby Metaprogramming

MyLib.name#=> “mylib”

MyLib.new.name#=> “mylib’s instance”

Page 54: Ruby Metaprogramming

BLOCOS, EVALUATION,

DEFINIÇÃO DE MÉTODOS.

Page 55: Ruby Metaprogramming

MyLib.class_eval do name "mylib" name #=> “mylib”end

Page 56: Ruby Metaprogramming

class MyLib def self.accessor(method) class_eval <<-RUBY def self.#{method}(*args) if args.size.zero? @#{method} else @#{method} = args.last end end RUBY end accessor :nameend

Page 57: Ruby Metaprogramming

MyLib.class_eval do name "mylib" name #=> “mylib”end

Page 58: Ruby Metaprogramming

configure do name "mylib"

name #=> “mylib”end

Page 59: Ruby Metaprogramming

def configure(&block) MyLib.instance_eval(&block)end

Page 60: Ruby Metaprogramming

DISCLAIMER.

Page 61: Ruby Metaprogramming

METHOD MISSING.

Page 62: Ruby Metaprogramming

MyLib.new.invalid

Page 63: Ruby Metaprogramming

NoMethodError: undefined method ‘invalid’ for #<MyLib:0x10017e2f0>

Page 64: Ruby Metaprogramming

class MyLib NAMES = { :name => "mylib’s instance" }

def method_missing(method, *args) if NAMES.key?(method.to_sym) NAMES[method.to_sym] else super end endend

Page 65: Ruby Metaprogramming

class MyLib #...

def respond_to?(method, include_private = false) if NAMES.key?(method.to_sym) true else super end endend

Page 66: Ruby Metaprogramming

lib.name#=> “mylib’s instance”

lib.respond_to?(:name)#=> true

Page 67: Ruby Metaprogramming

MIXINS.

Page 68: Ruby Metaprogramming

class MyLib extend Accessor accessor :nameend

class MyOtherLib extend Accessor accessor :nameend

Page 69: Ruby Metaprogramming

module Accessor def accessor(name) class_eval <<-RUBY def self.#{name}(*args) if args.size.zero? @#{name} else @#{name} = args.last end end RUBY endend

Page 70: Ruby Metaprogramming

MONKEY PATCHING, MIXINS,

EVALUATION, DYNAMIC

DISPATCHING E HOOKS.

Page 71: Ruby Metaprogramming

class Conference < ActiveRecord::Base has_permalinkend

Page 72: Ruby Metaprogramming

"welcome to QConSP".to_permalink#=> “welcome-to-qconsqp”

Page 73: Ruby Metaprogramming

class String def to_permalink self.downcase.gsub(/[^[a-z0-9]-]/, "-") endend

Page 74: Ruby Metaprogramming

class Conference < ActiveRecord::Base before_validation :generate_permalink

def generate_permalink write_attribute :permalink, name.to_s.to_permalink endend

Page 75: Ruby Metaprogramming

module Permalinkend

ActiveRecord::Base.send :include, Permalink

Page 76: Ruby Metaprogramming

module Permalink def self.included(base) base.send :extend, ClassMethods endend

Page 77: Ruby Metaprogramming

module Permalink # ... module ClassMethods def has_permalink class_eval do before_validation :generate_permalink include InstanceMethods end end endend

Page 78: Ruby Metaprogramming

module Permalink # ... module InstanceMethods def generate_permalink write_attribute :permalink, name.to_s.to_permalink end endend

Page 79: Ruby Metaprogramming

conf = Conference.create(:name => "QConSP 2010")conf.permalink#=> "qconsp-2010"

Page 80: Ruby Metaprogramming

ENTÃO...

Page 81: Ruby Metaprogramming

METAPROGRAMMING É

COMPLICADO.

Page 82: Ruby Metaprogramming

MAS NEM TANTO.

Page 83: Ruby Metaprogramming

APRENDA RUBY.

Page 84: Ruby Metaprogramming

OBRIGADO.