15 minute fix: Shorten long titles from feed items if needed (#13961)
* Shorten long titles from feed items if needed Fixes #13959 When the title is too long to create a valid article, put a shortened title in the generated article markdown. Added unit tests to cover the default case and the shortening case * Fix Struct initialization Rubocop suggested struct over openstruct because of performance, but Struct.new creates a "class" with a positional initializer, while Openstruct's new takes a hash like keyword set and builds an object from those directly. I mistakenly reused the openstruct syntax after the conversion. This changes the feed and item to use Struct's initializer. * Use String#truncate in place of custom trimming `separator` enables a natural break (preventing space between last character and ellipsis), and omission text "..." is the default behavior. * Use verifying doubles in test, use method access to members in code The instance_double for Feedjira::Parser::RSSEntry necessitated changing hash key access to reader method access for the data members (title, categories, summary, description).
This commit is contained in:
parent
26592a3a9c
commit
b4ce4ec975
2 changed files with 58 additions and 4 deletions
|
|
@ -6,8 +6,8 @@ module Feeds
|
|||
|
||||
def initialize(item, user, feed, feed_source_url)
|
||||
@item = item
|
||||
@title = item[:title].strip
|
||||
@categories = item[:categories] || []
|
||||
@title = item.title.strip
|
||||
@categories = item.categories || []
|
||||
@user = user
|
||||
@feed = feed
|
||||
@feed_source_url = feed_source_url
|
||||
|
|
@ -16,7 +16,7 @@ module Feeds
|
|||
def call
|
||||
body = <<~HEREDOC
|
||||
---
|
||||
title: #{@title}
|
||||
title: #{processed_title}
|
||||
published: false
|
||||
date: #{@item.published}
|
||||
tags: #{get_tags}
|
||||
|
|
@ -31,6 +31,10 @@ module Feeds
|
|||
|
||||
private
|
||||
|
||||
def processed_title
|
||||
@title.truncate(128, omission: "...", separator: " ")
|
||||
end
|
||||
|
||||
def get_tags
|
||||
@categories.first(4).map do |tag|
|
||||
tag.delete(" ").gsub(/[^[:alnum:]]/i, "")[0..19]
|
||||
|
|
@ -54,7 +58,7 @@ module Feeds
|
|||
end
|
||||
|
||||
def get_content
|
||||
@item[:content] || @item[:summary] || @item[:description]
|
||||
@item.content || @item.summary || @item.description
|
||||
end
|
||||
|
||||
def thorough_parsing(content, feed_url)
|
||||
|
|
|
|||
50
spec/services/feeds/assemble_article_markdown_spec.rb
Normal file
50
spec/services/feeds/assemble_article_markdown_spec.rb
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Feeds::AssembleArticleMarkdown, type: :service do
|
||||
let(:user) { create(:user, feed_mark_canonical: true) }
|
||||
let(:feed_source_url) { "https://feed.source/url" }
|
||||
let(:feed) { instance_double("Feedjira::Parser::RSS", url: "https://feed.source/") }
|
||||
let(:title) { "A title" }
|
||||
let(:content) { "Some content that came in with the item, should be the body" }
|
||||
|
||||
let(:item) do
|
||||
instance_double(
|
||||
"Feedjira::Parser::RSSEntry",
|
||||
title: title,
|
||||
categories: %w[tag1 tag2 tag3 tag4 tag5],
|
||||
published: "2020-12-20",
|
||||
content: content,
|
||||
)
|
||||
end
|
||||
|
||||
let(:feeds_assemble_article_markdown) { described_class.new(item, user, feed, feed_source_url) }
|
||||
|
||||
it "creates markdown head matter" do
|
||||
body = feeds_assemble_article_markdown.call
|
||||
|
||||
expect(body).to include("title: A title")
|
||||
expect(body).to include("date: 2020-12-20")
|
||||
end
|
||||
|
||||
it "includes the content from the feed" do
|
||||
body = feeds_assemble_article_markdown.call
|
||||
|
||||
expect(body).to include(content)
|
||||
end
|
||||
|
||||
context "when item has a long title" do
|
||||
let(:title) { "Words " * 25 }
|
||||
|
||||
it "limits the title to 128 characters by truncation" do
|
||||
body = feeds_assemble_article_markdown.call
|
||||
|
||||
title_line = body.lines.detect { |line| line.starts_with?("title:") }
|
||||
shortened_title = title_line.split(":").second.strip
|
||||
# we expect 21 "Words" plus an ellipsis, total of 128 characters
|
||||
expected_title = "Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words Words..." # rubocop:disable Layout/LineLength
|
||||
|
||||
expect(shortened_title.size).to eq(128)
|
||||
expect(shortened_title).to eq(expected_title)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue