I hope the title is not too unclear.
I am making arails app and I have a question about rails validation. Consider this code in the User,rb model file:
validates :name,
presence: true,
length: { maximum: 50 },
uniqueness: { case_sensitive: false }
I am using the friendly_id gem to generate slugs for the users. I wont allow users to change their name. What I now need is to ensure that Names are unique in such a way that there will be no UUID's appended to slugs if two people have the same name converted in ascii approximation.
Current behaviour is:
User 1 signs up with a name and gets a slug like this:
name: "Jaiel" slug: "jaiel"
User 2 now does the same name but a bit different:
name: "Jàìèl" slug: "jaiel-6558c3f1-e6a1-4199-a53e-4ccc565657d4"
The problem here as you see I want such a uniqueness validation that User 2 would have been rejected because both names would generate the slug "jaiel" for their friendly_id's
I would appreciate your help on that matter
Thanks
Take a look into ActiveSupport::Inflector.transliterate
:
ActiveSupport::Inflector.transliterate('Ærøskøbing')
#=> "AEroskobing"
Also, with this type of validation you might want to go with custom validation (alongside the one you already have):
class User
validate :unique_slug
private
def unique_slug
names = self.class.all.map(&:asci_name)
raise ActiveRecord::RecordInvalid.new(self) if names.include?(asci_name)
end
def asci_name
ActiveSupport::Inflector.transliterate(name)
end
end
Obviously, this is super inefficient to query whole table on each validation, but this is just to point you into one of the possible directions.
Another option would be going for a callback. Transliterating the name upon creation:
before_validation: :transliterate_name
def transliterate_name
self.name = ActiveSupport::Inflector.transliterate(name)
end
It will first transliterate the name, then validate uniqueness of already transliterated name with the validation you have. Looks like a solution, definitely not as heavy as initial one.