Rails: Умение интеллектуального текста

Интересно, есть ли плагин для включения своего рода умного усечения. Мне нужно урезать текст с точностью слова или предложения.

Например:

Post.my_message.smart_truncate(
 "Once upon a time in a world far far away. And they found that many people
 were sleeping better.", :sentences => 1)
# => Once upon a time in a world far far away.

или

Post.my_message.smart_truncate(
 "Once upon a time in a world far far away. And they found that many people
 were sleeping better.", :words => 12)
# => Once upon a time in a world far far away. And they ...
5 ответов

Я не видел такого плагина, но был похожий вопрос, который мог бы послужить основой для lib или вспомогательной функции.

То, как вы показываете функцию, похоже, ставит ее как расширение для String: если вы действительно не захотите сделать это за пределами представления, я бы склонен перейти к функции в application_helper.rb. Что-то вроде этого, возможно?

module ApplicationHelper
 def smart_truncate(s, opts = {})
 opts = {:words => 12}.merge(opts)
 if opts[:sentences]
 return s.split(/\.(\s|$)+/)[0, opts[:sentences]].map{|s| s.strip}.join('. ') + '.'
 end
 a = s.split(/\s/) # or /[ ]+/ to only split on spaces
 n = opts[:words]
 a[0...n].join(' ') + (a.size > n ? '...' : '')
 end
end
smart_truncate("a b c. d e f. g h i.", :sentences => 2) #=> "a b c. d e f."
smart_truncate("apple ********* cherry plum", :words => 3) #=> "apple ********* cherry..."


Это будет усекаться на границе слова на основе указанной длины char_limit. Поэтому он не усекает предложение в странных местах

def smart_truncate(text, char_limit)
 size = 0
 text.split().reject do |token|
 size += token.size() + 1
 size > char_limit
 end.join(' ') + ( text.size() > char_limit ? ' ' + '...' : '' )
end


Драгоценный камень truncate_html выполняет эту работу. Он также может пропускать фрагменты HTML, что может быть очень полезно, и дает возможность настраивать регулярное выражение границы слова. Кроме того, по умолчанию для всех параметров можно настроить, например, в config/environment.rb.

Пример:

some_html = '<ul><li><a href="http://whatever">This is a link</a></li></ul>'
truncate_html(some_html, :length => 15, :omission => '...(continued)')
=> <ul><li><a href="http://whatever">This...(continued)</a></li></ul>


Работая некоторое время с некоторыми обновлениями с разными проектами, я придумал эти усовершенствования кода, которые выглядят гораздо более полезными в реальных сценариях.

def smart_truncate_characters(text, char_limit)
 text = text.to_s
 text = text.squish
 size = 0
 new_text = text.mb_chars.split().reject do |token|
 size+=token.size()
 size>char_limit
 end.join(" ")
 if size > char_limit
 return new_text += '…'
 else
 return new_text
 end
end
def smart_truncate_sentences(text, sentence_limit)
 text = text.to_s
 text = text.squish
 size = 0
 arr = text.mb_chars.split(/(?:\.|\?|\!)(?= [^a-z]|$)/)
 arr = arr[0...sentence_limit]
 new_text = arr.join(".")
 new_text += '.'
end
def smart_truncate(text, sentence_limit, char_limit)
 text = smart_truncate_sentences(text, sentence_limit)
 text = smart_truncate_characters(text, char_limit)
end


Хороший помощник. Поскольку у меня был другой опыт, я изменил его так, что он останавливается на последнем слове и работает с лимитом символов. Я думаю, что это гораздо более реальный сценарий в большинстве приложений.

Обновление: взял код выше и немного обновил его. Казалось гораздо более приятным подходом для старого рубина и работает с utf8.

def smart_truncate(text, char_limit)
 text = text.squish
 size = 0
 text.mb_chars.split().reject do |token|
 size+=token.size()
 size>char_limit
 end.join(" ")
end

licensed under cc by-sa 3.0 with attribution.