module Feedzirra module FeedUtilities UPDATABLE_ATTRIBUTES = %w(title feed_url url last_modified) attr_writer :updated, :last_modified, :entries attr_accessor :etag def initialize @entries = [] super end def last_modified @last_modified ||= begin entry = entries.reject {|e| e.published.nil? }.sort_by { |entry| entry.published if entry.published }.last entry ? entry.published : nil end end [ :old, :new ].each do |flag| define_method("mark_all_entries_#{flag}!") do # def mark_all_entries_new! @entries.each{ |e| e.__send__(:"mark_#{flag}!") } # @entries.each {|e| e.mark_new! } end # end end def updated? @updated end def new_entries @entries.select{ |e| e.new_entry? } end def has_new_entries? new_entries.size > 0 end def update_from_feed(feed) # Mark all existing entries as old, then add new entries, which are # marked as new by default. self.entries.each{|e| e.mark_old! } find_new_entries_for(feed).each do |e| self.entries << e end updated! if UPDATABLE_ATTRIBUTES.any? { |name| update_attribute(feed, name) } end def update_attribute(feed, name) old_value, new_value = send(name), feed.send(name) if old_value != new_value send("#{name}=", new_value) end end def sanitize_entries! entries.each {|entry| entry.sanitize!} end private def updated! @updated = true end def find_new_entries_for(feed) # This implementation is a hack to get around the fact that not all feeds # have a published date - we exploit the fact that feeds are always # ordered with newest element first to work backwards until we reach feed urls # that we've already seen. feed.entries.reverse.inject([]) do |res, entry| break res if entry.url == self.entries.first.url res << entry end end def existing_entry?(test_entry) entries.any? { |entry| entry.url == test_entry.url } end end end