web-dev-qa-db-fra.com

Attribuer une variable uniquement si non nulle

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.

8
Juuro

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.

8
New Alexandria

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?
10
Mark Reed

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
9
Don Cruickshank

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
8
user

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
0
Escapeit