Rails:在数据库中强制空string为NULL

有没有一种简单的方法(即configuration)强制ActiveRecord在数据库中保存空string为NULL(如果列允许)?

这样做的原因是,如果数据库中没有默认值的情况下有一个NULLablestring列,则不设置此值的新logging将包含NULL,而将此值设置为空string的新logging不会为NULL,到我想避免的数据库中的不一致之处。

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

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

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

试试如果这个gem的作品:

https://github.com/rubiety/nilify_blanks

提供了一个框架,用于在您希望使用DB NULL而不仅仅是空白string的实例中将传入的空值保存为数据库中的nil …

在Rails中,从表单和值中保存模型不是由用户提供的,一个空string被logging到数据库而不是NULL,因为许多人会更喜欢(混合空格和空值会变得混乱)。 这个插件允许你指定一个属性列表(或者所有属性的exception),如果在保存模型之前它们是空白的,它们将被转换为nil。

只有属性响应空白? 与真值将被转换为零。 因此,这不适用于值为0的整数字段,例如…

是的,目前唯一的select是使用callback。

 before_save :normalize_blank_values def normalize_blank_values attributes.each do |column, value| self[column].present? || self[column] = nil end end 

您可以将代码转换为一个混合,以便将其包含在几个模型中。

 module NormalizeBlankValues extend ActiveSupport::Concern included do before_save :normalize_blank_values end def normalize_blank_values attributes.each do |column, value| self[column].present? || self[column] = nil end end end class User include NormalizeBlankValues end 

或者你可以在ActiveRecord :: Base中将其定义在你的所有模型中。

最后,你也可以将它包含在ActiveRecord :: Base中,但在需要时启用。

 module NormalizeBlankValues extend ActiveSupport::Concern def normalize_blank_values attributes.each do |column, value| self[column].present? || self[column] = nil end end module ClassMethods def normalize_blank_values before_save :normalize_blank_values end end end ActiveRecord::Base.send(:include, NormalizeBlankValues) class User end class Post normalize_blank_values # ... end 

我的build议:

 # 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 

另一个select是提供自定义setter,而不是在钩子处理。 例如:

 def foo=(val) super(val == "" ? nil : val) end 

对不起,我不知道答案,如果你需要解决scheme来指定应该被忽略的字段,我在这里找不到确切的东西:

 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你实际上不关心,你已经有几十个callback或方法,当field2是“”,但如果field2是nil ,将挖掘你的应用程序下的错误层。 我面对的情况。

可能对某人有用。

我使用属性标准化程序 gem规范化属性之前,他们到数据库。