J'ai @obj.items_per_page
, qui est 20
au début, et je veux que la méthode ci-dessous lui attribue une valeur uniquement si many_items
n'est pas nil
:
def fetch_it_baby (many_items = nil)
@obj.items_per_page = many_items
Avec le code ci-dessus, même si many_items
est nil
, @obj.items_per_page
reste à 20
. Pourquoi? Et est-ce "bon" codage? Je ne devrais pas utiliser quelque chose comme
@obj.items_per_page = many_items || @obj.items_per_page
Ou y a-t-il une troisième voie? Je ne me sens pas complètement à l'aise dans l'un ou l'autre cas.
Le style que je vois généralement ressemble à ceci:
@obj.items_per_page = many_items if many_items
Ceci utilise le conditionnel en ligne, tout en évitant les conditions négatives ou doubles négatives.
Même si many_items est nil @ obj.items_per_page reste à 20
Cela ressemble à la classe @obj
qui a une méthode de modificateur personnalisée items_per_page=
qui ne met à jour la valeur que si la nouvelle valeur n'est pas nil
. Ce n'est pas standard Ruby. Par exemple, étant donné cette définition:
class Demo
attr_accessor :items_per_page
end
J'ai ce comportement:
irb(main):005:0> demo = Demo.new #=> #<Demo:0x007fb7b2060240>
irb(main):006:0> demo.items_per_page = 20 #=> 20
irb(main):007:0> demo.items_per_page #=> 20
irb(main):008:0> demo.items_per_page = nil #=> nil
irb(main):009:0> demo.items_per_page #=> nil
Quant à votre exemple, je l’écrirais probablement de cette façon:
@obj.items_per_page = many_items unless many_items.nil?
Je suggère ce qui suit, car il est clair que vous avez une valeur par défaut pour l'affectation au cas où l'appelant n'aurait pas spécifié many_items
dans l'appel:
def function(argument = nil)
variable = argument || 20
...
end
Cependant, puisque vous avez spécifié que l'affectation n'a lieu que si la valeur n'est pas nil
, vous devez vérifier la valeur nil
, sinon vous manquerez l'assignation si la valeur était false
. Si vous vraiment avez besoin de ce cas, la solution est plus longue:
def function(argument = nil)
variable = argument.nil? ? 20 : argument
...
end
Vous pouvez utiliser &&=
(de la même manière que ||=
est utilisé pour affecter uniquement si nil ou false)
> a = 20 # => 20
> a &&= 30 # => 30
> a # => 30
> a = nil # => nil
> a &&= 30 # => nil
> a = false # => false
> a &&= 30 # => false
> a = {} # => {}
> a &&= 30 # => 30
new-alexandria La réponse de/est mon choix, mais une autre "troisième voie" consisterait à utiliser un ternaire :
class Demo
attr_accessor :items_per_page
end
many_items = 100
@obj = Demo.new
@obj.items_per_page = 20 #=> 20
@obj.items_per_page = !many_items.nil? ? 30 : nil #=> 30