ruby-on-rails - method - routes in ruby on rails
La mejor manera de generar slugs(IDs legibles por humanos) en Rails (12)
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.
Lo transcrito transforma cosas como é, á, ô en e, a, o. Como estoy desarrollando un sitio en portugués, eso importa.
Ya sabes, como myblog.com/posts/donald-e-knuth.
¿Debo hacer esto con el método incorporado de parameterize
?
¿Qué pasa con un plugin? Me podría imaginar que un complemento sea bueno para manejar slugs duplicados, etc. Aquí hay algunos complementos populares de Github. ¿Alguien tiene alguna experiencia con ellos?
Básicamente, parece que las babosas son un problema totalmente resuelto, y no reinventar la rueda.
Descubrí que la gema Unidecode era demasiado pesada, cargando casi 200 archivos YAML, para lo que necesitaba. Sabía que iconv
tenía algo de apoyo 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.
El principal problema para mis aplicaciones ha sido los apóstrofes: rara vez quieres que los -s estén ahí solos.
class String
def to_slug
self.gsub(/[''`]/, "").parameterize
end
end
Esto es lo que yo 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 existe el mismo, no será el nombre 01 o algo así.
Ejemplo:
".downcase.gsub(/[^a-z1-9]+/, ''-'').chomp(''-'')".downcase.gsub(/[^a-z1-9]+/, ''-'').chomp(''-'')
Salidas: -downcase-gsub-a-z1-9-chomp
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.
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 hablar de cubrir todos los idiomas europeos (incluidos los dialectos locales). Garantiza una creación de balas a prueba de balas.
Por ejemplo, considera esos:
"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.
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
Recientemente tuve el mismo dilema.
Como, como usted, no quiero reinventar la rueda, elegí friendly_id siguiendo la comparación en The Ruby Toolbox: Rails Permalinks & Slugs .
Basé mi decisión en:
- número de observadores de github
- no. de tenedores de github
- cuando fue el ultimo cometido
- no. de descargas
Espero que esto ayude a tomar la decisión.
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 usted guarda información redundante que ya está allí. Si lo piensas bien, no hay razón para salvar a la babosa. La bala debe ser lógica, no datos.
Escribí un post siguiendo este razonamiento, y la esperanza es de alguna ayuda.
Utilizamos to_slug http://github.com/ludo/to_slug/tree/master
. Hace todo lo que necesitamos que haga (escapar de ''personajes funky''). Espero que esto ayude.
EDIT: Parece estar rompiendo mi enlace, lo siento por eso.
Yo uso lo siguiente, que será
- traducir & -> "y" y @ -> "en"
- no inserta un guión bajo en lugar de un apóstrofe, así que "foo''s" -> "foos"
- no incluye dobles guiones bajos
- no crea una babosa que comienza o termina con un guión bajo
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"