[RAILS] Lire la métaprogrammation Ruby (partie I, jusqu'à mercredi)

Chapitre 1 Initial M

--Metaprogramming écrit du code qui écrit du code.

Qu'est-ce que l'introspection?

En programmation et Ruby, l'introspection est généralement la possibilité de voir des objets, des classes, etc. à l'exécution pour les connaître.

cf. introspection Ruby

Exemple:

#Ci-dessous la définition de la classe

class A
   def a; end
end

module B
   def b; end
end

class C < A
   include B
   def c; end
end

##Introspection
# Q.Qu'est-ce qu'une méthode d'instance C?
# A. C.instance_methods # [:c, :b, :a, :to_json, :instance_of?...]

# Q.Qu'est-ce qu'une méthode d'instance qui déclare uniquement C?
# A. C.instance_methods(false) # [:c]

# Q.Quels sont les ancêtres de la classe C?
# A. C.ancestors # [C, B, A, Object,...]

# Q.C super classe?
# A. C.superclass # A

Métaprogrammation

# the_m_word/orm.rb
class Entity
  attr_reader :table, :ident

  def initialize(table, ident)
    @table = table
    @ident = ident
    Database.sql "INSERT INTO #{@table} (id) VALUES (#{@ident})"
  end

  def set(col, val)
    Database.sql "UPDATE #{@table} SET #{col}='#{val}' WHERE id=#{@ident}"
  end

  def get(col)
    Database.sql("SELECT #{col} FROM #{@table} WHERE id=#{@ident}")[0][0]
  end
end

Même si vous n'écrivez pas la classe ci-dessus Vous pouvez écrire du code qui définit les méthodes d'accès au moment de l'exécution en héritant simplement de ActiveRecord :: Base.

Chapitre 2: Lundi: Modèle d'objet

Classe ouverte (patch de singe)

Variable d'instance

--Il n'y a pas de connexion entre les classes d'objets Ruby et les variables d'instance.

Méthode

classe

--Class est un objet --Une classe est un objet et la classe de la classe est la classe Class.

#De l'argument"false"Signifie "ignorer les méthodes héritées"
Class.instance_methods(false) # => [:allocate, :new, :superclass]

module

Class.superclass # => Module

constant

--Similarité entre les constantes Ruby et les fichiers

Chemin constant

--Séparez les chemins constants avec deux deux points. --Lorsque vous êtes à l'arrière de l'arborescence des constantes, vous pouvez spécifier une constante externe avec un chemin absolu en commençant par deux deux points indiquant la racine.

Résumé des objets et des classes

Qu'est-ce qu'un objet?

Qu'est-ce qu'une classe?

--Un objet (une instance de la classe Class) avec une liste de méthodes d'instance et un lien vers la superclasse.

Espace de nom

charger et exiger

load

require

Modèle d'objet Ruby

Recherche de méthode

MySubClass.ancestors # => [MySubclass, MyClass, Object, Kernel, BasicObject]

Receveur

--L'objet auquel appartient la méthode à appeler

Chaîne d'héritage

--Exemple de chaîne d'héritage de classe --Classe → Super classe → Super classe ... (Continuer vers BasicObject)

Recherche de modules et de méthodes

--Lorsque vous incluez un module dans une classe (ou un autre module), Ruby insère le module dans la chaîne d'héritage. ――Il entre dans ** directement au-dessus ** de la classe incluse.

module M1
  def my_method
    'My#my_method()'
  end
end

class C
  include M1
end

class D < C; end

D.ancestors # => [D, C, M, Object, Kernel, BasicObject]

méthode prefend

Exécution de la méthode

--Lorsque la méthode est appelée, la mémorisation de la référence du récepteur vous rappellera qui est le récepteur lorsque la méthode est exécutée.

mot-clé self

Contexte de haut niveau

--État lorsque la méthode n'est pas appelée, ou lorsque toutes les méthodes appelées sont retournées

self # => main
self.class # => Object

Définition de classe et soi

--Dans la définition d'une classe ou d'un module (en dehors de la méthode), le rôle de self est la classe ou le module lui-même.

class MyClass
  self # => MyClass
end

mot-clé privé

--Seulement, vous pouvez appeler une méthode avec private.

Refinements

module StringExtensions
  refine String do
    def reverse
      "esrever"
    end
  end
end

module StringStuff
  using StringExtensions
  "my_string".reverse # => "esrever"
end

"my_string".reverse # => "gnirts_ym"
  1. Le bloc de raffinage lui-même et
  2. De l'endroit où vous avez appelé using à la fin du module (si vous êtes dans la définition du module) ou à la fin du fichier (si vous êtes au niveau supérieur)

Résumé du chapitre 2

-Un objet se compose de plusieurs variables d'instance et de liens vers des classes.
-Les méthodes de l'objet vivent dans la classe de l'objet (du point de vue de la classe, cela s'appelle une méthode d'instance).
-Une classe est un objet de la classe Class. Les camarades de classe ne sont que des constantes.
-La classe est une sous-classe de Module. Un module est essentiellement une collection de méthodes. De plus, les classes peuvent être instanciées avec new ou créées hiérarchiquement avec superclass.
-Les constantes sont disposées sur une arborescence comme un système de fichiers. Les modules et les classes sont des répertoires nommés, et les constantes régulières sont comme des fichiers.
-Chaque classe a une chaîne d'héritage qui s'étend à BasicObject.
-Lorsque vous appelez la méthode, Ruby fait un pas vers la droite vers la classe du récepteur, puis remonte la chaîne d'héritage. Il continue jusqu'à ce que vous découvriez une méthode ou que vous mettiez fin à la chaîne d'héritage.
-Lorsque vous incluez un module dans une classe, le module est inséré directement au-dessus de la chaîne d'héritage pour cette classe. La pré-écriture d'un module l'insère directement sous la chaîne d'héritage pour cette classe.
-Lors de l'appel de la méthode, le récepteur devient soi-même.
-Lors de la définition d'un module (ou d'une classe), ce module devient self.
-Les variables d'instance sont toujours considérées comme des variables d'auto-instance.
-Si vous appelez une méthode sans spécifier explicitement un récepteur, elle est considérée comme une méthode self.
-Les raffinements sont comme la correction du code de classe et le remplacement de la recherche de méthode normale. Cependant, les raffinements ne sont valables que dans une zone limitée à partir du point où l'utilisation est appelée jusqu'au point où la définition du fichier ou du module se termine.

Chapitre 3: Mardi: Méthode

Éliminez le code en double

  1. Méthode dynamique
  2. method_missing

1. Méthode dynamique

--Utilisez la notation par points ou Object # send pour appeler la méthode.

obj = MyClass.new
obj.my_method(3) # => 6
obj.send(:my_method, 3) # => 6

Envoi dynamique

def refresh(options={})
  defaults = {}
  attributes = [ :input, :output, :commands, :print, :quiet,
                 :exception_handler, :hooks, :custom_completions,
                 :prompt, :memory_size, :extra_sticky_locals ]

  attributes.each do |attribute|
    defaults[attribute] = Pry.send attribute
  end
  # ...
  defaults.merge!(options).each do |key, value|
    # memory_size=L'accesseur de l'attribut tel que appelé.
    send("#{key}=", value) if respond_to?("#{key}=")
  end

  true
end
class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end

  def mouse
    component :mouse
  end

  def cpu
    component :cpu
  end

  def keyboard
    component :keyboard
  end

  def component(name)
    info = @data_source.send "get_#{name}_info", @id
    price = @data_source.send "get_#{name}_price", @id
    result = "#{name.capitalize}: #{info} ($#{price})"
    return "* #{result}" if price >= 100
    result
  end
end

Nom et symbole de la méthode

Méthode dynamique

--Une technique pour définir des méthodes lors de l'exécution.

Module#define_method

class MyClass
  define_method :my_method do |my_arg|
    my_arg * 3
  end
end

obj = MyClass.new
obj.my_method(2) # => 6
class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end

  def self.define_component(name)
    define_method(name) do
      info = @data_source.send "get_#{name}_info", @id
      price = @data_source.send "get_#{name}_price", @id
      result = "#{name.capitalize}: #{info} ($#{price})"
      return "* #{result}" if price >= 100
      result
    end
  end

  define_component :mouse
  define_component :cpu
  define_component :keyboard
end
class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
    # Array#Si vous passez un bloc à grep, le bloc sera évalué pour tous les éléments qui correspondent à l'expression régulière.
    #La chaîne qui correspond aux parenthèses de l'expression régulière est une variable globale$Stocké dans 1.
    #Exemple: data_la source est obtenir_cpu_info et obtenir_mouse_Si vous avez deux méthodes d'information
    # Computer.define_Vous appellerez le composant deux fois (passez les chaînes "cpu" et "mouse" respectivement)
    data_source.methods.grep(/^get_(.*)_info$/) { Computer.define_component $1 }
  end

  def self.define_component(name)
    define_method(name) do
      # ...
    end
  end
end

method_missing

--Lors de la recherche d'une méthode, si la méthode n'est pas trouvée, appelez la méthode method_missing pour accepter la perte. --method_missing est la méthode d'instance private de BasicObject héritée par tous les objets.

nick.send :method_missing, :my_method
# => NoMethodError: undefined method `my_method` for #<Lawyer:0x007f801b0f4978>
class Lawyer
  def method_missing(method, *args)
    puts "Appelé:#{method}(#{args.join(', ')})"
    puts "(J'ai aussi passé le bloc)" if block_given? 
  end
end

bob = Lawyer.new
bob.talk_simple('a', 'b') do
  #bloquer
end
# =>Appelé: parler_simple(a, b)
#(J'ai aussi passé le bloc)

Remplacer method_missing

Méthode fantôme

--Ce message est traité par method_missing et ressemble à un appel normal à l'appelant, mais la méthode correspondante n'est pas trouvée du côté du récepteur.

module Hashie
  class Mash < Hashie::Hash
    def method_missing(method_name, *args, &blk)
      #Si le nom de la méthode appelée est une clé de hachage[]Appelez la méthode et renvoyez la valeur correspondante.
      return self.[](method_name,&blk)ifkey?(method_name)
      #La fin du nom de la méthode est "="Si,"=Supprimez le "" pour récupérer le nom de l'attribut, puis conservez sa valeur.
      #Si aucun des deux ne correspond, méthode_missing renvoie la valeur par défaut.
      match = method_name.to_s.match(/(.*?)([?=!]?)$/)
      case match[2]
      when "="
        self[match[1]] = args.first
      else
        default(method_name, *args, &blk)
      end
    end
  end
end
Proxy dynamique

--Exemple de Ghee (une bibliothèque avec un accès facile à l'API HTTP de GitHub)

class Ghee
  class ResourceProxy
    # ...
 
    def method_missing(message, *args, &block)
      # my_gist.Hashie, un appel de méthode comme url::Mash#method_Transférer aux disparus.
      subject.send(message, *args, &block)
    end

    def subject
      #Recevoir l'objet GitHub en JSON et Hasie::Convertissez en purée.
      @subject ||= connection.get(path_prefix){|req| req.params.merge!params }.body
    end
  end
end

--Deux points de Ghee

  1. Maintenez l'objet GitHub dans un hachage dynamique. Les attributs de hachage sont accessibles en appelant des méthodes fantômes telles que «url» et «description».
  2. Enveloppez ces hachages dans un objet proxy. L'objet proxy fournit des méthodes supplémentaires. Le proxy fait deux choses.
  3. Implémentation d'une méthode nécessitant un traitement tel que "star".
  4. Transférez une méthode qui ne lit que des données telles que «url» dans le hachage encapsulé.

--Gee garde le code simple avec cette conception en deux étapes. --Il existe une méthode fantôme lors de la lecture des données, il n'est donc pas nécessaire de définir une méthode. --Définissez les méthodes uniquement lorsque vous avez besoin d'un code spécifique comme star.

class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end

  # BasicObject#method_Remplacer manquant
  def method_missing(name)
    super if !@data_source.respond_to?("get_#{name}_info")
    info = @data_source.send("get_#{name}_info", @id)
    price = @data_source.send("get_#{name}_price", @id)
    result = "#{name.capitalize}: #{info} ($#{price})"
    return "* #{result}" if price >= 100
    result
  end

  #Répondez pour voir s'il existe une méthode fantôme_to_missing?Est correctement annulée.
  def respond_to_missing?(method, include_private = false)
    @data_source.respond_to?("get_#{method}_info") || super
  end
end

Module#const_missing

class Module
  def const_missing(const_name)
    case const_name
    when :Task
      #Vous avertit de l'utilisation de noms de classe obsolètes.
      Rake.application.const_warning(const_name)
      Rake::Task
    when :FileTask
      Rake.application.const_warning(const_name)
      Rake::FileTask
    when :FileCreationTask
      # ...
    end
  end
end

Bugy method_missing

class Roulette
  def method_missing(name, *args)
    person = name.to_s.capitalize
    3.times do
      number = rand(10) + 1
      puts "#{number}..."
    end
    "#{person} got a #{number}"
  end
end

Ardoise vierge

--BasicObject, qui est la racine de la hiérarchie des classes de Ruby, n'a que le minimum de méthodes nécessaires, et afin de définir rapidement une ardoise vide dans Ruby, BasicObject doit être hérité.

Résumé du chapitre 3

-La méthode Ghost est un conseil de base (appelez toujours super, répondez toujours_to_missing?Redéfinit), ce qui évite la plupart des problèmes, mais provoque toujours des bogues complexes.
-Comme la méthode fantôme n'est pas une méthode réelle, elle se comporte différemment de la méthode réelle.
-Il existe certaines situations où seules des méthodes fantômes peuvent être utilisées, par exemple lorsqu'il y a un grand nombre d'appels de méthode ou lorsque la méthode à appeler n'est connue qu'au moment de l'exécution.
-"Utilisez des méthodes dynamiques si possible, utilisez des méthodes fantômes si vous ne pouvez pas aider"

Chapitre 4: Mercredi: Bloc

--Block fait partie d'une grande famille d '"objets appelables".

Bases du bloc

Le bloc est une fermeture

Blocs et bondage

--Définissez un bloc et obtenez la liaison à ce stade. --Lorsque vous transmettez un bloc à une méthode, emportez cette liaison avec vous.

def my_method
  #Les liaisons de la méthode ne sont pas visibles pour le bloc.
  x = "Goodbye"
  yield("cruel")
end

x = "Hello"
#Enveloppez une liaison locale comme x, puis passez le bloc à la méthode.
my_method = {|y| "#{x}, #{y} world"} # => "Hello, cruel world"

portée

Variables globales et variables d'instance de niveau supérieur

#Les variables globales sont accessibles à partir de n'importe quelle portée.
def a_scope
  $var = "some value"
end

def another_scope
  $var
end

a_scope
another_scope # => "some value"
#Les variables d'instance de niveau supérieur sont des variables d'instance de l'objet principal au niveau supérieur.
#Vous pouvez l'appeler de partout où le principal devient soi.
#Si l'autre objet devient self, la variable d'instance de niveau supérieur sort de la portée.
@var = "Variables de niveau supérieur@var"

def my_method
  @var
end

my_method # => "Variables de niveau supérieur@var"

class MyClass
  def my_method
    @var = "Variables de niveau supérieur@Pas var!"
  end
end

Porte de la portée

--Il y a trois endroits où le programme change d'étendue et ouvre une nouvelle étendue, et le mot clé qui marque chacune est appelé la porte d'étendue.

  1. Définition de classe (classe)
  2. Définition du module (module)
  3. Méthode (def)

Aplatir la portée

--Comment passer des liaisons à travers les portes de portée afin que les variables des autres portées soient visibles. ―― Cette magie est également appelée ** portée lexicale imbriquée **.

my_var = "Succès"

MyClass = Class.new do  # class MyClass
  puts "Dans la définition de classe#{my_var}!"

  define_method :my_method do  # def my_method
    "Également dans la définition de la méthode#{my_var}!"
  end
end

Portée partagée

def define_methods
  shared = 0

  Kernel.send :define_method, :counter do
    shared
  end

  Kernel.send :define_method, :inc do |x|
    shared += x
  end
end

define_methods

counter # => 0
inc(4)
counter # => 4

Résumé de la clôture

-Il existe de nombreuses contraintes sur la portée de Ruby.
    -Les portées sont séparées par des portes de portée telles que class, module et def.
-Si vous voulez sauter par-dessus la porte de la lunette et vous faufiler dans le bondage, vous pouvez utiliser le bloc (plus proche).
    -En définissant un bloc, vous pouvez encapsuler et transporter les contraintes dans votre environnement actuel.
        -Remplacez la porte de portée par un appel de méthode, encapsulez la liaison actuelle dans une fermeture et transmettez cette fermeture à la méthode.
-la classe est la classe.nouveau, le module est un module.nouveau et def sont module.define_Peut être remplacé par method.
    -C'est une lunette plate, la magie de base de la fermeture.
-Si vous définissez plusieurs méthodes dans la même étendue plate et que vous les protégez avec la porte d'étendue, vous pouvez partager la liaison.
    -C'est ce qu'on appelle une portée partagée.

instance_eval

--BasicObject # instance_eval ** évalue le bloc dans le contexte de l'objet **. -

class MyClass
  def initialize
    @v = 1
  end
end

obj = MyClass.new

# instance_Le bloc passé à eval est évalué après avoir rendu le récepteur self, donc
#La méthode privée du récepteur et@Vous pouvez également accéder à des variables d'instance telles que v.
obj.instance_eval do
  self  # => #<MyClass:0x3340dc @v=1>
  @v    # => 1
end

Différence entre instance_eval et instance_exec

class C
  def initialize
    @x = 1
  end
end

# instance_eval
class D
  def twisted_method
    @y = 2
    # instance_Quand eval se transforme en récepteur
    #La variable d'instance de l'appelant (D) sort du bloc.
    C.new.instance_eval { "@x: #{@x}, @y: #{@y}" }
  end
end

D.new.twisted_method # => "@x: 1, @y: "

# instance_exec
class D
  def twisted_method
    @y = 2
    #Les variables d'instance C et les variables d'instance D peuvent être dans la même portée.
    C.new.instance_exec(@y) {|y| "#{@x}, @y: #{y}" }
  end
end
D.mew.twisted_method # => "@x: 1, @y: 2"

À propos de la destruction de l'encapsulation

describe "PadrinoLogger" do
  context 'for logger functionality' do
    context "static asset logging" do
      ...
      should 'allow turning on static assets logging' do
        Padrino.logger.instance_eval { @log_static = true } 
        # ...
        get "/images/something.png "
        assert_equal "Foo", body
        assert_match /GET/, Padrino.logger.log.string
        Padrino.logger.instance_eval { @log_static = false }
      end
    end
  end
end

Chambre propre

--Créez un objet juste pour évaluer le bloc. Un environnement pour évaluer les blocs.

Où le code peut être stocké en dehors des blocs

--Objet appelable --Dans Ruby, méthode "enregistrer le code et l'appeler plus tard" --Dans Proc. C'est un bloc qui est devenu un objet.

Objet Proc

inc = Proc.new {|x| x + 1 }
inc.call(2) # => 3

Convertir des blocs en Proc

--Deux méthodes de noyau pour convertir des blocs en Proc - lambda - proc

dec = lambda {|x| x - 1 }
# dec = ->(x) { x - 1 }
dec.class # => Proc
dec.call(2) # => 1

& Modification

def math(a, b)
  yield(a, b)
end

# &Avec qualification, il prend le bloc passé à la méthode et le convertit en Proc!
def do_math(a, b, &operation) 
  math(a, b, &operation)
end

do_math(2, 3) {|x, y| x * y } # => 6
def my_method(&the_proc)
  the_proc
end

p = my_method {|name| "Hello, #{name}!" }
p.class # => "Proc"
p.call("Bill") # => "Hello, Bill!"
def my_method(greeting)
  "#{greeting}, #{yield}"
end

my_proc = proc { "Bill" }
my_method("Hello", &my_proc)

La conversion -Proc par & est appelée "coercition Proc" (coercition: coercition, coercition, etc.).

lambda

--La différence entre Proc et lambda

  1. Chose sur le mot-clé de retour
  2. Vérification des arguments

Proc, lambda et retour

#Pour lambda, return renvoie simplement de lambda.
def double(callable_object)
  callable_object.call * 2
end

1 = lambda { return 10 }
double(1) # => 20

#Pour Proc, retournez à partir de la portée dans laquelle Proc est défini.
def another_double
  p = Proc.new { return 10 }
  result = p.call
  return result * 2 #Je ne viendrai pas si loin!
end

another_double # => 10

def double(callable_object)
  callable_object.call * 2
end

p = Proc.new { return 10 }
double(p)  # => LocalJumpError

p = Proc.new { 10 }
double(p) # => 20

Proc, lambda et nombre de termes

p = Proc.new
p.call(1, 2, 3) # => [1, 2]
p.call(1)  # => [1, nil]
```

 Proc vs lambda

 - D'une manière générale, on dit que lambda est plus intuitif que Proc car il ressemble plus à une méthode.
 - De plus, le nombre de termes est strict et lorsque vous appelez return, il se termine simplement.
 - De nombreux Rubyistes choisissent d'abord lambda, sauf si vous avez besoin de la fonctionnalité Proc.


### Objet de méthode

 - La méthode devient également un objet appelable comme lambda.

```rb
class MyClass
  def initialize(value)
    @x = value
  end

  def my_method
    @x
  end
end

object = MyClass.new(1)
m = object.method :my_method  #Vous pouvez obtenir la méthode elle-même en tant qu'objet Method
m.call  # => 1  # Object#L'objet obtenu par méthode est utilisé comme méthode#Peut être exécuté en utilisant un appel
```

 --`Method` peut être converti en` Proc` avec `Method # to_proc`, et les blocs peuvent être convertis en méthodes avec` define_method`.

 --lambda est évalué dans la portée définie (plus proche), mais Method est évaluée dans la portée de l'objet auquel elle appartient.

 UnboundMethod

 - Quelque chose comme une méthode séparée de la classe ou du module d'origine.

```rb
module MyModule
  def my_method
    42
  end
end

unbound = MyModule.instance_method(:my_method)
unbound.class  # => UnboundMethod
```

### Récapitulatif des objets appelables

```
-Bloc (pas "objet" mais "appelable"): évalué dans la portée définie
-Proc: un objet de la classe Proc. Comme un bloc, il est évalué dans une portée définie.
-lambda: C'est aussi un objet de classe Proc, mais il est légèrement différent d'un Proc normal. Comme les blocs et les processus, il s'agit d'une clôture et est évalué dans une portée définie.
-Méthode: Liez à l'objet et évaluez dans la portée de l'objet. Vous pouvez également l'éloigner de la portée de l'objet et le lier à un autre objet.

-Pour les méthodes et les lambdas, retourne les retours de l'objet appelable.
    -D'autre part, Proc et Block reviennent du contexte d'origine de l'objet appelable.
-La méthode est stricte en ce qui concerne la différence de nombre de termes au moment de l'appel, et le lambda est également presque strict.
    -Proc et block sont tolérants.
-La différence ci-dessus est`Proc.new` 、 `Method#to_proc` 、 `&Qualification`Etc
Vous pouvez convertir d'un objet appelable à un autre.
```

## Langue spécifique au domaine

 - Exemple 1

```rb
def event(description)
  puts "ALERT: #{description}" if yield
end
loda 'events.rb'

# events.rb
event 'Des événements qui se produisent toujours' do
  true
end

event 'Des événements qui ne se produisent jamais' do
  false
end

# => ALERT:Des événements qui se produisent toujours
```

 - Exemple 2

```rb
def setup(&block)
  @setups << block
end

def event(description, &block)
  @events << {:description => description, :condition => block }
end

@setups = []
@events = []
load 'events.rb'

@events.each do |event|
  @setups.each do |setup|
    setup.call
  end
  puts "ALERT: #{event[:description}" if event[:condition].call
end
```

### Supprimer les variables globales

 - Exemple 2 révisé

```rb
lambda {
  #Les configurations et les événements sont des variables locales de lambad, donc ils ne sont pas visibles de l'extérieur
  setups = []
  events = []

  Kernel.send :define_method, :setup do |&block|
    setups << block
  end

  Kernel.send :define_method, :event do |description, &block|
    events << {:description => description, :condition => block}
  end

  Kernel.send :define_method, :each_setup do |&block|
    setups.each do |setup|
      block.call event
    end
  end

  Kernel.send :define_method, :each_event do |&block|
    events.each do |event|
      block.call event
    end
  end
}.call

each_event do |event|
  each_setup do |setup|
    setup.call
  end
  puts "ALERT: #{event[:description]}" if event[:condition].call
end

#Vous pouvez également utiliser une salle blanche dans le contexte de l'objet pour empêcher les événements de partager des variables d'instance.

each_event do |event|
  env = Object.new
  each_setup do |setup|
    env.instance_eval &setup
  end
  puts "ALERT: #{event[:description]}" if env.instance_eval &(event[:condition])
end
```

## Résumé du chapitre 4

```
-Scopegate et comment Ruby gère les étendues.
-Comment ajouter des étendues plates et partagées pour rendre les liaisons visibles dans toutes les étendues.
-Dans la portée de l'objet (instance_évaluation et instance_Comment exécuter du code (en utilisant exec) ou comment exécuter du code dans une salle blanche.
-Comment convertir des blocs et des objets (Proc) les uns aux autres.
-Comment convertir des méthodes et des objets (Method et UnboundMethod) entre eux.
-Types d'objets appelables (blocs, procs, Lambda) et leurs différences. Différence avec la méthode normale.
-Comment écrire votre propre petit DSL.
```



Recommended Posts

Lire la métaprogrammation Ruby (partie I, jusqu'à mercredi)
J'ai commencé Ruby
Ruby: lecture des données CouchDB (lecture)