6

I'm trying to find a way to normalize a string to pass it as a filename.

I have this so far:

my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').downcase.gsub(/[^a-z]/, '_')

But first problem: the - character. I guess there is more problems with this method.

I don't control the name, the name string can have accents, white spaces and special chars. I want to remove all of them, replace the accents with the corresponding letter ('é' => 'e') and replace the rest with the '_' character.

The names are like:

  • "Prélèvements - Routine"
  • "Carnet de santé"
  • ...

I want them to be like a filename with no space/special chars:

  • "prelevements_routine"
  • "carnet_de_sante"
  • ...

Thanks for the help :)

MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • Possible duplicate of [How to make a Ruby string safe for a filesystem?](https://stackoverflow.com/questions/1939333/how-to-make-a-ruby-string-safe-for-a-filesystem) – Jon Schneider Dec 05 '18 at 18:25

2 Answers2

11

Take a look at ActiveSupport::Inflector.transliterate, it's very useful handling this kind of chars problems. Read there: ActiveSupport::Inflector

Then, you could do something like:

ActiveSupport::Inflector.transliterate my_string.downcase.gsub(/\s/,"_")
AdrieanKhisbe
  • 3,899
  • 8
  • 37
  • 45
Dario Barrionuevo
  • 3,007
  • 1
  • 18
  • 17
1

Use ActiveStorage::Filename#sanitized, if spaces are okay.

If spaces are okay, which I would suggest keeping, if this is a User-provided and/or User-downloadable file, then you can make use of the ActiveStorage::Filename#sanitized method that is meant for exactly this situation.

It removes special characters that are not allowed in a file name, whilst keeping all of the nice characters that Users typically use to nicely organize and describe their files, like spaces and ampersands (&).

ActiveStorage::Filename.new( "Prélèvements - Routine" ).sanitized 
#=> "Prélèvements - Routine"

ActiveStorage::Filename.new( "Carnet de santé" ).sanitized 
#=> "Carnet de santé"

ActiveStorage::Filename.new( "Foo:Bar / Baz.jpg" ).sanitized 
#=> "Foo-Bar - Baz.jpg"

Use String#parameterize, if you want to remove nearly everything.

And if you're really looking to remove everything, try String#parameterize:

"Prélèvements - Routine".parameterize
#=> "prelevements-routine"

"Carnet de santé".parameterize
#=> "carnet-de-sante"

"Foo:Bar / Baz.jpg".parameterize
#=> "foo-bar-baz-jpg"
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245