如果字符串为空,则返回一些默认值


93

通常,我需要检查某个值是否为空,并这样写“无数据存在”:

@user.address.blank? ? "We don't know user's address" : @user.address

当我们有大约20-30个字段需要以这种方式处理时,它变得很丑陋。

我所做的是带有or方法的扩展String类

class String
  def or(what)
    self.strip.blank? ? what : self
  end
end

@user.address.or("We don't know user's address")

现在看起来好多了。但这仍然是粗糙的

如何更好地解决我的问题。也许最好扩展ActiveSupport class或使用辅助方法或mixins或其他任何方法。红宝石的思想,您的经验和最佳实践可以告诉我。

Answers:


227

ActiveSupport presence向所有对象添加一个方法,如果present?(与相对blank?),则返回其接收者,nil否则返回。

例:

host = config[:host].presence || 'localhost'

2
这很酷。默认为默认导轨。谢谢!
fl00r 2011年

首先,它是优选的,因为在我的解决方案中,我至少应扩展String,Fixnum和NilClass。在这里,我可以使用没有密码的清晰代码
fl00r 2011年

12

Phrogz在PofMagicfingers的评论中给了我这个主意,但是重写呢?代替?

class String
  def |(what)
    self.strip.blank? ? what : self
  end
end

@user.address | "We don't know user's address"

2

由于您是在Ruby on Rails中进行此操作的,因此您似乎正在使用模型。如果您想要在应用程序的任何地方都提供合理的默认值,则可以(例如)覆盖模型的address方法User

我对ActiveRecord不太了解,无法为此提供良好的代码。在续集中,它将类似于:

class User < Sequel::Model
  def address        
    if (val=self[:address]).empty?
      "We don't know user's address"
    else
      val
    end
  end
end

...但是对于上面的示例,这似乎是要将视图逻辑混入模型中,这不是一个好主意。


是的,在模型中设置默认值是一个坏主意:)我的表单将哭泣
fl00r 2011年

2

或的方法可能会产生一些不良影响,因为即使字符串不为空,也始终会评估备用值(默认值)。

例如

@user.address.or User.make_a_long_and_painful_SQL_query_here

即使地址不为空,也会做额外的工作。也许您可以对此进行一些更新(很抱歉混淆单线,试图使其简短):

class String
  def or what = ""
    self.strip.empty? ? block_given? ? yield : what : self
  end
end

@user.address.or "We don't know user's address"
@user.address.or { User.make_a_long_and_painful_SQL_query_here }

好话。得到它了。但是为什么所有代码​​都会被执行?看:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r 2011年

2
将在进行原始调用时执行,而不是通过三元运算符执行。所有参数将在方法调用时求值。
Tonttu 2011年

2

最好扩展ActiveRecord或单个模型而不是String。

在您看来,您可能希望使用更明确的模式,例如

@user.attr_or_default :address, "We don't know the user's address"

这是活动记录的一部分吗?找不到任何参考。
cabe56 2013年

0

红宝石:

unless my_str.empty? then my_str else 'default' end

回报率:

unless my_str.blank? then my_str else 'default' end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.