La méthode send permet d’appeler une méthode sur un objet en lui passant une chaîne de caractères.
Imaginons que nous avons plusieurs instances de Room et que nous souhaitons changer plusieurs variables d’instance en même temps.
class Room
attr_accessor :should_paint_walls,
:should_paint_ceiling,
:should_paint_furniture,
:should_paint_door
def initialize(args = {})
@should_paint_walls = false
@should_paint_ceiling = false
@should_paint_furniture = false
@should_paint_door = false
end
end
room = Room.new
p room.should_paint_walls # false
p room.should_paint_ceiling # false
p room.should_paint_furniture # false
p room.should_paint_door # false
room.should_paint_walls = true
room.should_paint_ceiling = true
room.should_paint_furniture = true
room.should_paint_door = true
p room.should_paint_walls # true
p room.should_paint_ceiling # true
p room.should_paint_furniture # true
p room.should_paint_door # true
Maintenant, nous allons reconstruire les méthodes d’instances à en itérant sur un tableau. La premier argument de la méthode send est le nom de la méthode et le second argument la valeur.
# [...]
room = Room.new
p room.should_paint_walls # false
p room.should_paint_ceiling # false
p room.should_paint_furniture # false
p room.should_paint_door # false
[:walls, :ceiling, :furniture, :door].each do |field_name|
room.send("should_paint_#{field_name}=", true)
end
p room.should_paint_walls # true
p room.should_paint_ceiling # true
p room.should_paint_furniture # true
p room.should_paint_door # true
La documentation se trouve ici.
||=
)On souhaite assigner une valeur à une variable si et seulement si elle n’est pas précédemment définie. Attention la valeur est réassigné si la variable est falsy (c’est à dire nil ou false). Donc il n’est pas conseillé d’utiliser cette méthode pour un booléan.
toto = nil
toto ||= "Je ne suis pas nil"
puts toto
# "Je ne suis pas nil"
toto = "J'ai déjà du contenu"
toto ||= "Je ne suis pas nil"
puts toto
# "J'ai déjà du contenu"
&
)Cela vous permet de naviguer à travers des objets sans risquer d’avoir une erreur.
Imaginons deux classes : Room et Flat. Une Room appartient à un Flat et ce dernier a une variable d’instance name.
class Flat
attr_accessor :name
def initialize(args = {})
@name = args[:name]
end
end
class Room
attr_accessor :flat
def initialize(args = {})
@flat = args[:flat]
end
end
flat = Flat.new(name: "Mon super appart")
room = Room.new(flat: flat)
puts room.flat.name
# => "Mon super appart"
Maintenant, imaginons qu’aucun projet ne soit rattaché à l’instance de Room.
# [...]
room = Room.new
puts room.flat.name
# => NoMethodError: undefined method `name' for nil:NilClass
Pour empêcher cette erreur, nous allons ajouter l’opérateur &
qui va nous renvoyer nil si la méthode ne fonctionne pas.
# [...]
puts room&.flat&.name
# => nil
Les procs sont très utiles quand vous souhaitez itérer sur des objets et appliquer une méthode sur chaque élément.
Commençons par un exemple un exemple simple d’un tableau de chiffres que nous voulons transformer en chaîne de caractères.
p [1,2,3].map { |number| number.to_s }
# => ["1", "2", "3"]
p [1,2,3].map(&:to_s)
# => ["1", "2", "3"]
Maintenant, imaginons une classe Room avec une variable d’instance area. Je veux récupérer toutes les valeurs et les additionner.
class Room
attr_accessor :area
def initialize(args = {})
@area = args[:area]
end
end
room1 = Room.new(area: 10)
room2 = Room.new(area: 15)
rooms = [room1, room2]
p rooms.sum { |room| room.area }
# => 25
p rooms.sum(&:area)
# => 25
On peut même écrire ses propres procs. Par exemple, un proc qui va calculer le volume des chambres (sachant qu’elles font toutes 4 mètres de hauteur).
# [...]
volume = Proc.new {|x| x.area * 4 }
p rooms.sum(&volume)
# => 100
La documentation se trouve ici.
Publié le 07/03/2020