0
RUBY META
PROGRAMMING.
@fnando
AVISOS.
TUDO É OBJETO.
    INCLUINDO CLASSES.
MUITO CÓDIGO.
VARIÁVEIS DE
    CLASSE.
class MyLib
  @@name = "mylib"

  def self.name
    @@name
  end
end
MyLib.name
#=> “mylib”
class MyOtherLib < MyLib
  @@name = "myotherlib"
end
MyOtherLib.name
#=> “myotherlib”

MyLib.name
#=> “myotherlib”
VARIÁVEIS DE
     CLASSE SÃO
COMPARTILHADAS.
VARIÁVEIS DE
  INSTÂNCIA.
class MyLib
  @name = "mylib"

  def self.name
    @name
  end
end
MyLib.name
#=> “mylib”
class MyOtherLib < MyLib
  @name = "myotherlib"
end
MyOtherLib.name
#=> “myotherlib”

MyLib.name
#=> “mylib”
VARIÁVEIS DE
  INSTÂNCIA
 PERTENCEM
 AO OBJETO.
METACLASSE.
class MyLib
  class << self
  end
end
class MyLib # ruby 1.9.2+
  singleton_class.class_eval do
  end
end
class Object
  def singleton_class
    class << self; self; end
  end
end unless Object.respond_to?(:singleton_class)
class MyLib
  class << self
    attr_accessor :name
  end
end
MyLib.name = "mylib"
MyLib.name
#=> mylib
BLOCOS.
MÉTODOS PODEM
RECEBER BLOCOS.
def run(&block)
end
BLOCOS PODEM
SER EXECUTADOS.
def run(&block)
  yield arg1, arg2
end
def run(&block)
  block.call(arg1, arg2)
end
def run(&block)
  block[arg1, arg2]
end
def run(&block) # ruby   1.9+
  block.(arg1, arg2)
end
METACLASSE,
   BLOCOS E
 VARIÁVEL DE
  INSTÂNCIA.
MyLib.configure do |config|
  config.name = "mylib"
end
class MyLib
  class << self
    attr_accessor :name
  end

  def self.configure(&block)
    yield self
  end
end
EVALUATION.
eval, class_eval, e
    instance_eval
MyLib.class_eval <<-RUBY
  "running inside class"
RUBY
#=> “running inside class”
MyLib.class_eval do
  "running inside class"
end
#=> “running inside class”
handler = proc {
  self.kind_of?(MyLib)
}

handler.call
#=> false
handler = proc {
  self.kind_of?(MyLib)
}

lib.instance_eval(&handler)
#=> true
BLOCOS,
METACLASSE,
VARIÁVEIS DE
  INSTÂNCIA,
 EVALUATION.
MyLib.configure do
  self.name = "mylib"
  name
  #=> “mylib”
end
class MyLib
  class << self
    attr_accessor :name
  end

  def self.configure(&block)
    instance_eval(&block)
  end
end
DEFINIÇÃO DE
   MÉTODOS.
MONKEY
PATCHING.
class Integer
  def kbytes
    self * 1024
  end
end

128.kbytes
#=> 131072
define_method.
MyLib.class_eval do
  define_method "name" do
    @name
  end

  define_method "name=" do |name|
    @name = name
  end
end
lib = MyLib.new
lib.name = "mynewname"
lib.name
#=> “mynewname”
EVALUATION.
MyLib.class_eval <<-RUBY
  def self.name
    "mylib"
  end

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

  def name
    "mylib's instance"
  end
end
MyLib.name
#=> “mylib”

MyLib.new.name
#=> “mylib’s instance”
BLOCOS,
 EVALUATION,
DEFINIÇÃO DE
   MÉTODOS.
MyLib.class_eval do
  name "mylib"

  name
  #=> “mylib”
end
class MyLib
  def self.accessor(method)
    class_eval <<-RUBY
      def self.#{method}(*args)
         if args.size.zero?...
MyLib.class_eval do
  name "mylib"

  name
  #=> “mylib”
end
configure do
  name "mylib"

  name
  #=> “mylib”
end
def configure(&block)
  MyLib.instance_eval(&block)
end
DISCLAIMER.
METHOD MISSING.
MyLib.new.invalid
NoMethodError: undefined method ‘invalid’ for
#<MyLib:0x10017e2f0>
class MyLib
  NAMES = { :name => "mylib’s instance" }

  def method_missing(method, *args)
    if NAMES.key?(method.to_sym...
class MyLib
  #...

 def respond_to?(method, include_private = false)
   if NAMES.key?(method.to_sym)
     true
   else
  ...
lib.name
#=> “mylib’s instance”



lib.respond_to?(:name)
#=> true
MIXINS.
class MyLib
  extend Accessor
  accessor :name
end

class MyOtherLib
  extend Accessor
  accessor :name
end
module Accessor
  def accessor(name)
    class_eval <<-RUBY
      def self.#{name}(*args)
         if args.size.zero?
    ...
MONKEY
PATCHING, MIXINS,
     EVALUATION,
        DYNAMIC
   DISPATCHING E
          HOOKS.
class Conference < ActiveRecord::Base
  has_permalink
end
"welcome to QConSP".to_permalink
#=> “welcome-to-qconsqp”
class String
  def to_permalink
    self.downcase.gsub(/[^[a-z0-9]-]/, "-")
  end
end
class Conference < ActiveRecord::Base
  before_validation :generate_permalink

  def generate_permalink
    write_attribut...
module Permalink
end

ActiveRecord::Base.send :include, Permalink
module Permalink
  def self.included(base)
    base.send :extend, ClassMethods
  end
end
module Permalink
  # ...
  module ClassMethods
    def has_permalink
      class_eval do
        before_validation :genera...
module Permalink
  # ...
 module InstanceMethods
   def generate_permalink
     write_attribute :permalink, name.to_s.to_p...
conf = Conference.create(:name => "QConSP 2010")
conf.permalink
#=> "qconsp-2010"
ENTÃO...
META
PROGRAMMING É
  COMPLICADO.
MAS NEM TANTO.
APRENDA RUBY.
OBRIGADO.
nandovieira.com.br
simplesideias.com.br
       spesa.com.br
  github.com/fnando
            @fnando
Upcoming SlideShare
Loading in...5
×

Ruby Metaprogramming

3,231

Published on

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,231
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
80
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

Transcript of "Ruby Metaprogramming"

  1. 1. RUBY META PROGRAMMING.
  2. 2. @fnando
  3. 3. AVISOS.
  4. 4. TUDO É OBJETO. INCLUINDO CLASSES.
  5. 5. MUITO CÓDIGO.
  6. 6. VARIÁVEIS DE CLASSE.
  7. 7. class MyLib @@name = "mylib" def self.name @@name end end
  8. 8. MyLib.name #=> “mylib”
  9. 9. class MyOtherLib < MyLib @@name = "myotherlib" end
  10. 10. MyOtherLib.name #=> “myotherlib” MyLib.name #=> “myotherlib”
  11. 11. VARIÁVEIS DE CLASSE SÃO COMPARTILHADAS.
  12. 12. VARIÁVEIS DE INSTÂNCIA.
  13. 13. class MyLib @name = "mylib" def self.name @name end end
  14. 14. MyLib.name #=> “mylib”
  15. 15. class MyOtherLib < MyLib @name = "myotherlib" end
  16. 16. MyOtherLib.name #=> “myotherlib” MyLib.name #=> “mylib”
  17. 17. VARIÁVEIS DE INSTÂNCIA PERTENCEM AO OBJETO.
  18. 18. METACLASSE.
  19. 19. class MyLib class << self end end
  20. 20. class MyLib # ruby 1.9.2+ singleton_class.class_eval do end end
  21. 21. class Object def singleton_class class << self; self; end end end unless Object.respond_to?(:singleton_class)
  22. 22. class MyLib class << self attr_accessor :name end end
  23. 23. MyLib.name = "mylib" MyLib.name #=> mylib
  24. 24. BLOCOS.
  25. 25. MÉTODOS PODEM RECEBER BLOCOS.
  26. 26. def run(&block) end
  27. 27. BLOCOS PODEM SER EXECUTADOS.
  28. 28. def run(&block) yield arg1, arg2 end
  29. 29. def run(&block) block.call(arg1, arg2) end
  30. 30. def run(&block) block[arg1, arg2] end
  31. 31. def run(&block) # ruby 1.9+ block.(arg1, arg2) end
  32. 32. METACLASSE, BLOCOS E VARIÁVEL DE INSTÂNCIA.
  33. 33. MyLib.configure do |config| config.name = "mylib" end
  34. 34. class MyLib class << self attr_accessor :name end def self.configure(&block) yield self end end
  35. 35. EVALUATION.
  36. 36. eval, class_eval, e instance_eval
  37. 37. MyLib.class_eval <<-RUBY "running inside class" RUBY #=> “running inside class”
  38. 38. MyLib.class_eval do "running inside class" end #=> “running inside class”
  39. 39. handler = proc { self.kind_of?(MyLib) } handler.call #=> false
  40. 40. handler = proc { self.kind_of?(MyLib) } lib.instance_eval(&handler) #=> true
  41. 41. BLOCOS, METACLASSE, VARIÁVEIS DE INSTÂNCIA, EVALUATION.
  42. 42. MyLib.configure do self.name = "mylib" name #=> “mylib” end
  43. 43. class MyLib class << self attr_accessor :name end def self.configure(&block) instance_eval(&block) end end
  44. 44. DEFINIÇÃO DE MÉTODOS.
  45. 45. MONKEY PATCHING.
  46. 46. class Integer def kbytes self * 1024 end end 128.kbytes #=> 131072
  47. 47. define_method.
  48. 48. MyLib.class_eval do define_method "name" do @name end define_method "name=" do |name| @name = name end end
  49. 49. lib = MyLib.new lib.name = "mynewname" lib.name #=> “mynewname”
  50. 50. EVALUATION.
  51. 51. MyLib.class_eval <<-RUBY def self.name "mylib" end def name "mylib's instance" end RUBY
  52. 52. MyLib.class_eval do def self.name "mylib" end def name "mylib's instance" end end
  53. 53. MyLib.name #=> “mylib” MyLib.new.name #=> “mylib’s instance”
  54. 54. BLOCOS, EVALUATION, DEFINIÇÃO DE MÉTODOS.
  55. 55. MyLib.class_eval do name "mylib" name #=> “mylib” end
  56. 56. 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 :name end
  57. 57. MyLib.class_eval do name "mylib" name #=> “mylib” end
  58. 58. configure do name "mylib" name #=> “mylib” end
  59. 59. def configure(&block) MyLib.instance_eval(&block) end
  60. 60. DISCLAIMER.
  61. 61. METHOD MISSING.
  62. 62. MyLib.new.invalid
  63. 63. NoMethodError: undefined method ‘invalid’ for #<MyLib:0x10017e2f0>
  64. 64. 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 end end
  65. 65. class MyLib #... def respond_to?(method, include_private = false) if NAMES.key?(method.to_sym) true else super end end end
  66. 66. lib.name #=> “mylib’s instance” lib.respond_to?(:name) #=> true
  67. 67. MIXINS.
  68. 68. class MyLib extend Accessor accessor :name end class MyOtherLib extend Accessor accessor :name end
  69. 69. module Accessor def accessor(name) class_eval <<-RUBY def self.#{name}(*args) if args.size.zero? @#{name} else @#{name} = args.last end end RUBY end end
  70. 70. MONKEY PATCHING, MIXINS, EVALUATION, DYNAMIC DISPATCHING E HOOKS.
  71. 71. class Conference < ActiveRecord::Base has_permalink end
  72. 72. "welcome to QConSP".to_permalink #=> “welcome-to-qconsqp”
  73. 73. class String def to_permalink self.downcase.gsub(/[^[a-z0-9]-]/, "-") end end
  74. 74. class Conference < ActiveRecord::Base before_validation :generate_permalink def generate_permalink write_attribute :permalink, name.to_s.to_permalink end end
  75. 75. module Permalink end ActiveRecord::Base.send :include, Permalink
  76. 76. module Permalink def self.included(base) base.send :extend, ClassMethods end end
  77. 77. module Permalink # ... module ClassMethods def has_permalink class_eval do before_validation :generate_permalink include InstanceMethods end end end end
  78. 78. module Permalink # ... module InstanceMethods def generate_permalink write_attribute :permalink, name.to_s.to_permalink end end end
  79. 79. conf = Conference.create(:name => "QConSP 2010") conf.permalink #=> "qconsp-2010"
  80. 80. ENTÃO...
  81. 81. META PROGRAMMING É COMPLICADO.
  82. 82. MAS NEM TANTO.
  83. 83. APRENDA RUBY.
  84. 84. OBRIGADO.
  85. 85. nandovieira.com.br simplesideias.com.br spesa.com.br github.com/fnando @fnando
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×