53 votes

Rails: Force la chaîne vide à NULL dans la base de données

Est-il un moyen facile (c'est à dire une configuration) pour forcer ActiveRecord pour enregistrer les chaînes vides comme des NULL dans la base de données (si la colonne permet)?

La raison pour cela est que si vous avez un NULLable chaîne de colonne dans la base de données sans valeur par défaut, les nouveaux enregistrements qui ne définissez pas cette valeur contient la valeur NULL, alors que de nouveaux enregistrements de définir cette valeur à la chaîne vide ne sera pas NULLE, qui conduit à des incohérences dans la base de données que je voudrais éviter.

Maintenant je suis en train de faire des choses comme cela dans mes modèles:

before_save :set_nil

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

ce qui fonctionne, mais n'est pas très efficace ou SECS. Je pourrais facteur sur une méthode et mélanger à ActiveRecord, mais avant de m'en aller dans cette voie, je voudrais savoir si il existe un moyen de le faire déjà.

55voto

Simone Carletti Points 77653

Oui, la seule option pour le moment est d'utiliser un rappel.

 before_save :normalize_blank_values

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

Vous pouvez convertir le code en un mix pour l'inclure facilement dans plusieurs modèles.

 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
 

Ou vous pouvez le définir dans ActiveRecord :: Base pour l’avoir dans tous vos modèles.

Enfin, vous pouvez également l'inclure dans ActiveRecord :: Base mais l'activer si nécessaire.

 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
 

19voto

dexter Points 6000

Essayez si cette gemme fonctionne:

https://github.com/rubiety/nilify_blanks

5voto

Sergey Yakovlev Points 64

Ma suggestion:

 # 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
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X