Rails:在数据库中强制将空字符串设置为NULL

时间:2011-08-26 08:59:46

标签: mysql ruby-on-rails activerecord ruby-on-rails-3.1

是否有一种简单的方法(即配置)强制ActiveRecord在DB中将空字符串保存为NULL(如果列允许)?

原因是如果DB中的NULLable字符串列没有默认值,则不设置此值的新记录将包含NULL,而将此值设置为空字符串的新记录将不会NULL,导致数据库中的不一致,我想避免。

现在我在我的模特中做这样的事情:

before_save :set_nil

def set_nil
  [:foo, :bar].each do |att|
    self[att] = nil if self[att].blank?
  end
end

哪个有效,但效率不高或干燥。我可以把它分解成一个方法并将它混合到ActiveRecord中,但在我走这条路之前,我想知道是否有办法做到这一点。

6 个答案:

答案 0 :(得分:19)

尝试这个宝石是否有效:

https://github.com/rubiety/nilify_blanks

  

提供一个框架,用于在数据库中将传入的空白值保存为nil,在这种情况下,您宁愿使用DB NULL,而不仅仅是空字符串......

     

在Rails中,当从表单保存模型并且用户不提供值时,会将空字符串记录到数据库而不是许多人希望的NULL(混合空格和NULL会变得混乱)。此插件允许您指定属性列表(或所有属性中的异常),如果在保存模型之前它们为空,则将转换为nil。

     

只有属性响应空白?值为true的值将转换为nil。因此,这不适用于值为0的整数字段,例如......

答案 1 :(得分:7)

另一个选择是提供自定义setter,而不是在钩子中处理它。 E.g:

viewDidLoad()

答案 2 :(得分:4)

我的建议:

# app/models/contact_message.rb
class ContactMessage < ActiveRecord::Base
  include CommonValidations
  include Shared::Normalizer
end


# app/models/concerns/shared/normalizer.rb
module Shared::Normalizer
  extend ActiveSupport::Concern

  included do
    before_save :nilify_blanks
  end

  def nilify_blanks
    attributes.each do |column, value|
      # ugly but work
      # self[column] = nil if !self[column].present? && self[column] != false

      # best way
      #
      self[column] = nil if self[column].kind_of? String and self[column].empty?
    end
  end

end

答案 3 :(得分:2)

对于necroposting很抱歉,但如果您需要指定字段的解决方案,我在答案中找不到确切的内容:

module EnforceNil
  extend ActiveSupport::Concern

  module ClassMethods
    def enforce_nil(*args)
      self.class_eval do
        define_method(:enforce_nil) do
          args.each do |argument|
            field=self.send(argument)
            self.send("#{argument}=", nil)  if field.blank?
          end
        end           
        before_save :enforce_nil
      end
    end
  end
end

ActiveRecord::Base.send(:include, EnforceNil)

这样:

class User
  enforce_nil :phone #,:is_hobbit, etc  
end

当我们说你有field1和field2时,执行某个字段很方便。 Field1在SQL中有唯一的索引,但可以是空白的,所以你需要强制执行(NULL被认为是唯一的,“” - 不是通过SQL),但对于field2你实际上并不关心,你已经有很多回调或方法,它们都有效当field2为“”时,如果field2为nil,则会在错误层下挖掘您的应用。我面临的情况。

可能对某人有用。

答案 4 :(得分:0)

我使用attribute normalizer gem在属性进入db之前对其进行规范化。

答案 5 :(得分:0)

Strip Attributes Gem

有一个方便的宝石可以在保存记录时自动执行此操作,无论是在用户表单中还是在控制台中或在rake任务中等。

它被称为 strip_attributes ,非常易于使用,开箱即用的默认设置。

默认情况下它会做两件事,几乎总是要完成:

  1. 剥去前导和尾随空格:

    " My Value " #=> "My Value"
    
  2. 将空字符串转换为NULL

    ""  #=> NULL
    " " #=> NULL
    
  3. 安装

    您可以使用以下命令将其添加到您的gem文件中:

    gem strip_attributes

    用法

    将其添加到要删除前导/尾随空格的任何(或所有)模型,并将空字符串转换为NULL

    class DrunkPokerPlayer < ActiveRecord::Base
      strip_attributes
    end
    

    高级用法

    您可以基于每个模型传递其他选项来处理异常,例如,如果您想要保留前导/尾随空格等等。

    您可以在此处查看GitHub存储库中的所有选项:

    https://github.com/rmm5t/strip_attributes#examples