【问题标题】:Rails checking model to see if all fields are emptyRails 检查模型以查看所有字段是否为空
【发布时间】:2023-12-28 10:43:02
【问题描述】:

据我测试,这个辅助方法完全按照它的意图工作,但是我想知道是否有任何更简单、内置或更智能的方法来运行此检查!我也知道在 ApplicationHelper 中有这个可能并不理想。不确定我是否应该将其放在父对象(Inspection)、其他模型中,还是保持原样。

对于is_model_empty?,我需要遍历十一个不同(但相似)模型中的任何一个的每个字段,以检查它们是否都是空的。除了永远不会为空的 :id、:inspection_id、:created_at 和 :updated_at 字段之外的所有这些字段。 Empty 可以是 nil,可以是 [],也可以是 ['']。一个空字符串实际上意味着用户输入了一些内容,因此不会被包含在内。该值可以是字符串或数组,因此 .empty? 将不起作用。

def is_model_empty?(model)
    model.attributes.each do |k, v|
        unless ['id', 'inspection_id', 'created_at', 'updated_at'].include?(k)
            return false unless v.nil? || v == [] || v == [""]
        end
    end
    true
end

十一个模型都属于Inspection,每个模型都有has_one关系:

has_one :first_info_section
has_one :second_info_section
has_one :third_info_section

任何建议/反馈将不胜感激。感谢阅读!

-戴夫

【问题讨论】:

  • 您的代码将始终返回true。在初始分配之后,您永远不会向 answer 分配任何东西。
  • 感谢Jordan,但只要字段中的值不等于nil、[]或[""],它就会自动退出方法并返回false。 (return false unless v.nil? || v == [] || v == [""])。只需要一个字段中有一些文本或一个数组就可以告诉方法它不是空的!
  • 哦,我明白你的意思了,大卫。在那种情况下,如果您可以将true 放在底部,为什么还要分配answer? ;)
  • Lol 刚刚对其进行了编辑,感谢 Jordan!

标签: ruby-on-rails ruby oop model helper


【解决方案1】:
user.attributes.values.all?(&:blank?)

【讨论】:

    【解决方案2】:

    这是一个非常基本的重构:

    def is_empty?(model)
      whitelist = %w[ id inspection_id created_at updated_at ]
    
      model.attributes.all? do |attr, val|
        whitelist.exclude?(attr) || val.nil? || val == [] || val == [""]
      end
    end
    

    不过,您真正想要的是一个验证器,在 Active Record Validations Rails Guide 中有描述:

    在这种情况下,它看起来像这样:

    class EmptyValidator < ActiveModel::Validator
      WHITELIST = %w[ id inspection_id created_at updated_at ].freeze
    
      def validate(record)
        return unless model.attributes.all? do |attr, val|
          WHITELIST.exclude?(attr) || empty?(val)
        end
        record.errors[:base] << "You missed one!"
      end
    
      private
      def empty?(val)
        val.nil? || val == [] || val == [""]
      end
    end
    

    然后,在您的每个模型中...

    class MyModel < ActiveRecord::Base
      validates_with EmptyValidator
    end
    

    希望对你有帮助!

    【讨论】:

    • 感谢 Jordan,这非常有帮助,每当我需要对模型运行验证以确保一种或另一种状态时,它都会派上用场。有了这个项目,这两种情况都是完全可以接受的(空模型与完整模型),所以尽管架构可能还有一些不足之处,但我不需要引发任何异常或记录错误,只需要根据情况返回 true 或 false每个模型中的数据(或缺少数据)。感谢您的时间!
    【解决方案3】:

    您的方法可以简化为每个模型上的实例方法。如果所有模型的属性异常都相同,您可以创建一个共享库并将其包含在每个模型中。

    app/models/empty_detection.rb:

    module EmptyDetection
      def empty?
        attributes.all? do |k, v|
          ['id', 'inspection_id', 'created_at', 'updated_at'].include?(k) || v.nil? || v == [] || v == [""]
        end
      end
    end
    

    在您希望能够检查空条件的每个模型中包含该模块。比如Widget模型:

    class Widget < ActiveRecord::Base
      include EmptyDetection
    end
    

    现在您可以在任何 Widget 实例上使用它:

    widget = Widget.find(45)
    widget.empty?
    

    【讨论】:

    • 几乎正是我想要的,已经实现并且(仍然)工作得很好!感谢您的帮助和您的宝贵时间。