【问题标题】:Which is the best way to test if a model instance is "empty" in Ruby on Rails?在 Ruby on Rails 中测试模型实例是否为“空”的最佳方法是什么?
【发布时间】:2011-12-07 03:07:55
【问题描述】:

我想实现一个方法来检查模型的实例是否只有 nil 或空属性,除了它的 id 或时间戳。

我使用了一种辅助方法,从 Hash 中删除一个键并返回剩余的哈希 (question 6227600)

class ActiveRecord::Base
    def blank?
        self.attributes.remove("id","created_at","updated_at").reject{|attr| self[attr].blank?}.empty?
    end
end

我想可能有更简单、有效或更安全的方法来做到这一点。有什么建议吗?

【问题讨论】:

  • 为什么要创建空实例?当您有信息填写时,只需创建实例即可。
  • 您是否要检查模型对象是否已更改?例如,如果用户没有输入任何内容,那么它就不会改变。

标签: ruby-on-rails ruby activerecord


【解决方案1】:
def blank?
  self.attributes.all?{|k,v| v.blank? || %w(id created_at updated_at).include?(k)}
end

我的回答与 tadman 给出的几乎相同,但表达方式更简洁。 小心两种情况:

- **blank?** 不是一个好的名称选择,因为如果你调用 **object_a.object_b.blank?** 试图知道 object_a 中是否有 object_b,你会得到 true如果对象存在则事件。 **empty?** 似乎是一个更好的名字

- 如果数据库设置默认值,这可能会很棘手。

编辑:由于每次迭代都构建一个数组很慢(感谢 tadman),一个更好的解决方案是:

def empty?
  ignored_attrs = {'id' => 1, 'created_at' => 1, 'updated_at' => 1}
  self.attributes.all?{|k,v| v.blank? || ignored_attrs[k]}
end

【讨论】:

  • 也感谢您对方法名称的观察。我从未找到 Object#blank?非常有用,但无论如何你是对的,最好不要覆盖默认方法。
  • 每次通过循环声明数组内联会产生显着的性能损失。您应该考虑创建一个包含您希望忽略的属性的常量,或者更好地将其转换为哈希,以便测试是 IGNORED_ATTRIBUTES[k] 而不是 ARRAY.include?(k)
  • 确实如此,但性能不是重点。我将编辑回复:D
【解决方案2】:

您可以检查 attributes 哈希中的所有属性是否不存在,或者相反:

class ActiveRecord::Base
  def blank?
    !self.attributes.find do |key, value| 
      case (key)
      when 'id', 'created_at', 'updated_at'
        false
      else
        value.present?
      end
    end
  end
end

不幸的是,如果分配了任何关系键等,这将不考虑在您的数据库中使用default 设置的内容。您必须将它们添加为异常,或将这些值与某种已知的默认状态进行比较。

这种事情可能最好根据具体情况实施。

【讨论】:

  • 谢谢你。我只能接受一个答案,我选择 Cibernox 的答案主要是因为我更喜欢避免使用案例构造。但是,您有第一个好答案的功劳!
  • 那么你应该重新考虑你的立场。 case 几乎是 O(1) 时间,其中 Array#include? 是 O(N) 时间。即使列表中只有几项,case 的表现也要好五倍。
猜你喜欢
  • 1970-01-01
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
  • 1970-01-01
相关资源
最近更新 更多