Ever added the uniqueness validation to a model
class Person < ApplicationRecord
validates :name, uniqueness: { case_sensitive: false }
end
but just adding the above alone will not prevent the duplicates
Soon you will start seeing duplicates and you’ll wonder how’s that happening. After spending some time (or hours) debugging you will notice that users are adding extra white spaces to bypass the uniqueness validation. Smart hn!!
Bagel & Cream Cheese Bagel & Cream Cheese Bagel & Cream Cheese
Means now you have to take care of extra white space, and in many models. Lets create a module to handle that.
module StripedColumns
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
StripedColumnsDefaultOptions = { squeeze: false }
# add has_striped_columns as a class method
def has_striped_columns(options = StripedColumnsDefaultOptions)
options[:squeeze] = { string: true, text: true } if options[:squeeze] == true
before_validation do
self.class.columns.each do |column|
# only run for String or Text columns
next unless column.type.in? %i(string text)
# make sure value is not nil
next unless value = self.send(column.name)
# run :if condition passed as options
next unless options[:if].to_proc.call(self) if options[:if]
# check if value is a string
if value.kind_of?(String)
# remove white spaces around the text
value = value.strip
# grab the value after running the options
value = apply_striped_columns_options(column, value, options)
# assign the new value to the column
self.send("#{column.name}=", value)
end
end
end
end
end
private
def apply_striped_columns_options(column, string, options)
if squeeze_opts = options[:squeeze]
if (squeeze_opts[:string] == true && column.type == :string) ||
(squeeze_opts[:text] == true && column.type == :text)
# remove extra white spaces between words
string = string.squeeze(" ")
end
end
string
end
end
# add it to ActiveRecord::Base to make it available to all the models
ActiveRecord::Base.include(StripedColumns)
That little module will handle all the extra white space issues
class Person < ApplicationRecord
# has_striped_columns # remove spaces around
# has_striped_columns, if: :is_true? # remove spaces around only if is true
# has_striped_columns, squeeze: true # remove spaces around + remove extra space between words
# has_striped_columns, squeeze: :string # remove spaces around + remove extra space between words for string column only
# has_striped_columns, squeeze: :text # remove spaces around + remove extra space between words for text column only
validates :name, uniqueness: { case_sensitive: false }
end