Skip to content

Commit 89692ed

Browse files
Merge pull request #22 from gustavothecoder/refactor-feed-parser
Refactor `FeedParser` to use lambdas
2 parents 2a7275c + 6b1b5c1 commit 89692ed

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

lib/pod/infrastructure/feed_parser.rb

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,57 @@
44
require "feedjira"
55

66
require_relative "dto"
7+
require_relative "function_pipeline"
78

89
module Infrastructure
910
module FeedParser
1011
def self.call(feed)
12+
pipeline = FunctionPipeline.new(
13+
functions: [
14+
FetchContent,
15+
ParseContent,
16+
InitializePodcastDTO,
17+
InitializeEpisodesDTO,
18+
InitializeFeedDTO
19+
],
20+
on_error: InitializeEmptyFeedDTO,
21+
context: {feed: feed}
22+
)
23+
24+
pipeline.call
25+
end
26+
27+
private
28+
29+
FetchContent = ->(ctx) do
30+
feed = ctx[:feed]
31+
1132
content = if File.exist?(feed)
1233
File.new(feed).read
1334
else
1435
Net::HTTP.get(URI(feed))
1536
end
16-
parsed_content = Feedjira.parse(content)
1737

18-
podcast = Infrastructure::DTO.new(
38+
ctx[:content] = content
39+
end
40+
41+
ParseContent = ->(ctx) do
42+
ctx[:parsed_content] = Feedjira.parse(ctx[:content])
43+
end
44+
45+
InitializePodcastDTO = ->(ctx) do
46+
parsed_content = ctx[:parsed_content]
47+
ctx[:podcast] = Infrastructure::DTO.new(
1948
name: parsed_content.title,
2049
description: parsed_content.description,
2150
feed: parsed_content.itunes_new_feed_url,
2251
website: parsed_content.url
2352
)
53+
end
2454

25-
episodes = parsed_content.entries.map do |e|
55+
InitializeEpisodesDTO = ->(ctx) do
56+
parsed_content = ctx[:parsed_content]
57+
ctx[:episodes] = parsed_content.entries.map do |e|
2658
Infrastructure::DTO.new(
2759
title: e.title,
2860
release_date: e.published.iso8601,
@@ -31,11 +63,17 @@ def self.call(feed)
3163
external_id: e.entry_id
3264
)
3365
end
66+
end
3467

68+
InitializeFeedDTO = ->(ctx) do
69+
podcast = ctx[:podcast]
70+
episodes = ctx[:episodes]
3571
# The #reverse is necessary to put the oldest episodes on the top of the feed.
36-
Infrastructure::DTO.new(podcast: podcast, episodes: episodes.reverse)
37-
rescue NoMethodError
38-
Infrastructure::DTO.new(podcast: nil, episodes: nil)
72+
ctx[:feed] = Infrastructure::DTO.new(podcast: podcast, episodes: episodes.reverse)
73+
end
74+
75+
InitializeEmptyFeedDTO = ->(ctx) do
76+
ctx[:feed] = Infrastructure::DTO.new(podcast: nil, episodes: nil)
3977
end
4078
end
4179
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
module Infrastructure
4+
class FunctionPipeline
5+
def initialize(functions:, on_error:, context: {})
6+
@functions = functions
7+
@on_error = on_error
8+
@context = Context.new(context)
9+
end
10+
11+
def call
12+
@functions.each { |f| f.call(@context) }
13+
rescue => e
14+
@context[:error] = e
15+
@on_error.call(@context)
16+
ensure
17+
return @context.last_entry # standard:disable Lint/EnsureReturn
18+
end
19+
20+
private
21+
22+
class Context
23+
def initialize(context)
24+
@state = context
25+
end
26+
27+
def [](key)
28+
@state[key.to_sym]
29+
end
30+
31+
def []=(key, value)
32+
@state[key.to_sym] = value
33+
@state[:last_entry] = key
34+
end
35+
36+
def last_entry
37+
key = @state[:last_entry]
38+
@state[key]
39+
end
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)