ruby 仅在不为空时分配变量

m4pnthwp  于 2022-11-04  发布在  Ruby
关注(0)|答案(9)|浏览(128)

我有一个@obj.items_per_page,它的开头是20,我希望下面的方法仅在many_items不是nil时才给它赋值:

def fetch_it_baby (many_items = nil)
    @obj.items_per_page = many_items

使用上面的代码,即使many_itemsnil@obj.items_per_page仍然是20。为什么?这是“好的”代码吗?我不应该使用类似于

@obj.items_per_page = many_items || @obj.items_per_page

或者有第三种方法吗?我对这两种方法都不太满意。

1bqhqjot

1bqhqjot1#

我通常看到的样式是这样的:

@obj.items_per_page = many_items if many_items

这会使用内嵌条件式,同时避免负数或双负数条件。

xu3bshqb

xu3bshqb2#

我建议如下,因为它清楚地表明,如果调用者在调用中没有指定many_items,则可以为赋值指定一个默认值:

def function(argument = nil)
  variable = argument || 20
  ...
end

然而,由于您指定了仅当值不是nil时才进行赋值,因此您需要检查nil值,否则如果值是false,您将错过赋值。如果您 * 真的 * 需要这种情况,则解决方案将更加冗长:

def function(argument = nil)
  variable = argument.nil? ? 20 : argument
  ...
end
epggiuax

epggiuax3#

你可以使用&&=(与||=仅在nil或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

但记住

> a = 30      # => 30
> a &&= nil   # => nil
> a &&= false # => nil
> b &&= 3     # => nil
tyu7yeag

tyu7yeag4#

即使many_items为nil @obj.items_per_page仍保持为20
这听起来像是无论@obj是什么类,都有一个自定义的修饰符方法items_per_page=,它只在新值不是nil时才更新值,这不是标准的Ruby。

class Demo
  attr_accessor :items_per_page
end

我得到这样的行为:

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

至于你的例子,我可能会这样写:

@obj.items_per_page = many_items unless many_items.nil?
ct3nt3jp

ct3nt3jp5#

对于Rails,您也可以使用presence,如here所述

region = params[:state].presence || params[:country].presence || 'US'
cclgggtu

cclgggtu6#

new-alexandria的答案是我的首选,但另一个“第三种方法”是使用三元:

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
ruoxqz4g

ruoxqz4g7#

我正在使用Rails,我也有类似的需求。
您可以在模型上定义方法:

class Gift < ApplicationRecord
  def safe_set(attribute, value)
    return if value.nil?
    send("#{attribute}=", value)
  end
end

所以你可以做

g = Gift.new
g.colour = 'red'
g.safe_set(:colour, nil)
g.colour  -> 'red'
g.safe_set(:colour, 'green')
g.colour  -> 'green'
nzrxty8p

nzrxty8p8#

我们在Rails中还有一个方法,可以帮助删除为nil的值。
紧凑的
此方法可用于数组hash。返回相同的数据,删除所有为nil的值
例如:
array.compact
进一步参考:
https://apidock.com/ruby/v1_9_3_392/Array/compact

3bygqnnd

3bygqnnd9#

如果many_items是一个变量,那么if/unless版本是最好的。但是如果many_items实际上是一个你不想多次求值的方法,我发现下面的方法很有用。

@obj.items_per_page = many_items.presence || @obj.items_per_page

这并不是你想要的,因为它不会赋值空字符串或其他非nil但非present的值,但大多数时候我想做这种事情,这对我很有效(当值为nil/非present时,它会创建一个自赋值,所以只有当你的setter是幂等的时候才使用它)。

相关问题