Fernando Guillén

un Desarrollador Web Freelance

cabecera decorativa

nada por aquí y nada por allá ó el desarrollo de software como expresión artística.

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.

12 Comentarios 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

Deja un Comentario

un Desarrollador Web Freelance is proudly powered by WordPress
Entries (RSS) and Comments (RSS).