Thinking on hiring me?

Please read

Fernando Guillén

a Freelance Web Developer

cabecera decorativa

software development as an artistic expression

Ruby, sanitizando tus títulos en 2 líneas.

Ayer me acosté super contento, había conseguido escribir una función para sanitizar strings, o como dicen por ahí: crear un SLUG (que todavía no he encontrado la definición exacta).

Si no sabes de que hablo se trata de convertir un “Hola mundo!, qué tal?” en un “hola-mundo-que-tal” para las URLS bonitas y todo eso.

No había sido fácil pues Ruby se lleva mal con los caracteres no-ASCII y el castellano tiene muchos, había que hacer un pequeño malabarismo con la gema Unicode.

Al final mi función se veía así:

require 'unicode'
def to_slug( sentence, length = 64 )
  return if sentence.blank?
 
  wrong = ['á','é','í','ó','ú','ä','ë','ï','ö','ü','à','è','ì','ò','ù','ñ','ç','º','ª','_']
  right = ['a','e','i','o','u','a','e','i','o','u','a','e','i','o','u','n','s','o','a','-']
 
  sentence = sentence[0..length-1]
  sentence = Unicode.downcase( sentence )
 
  for i in 0..wrong.size-1
    sentence.gsub!( wrong[i], right[i] )
  end
 
  sentence.gsub!( /[^a-z0-9-]/, '-' ) # not letters of numbers
  sentence.gsub!( /-{2,}/, '-' )      # 2 or more '-' together becoming 1 '-'
  sentence.gsub!( /^-|-$/, '' ) unless sentence.size == 1 # '-' at begging or at end
  sentence
end

Estaba super orgulloso hasta que me despierto por la mañana y cambiando la pregunta a Google me encuentro con un… ‘inombrable’ que me hace esto:

require 'unicode'
def to_slug
  str = Unicode.normalize_KD(self).gsub(/[^\x00-\x7F]/n,'')
  str = str.gsub(/\W+/, '-').gsub(/^-+/,'').gsub(/-+$/,'').downcase
end

Exactamente (casi) lo que yo tenía pero en 2 líneas.

¡Así es Ruby!

Al final he hecho algún cambio y cogido lo bueno de uno y de otro y le he añadido soporte para STOPWORDS:

STOPWORDS = [
  'de','a','que','no','tiene','en','para',
  'por','le','la','lo','las','los','el',
  'una','un'
]
 
def to_slug( length = 64, drop_stopwords = false )
  return "" if self.length == 0
 
  str = Unicode.normalize_KD(self).gsub(/[^\x00-\x7F]/n,'').downcase
 
  # stopwords
  if drop_stopwords
    STOPWORDS.each do |stopword|
      str.gsub!( /\s#{stopword}\s|^#{stopword}\s/, ' ' )
    end
  end
 
  str = str.gsub(/[^A-Za-z0-9]/, '-').gsub(/^-+/,'').gsub(/-+$/,'').downcase
  str = str[0..length-1]
end

Por su puesto que se recomienda completar la lista de STOPWORDS con las que quieras.

16 Comments to “Ruby, sanitizando tus títulos en 2 líneas.”
  1. David Calavera Says:

    jajaja, de esas puedes encontrar unas cuantas en refactormycode.com. Una de las mejores que recuerdo fue, como parsear los parámetros de una url y meterlos en un hash, tras muchos comentarios de todo tipo por fin alguien llegó a esto:

    CGI.parse(URI.parse(url).query)

    XD

  2. fguillen Says:

    Buen link.. muy divertido :)

  3. Juanjo Bazán Says:

    Echale también un ojo al método normalize que te da Rails:
    http://api.rubyonrails.org/classes/ActiveSupport/Multibyte/Handlers/UTF8Handler.html#M000155

  4. YoNoSoyTu Says:

    No necesitas la gema de Unicode para ello si utilizas Rails, que viene con Unicode incorporado:

    ‘àéïôúñ’.chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, ”) # => “aeioun”

    (Es una dependencia menos)

  5. Andrés Panitsch Says:

    Podés pensar que tu función, aunque más larga, es clara para vos y por ello podés mantenerla y modificarla si alguna vez te da algún problema… si en alguna situación ese código de dos líneas no funciona la vas a ver de a cuadros.

    Me parece el camino acertado entender esas dos líneas y utilizarlas para mejorar tu código en vez de tomarlas a ciegas.

    Todo esto muy teórico porque si bien entiendo regular expressions (con lo cual imagino lo que hace) la sintaxis de ruby se me escapa completamente :-)

    Muy buen post!

  6. fguillen Says:

    Juanjo: thx.. a ver si se levanta api.rubyonrails.org para verlo

    Daniel (;P): cierto, lo he comprobado.

  7. fguillen Says:

    Andrés: Estoy contigo en que hay que anteponer lo auto-explicativo de un código a lo corto que sea.

  8. christos zisopoulos Says:

    Y ahora hay esto:

    http://github.com/rails/rails/commit/90366a1521659d07a3b75936b3231adeb376f1a4

  9. fguillen Says:

    christos demasiado tosco:

    ?> "hola! qué pasa con las ñÑññs y tal y cuál?".gsub(/[^a-z0-9]+/i, "-").downcase
    => "hola-qu-pasa-con-las-s-y-tal-y-cu-l-"

    El to_slug que tengo hace esto:

    >> "hola! qué pasa con las ñÑññs y tal y cuál?".to_slug
    => "hola-que-pasa-con-las-nnnns-y-tal-y-cual"

    Pero buscando en github me encuentro esto:
    http://github.com/ludo/to_slug/tree/master

    Que mola bastante.

  10. ceritium Says:

    Sin duda interesante el post y el hilo de comentarios, pero nadie ha dicho nada sobre lo positivo o negativo del uso de las stop words en el posicionamiento de una página.

    ¿Hasta que punto es interesante usarlas? A veces interesa posicionar por una frase concreta y no por palabras clave.

    ¿Como lo veis?

  11. fguillen Says:

    @ceritium: Yo dejo las stop-words en mis slugs. Si te sirve de opinión.

    Veo más sentido que sean obviadas por el propio indexador (en este caso google) pero los slugs me gustan más con la frase completa como tú dices.

  12. fguillen Says:

    También he encontrado esto:
    http://github.com/henrik/slugalizer/tree/master

  13. Rolando Says:

    If you desire to improve your knowledge only keep
    visiting this web site and be updated with the hottest news update posted here.

  14. Shelli Says:

    Thanks for sharing your info. I truly appreciate your efforts and I am waiting for your further
    post thanks once again.

  15. Pauline Says:

    whoah this weblog is excellent i love studying your articles.
    Keep up the great work! You understand, many individuals are searching round for this information, you can help them greatly.

  16. leptin resistance Says:

    An impressive share! I have just forwarded this onto a colleague who has been doing a little
    homework on this. And he in fact bought me breakfast simply because I found it for
    him… lol. So allow me to reword this…. Thanks
    for the meal!! But yeah, thanks for spending the time
    to discuss this issue here on your web page.

Leave a comment

a Freelance Web Developer is proudly powered by WordPress
Entries (RSS) and Comments (RSS).

Creative Commons License
Fernando Guillen's blog by Fernando Guillen is licensed under a Creative Commons Attribution-NoDerivs 3.0 Unported License.