ruby on rails - sistemas - rails: obtener un adelanto/extracto de un artículo
sistema de recomendacion tesis (7)
Tengo una página que enumerará artículos de noticias. Para reducir la longitud de la página, solo quiero mostrar un avance (las primeras 200 palabras / 600 letras del artículo) y luego mostrar un enlace "más ..." que, al hacer clic, expandirá el resto del artículo en una forma jQuery / Javascript. Ahora, tengo todo lo que descubrí e incluso encontré el siguiente método de ayuda en una página de pegar, lo que asegurará que el artículo de noticias (cadena) no se recorta justo 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 los cuerpos de los artículos de noticias que obtengo de la BD tienen formato HTML. Entonces, si no tengo suerte, el asistente anterior cortará mi cadena de artículos justo en el medio de una etiqueta html e insertará la cadena "más ..." allí (por ejemplo, entre ""), lo que dañará mi html en la página .
¿Hay alguna forma de evitar esto o hay un complemento que pueda usar para generar extractos / avances de una cadena HTML?
¡Muchas gracias por sus respuestas! Sin embargo, mientras tanto me encontré con el complemento jQuery HTML Truncator , que se adapta perfectamente a mis propósitos y cambia el truncamiento al lado del cliente. No se pone más fácil :-)
Tendría que escribir un analizador sintáctico más complejo si no desea dividirlo en el medio de los elementos html. Tendría que recordar si está en el medio de un bloque <> y si está entre dos etiquetas.
incluso si lo hicieras, aún tendrías problemas. si algunos ponen el artículo completo en un elemento html, ya que el analizador no pudo dividirlo en ningún lado, debido a la etiqueta de cierre faltante.
si es posible, trataría de no poner etiquetas en los artículos o mantenerlas en etiquetas que no contengan nada (ni <div>
etc.). De esa manera solo tendrías que verificar si estás en el 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
Hubiera esterilizado el HTML y extraje la primera oración. Suponiendo que tiene un modelo de artículo, con un atributo ''cuerpo'' que contiene el 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 "<b> Este </ b> es un artículo <em> importante </ em>! Y aquí está el resto del artículo". en "Este es un artículo importante".
Lo solucioné usando la siguiente solución
Instalar gema ''desinfectar''
gem install sanitize
y usado el siguiente código, aquí el cuerpo es 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 extracto con html válido Espero que ayude a alguien.
Ahora hay una gema llamada HTMLTruncator que se ocupa de esto por ti. Lo he usado para mostrar extractos de publicaciones y similares, y es muy robusto.
Puede usar una combinación de Sanitize y Truncate .
truncate("And they found that many people were sleeping better.",
:omission => "... (continued)", :length => 15)
# => And they found... (continued)
Estoy haciendo una tarea similar donde tengo publicaciones de blog y solo quiero mostrar un extracto rápido. Entonces, en mi opinión, simplemente lo hago:
sanitize(truncate(blog_post.body, length: 150))
Eso elimina las etiquetas HTML, me da los primeros 150 caracteres y se maneja en la vista para que sea amigable con MVC.
¡Buena suerte!
Mi respuesta aquí debería hacer el trabajo. La pregunta original (error, preguntada por mí) fue sobre truncar el descuento, pero terminé convirtiendo el descuento en HTML y luego truncar eso, por lo que debería funcionar.
Por supuesto, si su sitio recibe mucho tráfico, debe almacenar en caché el fragmento (¿quizás cuando se crea / actualiza la publicación, puede almacenar el extracto en la base de datos?), Esto también significa que podría permitir que el usuario modifique o ingrese 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