La mejor manera de generar slugs (ID legibles por humanos) en Rails


Ya sabes, como myblog.com/posts/donald-e-knuth.

¿Debería hacer esto con el método incorporado parameterize ?

¿Qué pasa con un plugin? Me imagino que un plugin es agradable para el manejo de slugs duplicados, etc. Aquí hay algunos plugins de Github populares does ¿alguien tiene alguna experiencia con ellos?

  1. http://github.com/rsl/stringex/tree/master
  2. http://github.com/norman/friendly_id/tree/master

Básicamente parece que las babosas son un problema totalmente resuelto, y no lo hago para reinventar la rueda.

Author: Community, 2009-08-19

12 answers

Utilizo lo siguiente, que

  • traducir & --> "y" y @ --> "en"
  • no inserta un subrayado en lugar de un apóstrofo, por lo que "foo's" > > "foos"
  • no incluye guiones bajos dobles
  • no crea slug que comienza o termina con un subrayado

  def to_slug
    #strip the string
    ret = self.strip

    #blow away apostrophes
    ret.gsub! /['`]/,""

    # @ --> at, and & --> and
    ret.gsub! /\s*@\s*/, " at "
    ret.gsub! /\s*&\s*/, " and "

    #replace all non alphanumeric, underscore or periods with underscore
     ret.gsub! /\s*[^A-Za-z0-9\.\-]\s*/, '_'  

     #convert double underscores to single
     ret.gsub! /_+/,"_"

     #strip off leading/trailing underscore
     ret.gsub! /\A[_\.]+|[_\.]+\z/,""

     ret
  end

Así, por ejemplo:


>> s = "mom & dad @home!"
=> "mom & dad @home!"
>> s.to_slug
> "mom_and_dad_at_home"
 36
Author: klochner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-19 19:35:59

En Rails se puede usar # parametrizar

Por ejemplo:

> "Foo bar`s".parameterize 
=> "foo-bar-s"
 205
Author: grosser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-15 12:24:41

La mejor manera de generar slugs es usar la gema Unidecode. Tiene, con mucho, la mayor base de datos de transliteración disponible. Tiene incluso transliteraciones para caracteres chinos. Por no mencionar que abarca todas las lenguas europeas (incluidos los dialectos locales). Garantiza una creación de babosas a prueba de balas.

Por ejemplo, considere los siguientes:

"Iñtërnâtiônàlizætiøn".to_slug
=> "internationalizaetion"

>> "中文測試".to_slug
=> "zhong-wen-ce-shi"

Lo uso en mi versión del método String.to_slug en mi complemento ruby_extensions. Ver ruby_extensions.rb para el método to_slug.

 50
Author: Paweł Gościcki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-24 17:19:30

Esto es lo que uso:

class User < ActiveRecord::Base
  before_create :make_slug
  private

  def make_slug
    self.slug = self.name.downcase.gsub(/[^a-z1-9]+/, '-').chomp('-')
  end
end

Bastante autoexplicativo, aunque el único problema con esto es que si ya hay el mismo, no será name-01 o algo así.

Ejemplo:

".downcase.gsub(/[^a-z1-9]+/, '-').chomp('-')".downcase.gsub(/[^a-z1-9]+/, '-').chomp('-')

Salidas: -downcase-gsub-a-z1-9-chomp

 9
Author: Garrett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-19 19:15:56

Lo modifiqué un poco para crear guiones en lugar de guiones bajos, si alguien está interesado:

def to_slug(param=self.slug)

    # strip the string
    ret = param.strip

    #blow away apostrophes
    ret.gsub! /['`]/, ""

    # @ --> at, and & --> and
    ret.gsub! /\s*@\s*/, " at "
    ret.gsub! /\s*&\s*/, " and "

    # replace all non alphanumeric, periods with dash
    ret.gsub! /\s*[^A-Za-z0-9\.]\s*/, '-'

    # replace underscore with dash
    ret.gsub! /[-_]{2,}/, '-'

    # convert double dashes to single
    ret.gsub! /-+/, "-"

    # strip off leading/trailing dash
    ret.gsub! /\A[-\.]+|[-\.]+\z/, ""

    ret
  end
 6
Author: Victor S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-10 05:55:51

El principal problema para mis aplicaciones han sido los apóstrofes - rara vez quieres que los-s se sientan por su cuenta.

class String

  def to_slug
    self.gsub(/['`]/, "").parameterize
  end

end
 6
Author: Mark Swardstrom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-30 22:39:23

La gema Unidecoder no se ha actualizado desde 2007.

Recomiendo la gema stringex, que incluye la funcionalidad de la gema Unidecoder.

Https://github.com/rsl/stringex

Mirando su código fuente, parece volver a empaquetar el código fuente de Unidecoder y agregar una nueva funcionalidad.

 4
Author: Tilo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-30 14:23:05

Usamos to_slug http://github.com/ludo/to_slug/tree/master. Hace todo lo que necesitamos hacer (escapar de 'personajes funky'). Espero que esto ayude.

EDITAR: Parece estar rompiendo mi enlace, lo siento.

 3
Author: theIV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-19 19:41:15

Recientemente tuve el mismo dilema.

Ya que, como tú, no quiero reinventar la rueda, elegí friendly_id siguiendo la comparación en La caja de herramientas de Ruby: Rails Permalinks & Slugs .

Basé mi decisión en:

  • número de observadores de github
  • no. de bifurcaciones de github
  • cuándo se realizó la última confirmación
  • no. de descargas

Espero que esto ayude a tomar la decisión.

 3
Author: Marius Butuc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-19 17:52:26

Encontré que la gema Unidecode era demasiado pesada, cargando casi 200 archivos YAML, para lo que necesitaba. Sabía que iconv tenía cierto soporte para las traducciones básicas, y aunque no es perfecto, está integrado y es bastante ligero. Esto es lo que se me ocurrió:

require 'iconv' # unless you're in Rails or already have it loaded
def slugify(text)
  text.downcase!
  text = Iconv.conv('ASCII//TRANSLIT//IGNORE', 'UTF8', text)

  # Replace whitespace characters with hyphens, avoiding duplication
  text.gsub! /\s+/, '-'

  # Remove anything that isn't alphanumeric or a hyphen
  text.gsub! /[^a-z0-9-]+/, ''

  # Chomp trailing hyphens
  text.chomp '-'
end

Obviamente, probablemente debería agregarlo como un método de instancia en cualquier objeto en el que lo esté ejecutando, pero para mayor claridad, no lo hice.

 2
Author: coreyward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-16 01:49:17

Con Rails 3, he creado un inicializador, slug.rb, en el que he puesto el siguiente código:

class String
  def to_slug
    ActiveSupport::Inflector.transliterate(self.downcase).gsub(/[^a-zA-Z0-9]+/, '-').gsub(/-{2,}/, '-').gsub(/^-|-$/, '')
  end
end

Luego lo uso en cualquier lugar que desee en el código, se define para cualquier cadena.

El transliterado transforma cosas como é,á,ô en e,a,o. Como estoy desarrollando un sitio en portugués, eso importa.

 0
Author: Thiago Ganzarolli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-15 21:20:37

Sé que esta pregunta tiene algún tiempo ahora. Sin embargo, veo algunas respuestas relativamente nuevas.

Guardar el slug en la base de datos es problemático, y guarda información redundante que ya está allí. Si lo piensas, no hay razón para salvar la bala. La bala debe ser lógica, no datos.

Escribí un post siguiendo este razonamiento, y la esperanza es de alguna ayuda.

Http://blog.ereslibre.es/?p=343

 -2
Author: ereslibre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-16 14:20:34