rails:obtener un teaser/extracto de un artículo
-
22-08-2019 - |
Pregunta
Tengo una página que lista los artículos de noticias.Para cortar hacia abajo en la página de longitud, sólo quiero mostrar un teaser (las primeras 200 palabras / 600 cartas del artículo) y, a continuación, mostrar un "más...", la que, cuando se hace clic, se expanda al resto del artículo en jQuery/Javascript manera.Ahora, todo lo que he averiguado y aún encontrado el siguiente método auxiliar en un poco de pasta de página, que se asegurará de que el artículo de las noticias (la cadena) no está cortado a la derecha en el medio de una palabra:
def shorten (string, count = 30)
if string.length >= count
shortened = string[0, count]
splitted = shortened.split(/\s/)
words = splitted.length
splitted[0, words-1].join(" ") + ' ...'
else
string
end
end
El problema que tengo es que el artículo de las noticias de los cuerpos que puedo obtener de la base de datos tienen el formato HTML.Así que si estoy de mala suerte, por encima de la auxiliar va a despedazar mi artículo de la cadena de la derecha en el medio de una etiqueta html e insertar el "más..." de la cadena de allí (por ejemplo,entre ""), que se corrompe mi código html de la página.
¿Hay alguna forma de evitar esto o es que hay un plugin que me pueda usar para generar fragmentos/teasers de una cadena HTML?
Solución 3
Muchas gracias por sus respuestas! Sin embargo, en el ínterin me topé con la jQuery HTML truncador Plugin , que se adapta perfectamente a mis propósitos y desplaza el truncamiento para el lado del cliente. No hay nada más fácil: -)
Otros consejos
Puede utilizar una combinación de Desinfección y Truncar .
truncate("And they found that many people were sleeping better.",
:omission => "... (continued)", :length => 15)
# => And they found... (continued)
Me estoy haciendo una tarea similar en el que tengo entradas de blog y sólo quiero mostrar un extracto rápido. Así que en mi opinión, lo hago simplemente:
sanitize(truncate(blog_post.body, length: 150))
que despoja a las etiquetas HTML, me da los primeros 150 caracteres y se maneja en la vista de lo que es MVC usar.
Buena suerte!
Mi respuesta aquí debe hacer el trabajo. La pregunta original (err, se le preguntó por mí) estaba a punto de truncar reducción del precio, pero terminó por convertir la reducción del precio a HTML entonces truncando que, por lo que debería funcionar.
Por supuesto, si su sitio se vuelve mucho tráfico, debería almacenar en caché el fragmento (tal vez cuando se creó el cargo / modificada, se puede almacenar el extracto en la base de datos?), Esto también significaría que podría permitir al usuario modificar o entrar en su propio extracto
Uso:
>> puts "<p><b><a href=\"hi\">Something</a></p>".truncate_html(5, at_end = "...")
=> <p><b><a href="hi">Someth...</a></b></p>
.. y el código (copiado de la otra respuesta):
require 'rexml/parsers/pullparser'
class String
def truncate_html(len = 30, at_end = nil)
p = REXML::Parsers::PullParser.new(self)
tags = []
new_len = len
results = ''
while p.has_next? && new_len > 0
p_e = p.pull
case p_e.event_type
when :start_element
tags.push p_e[0]
results << "<#{tags.last}#{attrs_to_s(p_e[1])}>"
when :end_element
results << "</#{tags.pop}>"
when :text
results << p_e[0][0..new_len]
new_len -= p_e[0].length
else
results << "<!-- #{p_e.inspect} -->"
end
end
if at_end
results << "..."
end
tags.reverse.each do |tag|
results << "</#{tag}>"
end
results
end
private
def attrs_to_s(attrs)
if attrs.empty?
''
else
' ' + attrs.to_a.map { |attr| %{#{attr[0]}="#{attr[1]}"} }.join(' ')
end
end
end
tendría que escribir más complejos programas de análisis si no desea dividir en medio de los elementos HTML. tendría que recordar si se encuentra en medio de un bloque <> y si su entre dos etiquetas.
incluso si lo hizo, a pesar de ello tener problemas. si algunos ponen todo el artículo en un elemento HTML, ya que el analizador no podría dividirse en cualquier lugar, debido a la falta etiqueta de cierre.
si es posible en absoluto me gustaría tratar de no poner ninguna etiqueta en los artículos o mantenerlo a las etiquetas que No contiene nada (sin <div>
y así sucesivamente). de esa manera usted sólo tiene que comprobar si se encuentra en medio de una etiqueta que es bastante simple:
def shorten (string, count = 30)
if string.length >= count
shortened = string[0, count]
splitted = shortened.split(/\s/)
words = splitted.length
if(splitted[words-1].include? "<")
splitted[0,words-2].join(" ") + ' ...'
else
splitted[0, words-1].join(" ") + ' ...'
else
string
end
end
Me hubiera saneado el código HTML y extrae la primera frase. Asumiendo que tiene un modelo de artículo, con un atributo de 'cuerpo' que contiene el código HTML:
# lib/core_ext/string.rb
class String
def first_sentence
self[/(\A[^.|!|?]+)/, 1]
end
end
# app/models/article.rb
def teaser
HTML::FullSanitizer.new.sanitize(body).first_sentence
end
Esto convertiría a " es un importante artículo! Y aquí está el resto del artículo." en "Este es un artículo importante".
Lo resuelto utilizando la siguiente solución
Instalar la gema 'desinfectar'
gem install sanitize
y utiliza código siguiente, aquí cuerpo es el texto que contiene etiquetas html.
<%= content_tag :div, Sanitize.clean(truncate(body, length: 200, separator: ' ', omission: "... #{ link_to '(continue)', '#' }"), Sanitize::Config::BASIC).html_safe %>
Da fragmento de código html válido.Espero que ayude a alguien.
En la actualidad existe una joya llamada HTMLTruncator que se encarga de esto para usted. Lo he utilizado para mostrar extractos de entradas y similares, y es muy robusto.