Pour continuer avec les structures de données présentes dans la bibliothèque standard de Ruby, après les Sets, je souhaite vous présenter les Struct. Cette structure permet de créer une sorte de classe légère avec quelques attributs.
Voyons un exemple :
Struct.new("Customer", :name, :address)
customer = Struct::Customer.new("Dave", "123 Main")
customer.name # -> "Dave"
customer.address # -> "123 Main"
customer.name = "Joe"
customer.name # -> "Joe"
À la première ligne, on définit notre structure, avec d'abord son nom, suivi
de la liste des attributs. Cette structure sera ensuite accessible via
Struct::Customer. À la ligne suivante, on instancie un objet en lui passant
les paramètres dans le même ordre que les attributs lors de la définition de
la structure. Enfin, on peut utiliser les attributs sur cet objet comme pour
une classe normale où ils auraient été définis avec un attr_accessor.
Une première propriété bien sympatique des Struct est de pouvoir accéder aux
attributs comme si cet objet était un Hash :
Struct.new("Customer", :name, :address)
customer = Struct::Customer.new("Dave", "123 Main")
customer[:name] # -> "Dave"
customer[:name] = "Joe"
customer.name # -> "Joe"
Et l'autre caractérisque que j'apprécie particulièrement chez les Struct est
que le constructeur renvoie la classe. Cela permet, par exemple, de l'assigner
à une autre constante sans le namespace Struct:: :
Customer = Struct.new("Customer", :name, :address)
customer = Customer.new("Dave", "123 Main")
Dans ce cas, on peut également se passer de passer le nom de la structure en premier paramètre :
Customer = Struct.new(:name, :address)
customer = Customer.new("Dave", "123 Main")
Mais surtout, je l'utilise souvent pour hériter d cette classe. Voici un exemple
pris depuis ma gem guide-em-up :
class Index < Struct.new(:root, :current_dir, :data_dir, :themes)
def html
file = File.join(data_dir, "/browser.erb")
tmpl = File.read(file)
Erubis::Eruby.new(tmpl).result(to_hash)
end
# ...
end
Dans le même style, Ruby possède des
OpenStruct,
qui sont un mélange entre les Struct et les Hash. Voici un exemple
d'utilisation :
require 'ostruct'
person = OpenStruct.new(:first_name => "John", :last_name => "Doe")
person.age = 42
puts "#{person.first_name} #{person.last_name} a #{person.age} ans."
# -> "John Doe a 42 ans."
Note : par contre, il n'est pas possible d'utiliser la syntaxe de type
Hash pour accéder aux attributs d'un OpenStruct. Dommage…
Au final, on ne rencontre pas souvent Struct et OpenStruct quand on lit
du code Ruby. Mais ils peuvent être bien pratiques, et c'est pourquoi, je
pense que c'est une bonne idée de les connaître. Ils m'ont déjà rendu bien des
services par le passé et j'espère que vous pourrez en dire autant dans
quelques temps.
