Question
Je travaille sur une classe Chart
qui comporte un paramètre margin
, qui contient : top
, : bottom
, : droit
et : gauche
. Ma première option a été de faire de margin
un setter et de définir des valeurs telles que:
# Sets :left and :right margins and doesn't alter :top and :bottom
chart.margins = {:left => 10, :right => 15}
C'est bien, parce que c'est clairement un configurateur, mais, après réflexion, je pense que cela pourrait être déroutant aussi: l'utilisateur pourrait penser que les marges ne contiennent que : left
et : right
valeurs, ce qui n'est pas correct. Une autre option est d’éliminer =
et d’en faire une méthode ordinaire:
chart.margins(:left => 10, :right => 15)
Avec cette syntaxe, il est facile de comprendre ce qui se passe, mais ce n'est pas un outil de définition standard qui entre en conflit avec marges
getter. Et il y a encore une autre option:
chart.margins(:left, 10)
chart.margins(:right, 15)
Je ne sais pas quoi penser à ce sujet. Pour moi, il est évident que la méthode est un setter, mais cette fois, je ne peux pas définir plusieurs valeurs avec un seul appel et le problème avec getter est à nouveau problématique. Je suis relativement nouveau chez Ruby et je ne suis pas encore habitué à tous les idiomes. Alors, qu'en pensez-vous les gars? Quelle est la meilleure option?
La solution
Vous pouvez également créer une classe Margin afin de profiter de la syntaxe claire suivante:
class Margin
attr_accessor :left, :right, :top, :bottom
...
end
class Chart
attr_accessor :margins
...
end
chart.margins.left = 10
puts chart.margins.right
Autres conseils
Vous n'êtes pas sûr de savoir si c'est le type de syntaxe que vous souhaitez rendre disponible (désolé si ce n'est pas le cas)
#!/usr/bin/ruby
class Margins < Struct.new(:top, :bottom, :left, :right)
end
class Chart
attr_reader :margins
def initialize()
@margins = Margins.new(0,0,0,0)
end
def margins=(hash)
[:top, :bottom, :left, :right].each do |dir|
if (hash[dir])
@margins[dir] = hash[dir]
end
end
end
end
c = Chart.new
c.margins.left = 10
c.margins={:top=>12,:bottom=>13}
puts c.margins.left
# 10
puts c.inspect;
# #<Chart:0xb7caaf8c @margins=#<struct Margins top=12, bottom=13, left=10, right=0>>
# However c.margins.foo = 12 would give you an error
En plus de la réponse de paradigmatic, vous pouvez ajouter une méthode à la classe Margins pour prendre en charge:
chart.margins.set :left => 10, :right => 15
Vous pouvez étendre la méthode margins = pour traiter un argument numérique:
chart.margins = 20
en sucre pour:
chart.margins = Margins.new(20, 20, 20, 20)
Je ne pense pas que créer une classe pour Margin soit une exagération. Vous pouvez toujours exposer ses valeurs sous forme de hachage à l'aide de to_hash
ou quelque chose de similaire.
En outre, si vous le souhaitez, vous pouvez le faire fonctionner à la manière de DSL:
chart.margins do |m|
m.left 10
m.right 20
m.vertical 5 # sets both top and bottom margin
end
Mais je suppose que je choisirais quand même l'approche de paradigmatic ...
Vous pouvez également vous en tenir à ce que vous aviez auparavant et utiliser la syntaxe de hachage normale.
margins["left"] = 10 #to set just one without changing the others