Class: SubscriptionsManager

Inherits:
Object
  • Object
show all
Defined in:
lib/subscriptions_manager.rb

Overview

This class has methods related to managing users' subscriptions to feeds.

Class Method Summary collapse

Class Method Details

.add_subscription(feed, user) ⇒ Object

Add a new subscription of a user to a feed. The cached count of unread entries will be initialized to the current number of entries in the feed, thanks to various model callbacks.

Receives as arguments the suscribing user and the feed to which he's to be subscribed.

If the user is already subscribed to the feed, an AlreadySubscribedError is raised.


14
15
16
17
18
19
20
21
22
# File 'lib/subscriptions_manager.rb', line 14

def self.add_subscription(feed, user)
  check_user_unsubscribed feed, user

  Rails.logger.info "subscribing user #{user.id} - #{user.email} to feed #{feed.id} - #{feed.fetch_url}"
  feed_subscription = FeedSubscription.new feed_id: feed.id
  user.feed_subscriptions << feed_subscription

  return nil
end

.enqueue_unsubscribe_job(feed, user) ⇒ Object

Enqueue a job to unsubscribes a user from a feed.

Receives as argument the feed to unsubscribe, and the user who is unsubscribing.


49
50
51
52
53
54
55
56
57
58
59
# File 'lib/subscriptions_manager.rb', line 49

def self.enqueue_unsubscribe_job(feed, user)
  if !user_subscribed? feed, user
    Rails.logger.warn "User #{user.id} - #{user.id} tried to enqueue job to unsubscribe from feed #{feed.id} - #{feed.fetch_url} but he is not subscribed"
    raise NotSubscribedError.new
  end

  Rails.logger.info "Enqueuing unsubscribe job for user #{user.id} - #{user.email}, feed #{feed.id} - #{feed.fetch_url}"
  UnsubscribeUserWorker.perform_async user.id, feed.id

  return nil
end

.feed_decrement_count(feed, user, decrement = 1) ⇒ Object

Decrement the count of unread entries in a feed for a given user.

Receives as arguments:

  • feed which count will be decremented

  • user for which the count will be decremented

  • decrement: how much to decrement the count. Optional, has default value of 1.

If the user is not actually subscribed to the feed, a NotSubscribedError is raised.


117
118
119
# File 'lib/subscriptions_manager.rb', line 117

def self.feed_decrement_count(feed, user, decrement=1)
  self.feed_increment_count feed, user, -decrement
end

.feed_increment_count(feed, user, increment = 1) ⇒ Object

Increment the count of unread entries in a feed for a given user.

Receives as arguments:

  • feed which count will be incremented

  • user for which the count will be incremented

  • increment: how much to increment the count. Optional, has default value of 1.

If the user is not actually subscribed to the feed, a NotSubscribedError is raised.


93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/subscriptions_manager.rb', line 93

def self.feed_increment_count(feed, user, increment=1)
  if !user_subscribed? feed, user
    Rails.logger.warn "User #{user.id} - #{user.id} tried to change unread count for feed #{feed.id} - #{feed.fetch_url} but he is not subscribed"
    raise NotSubscribedError.new
  end

  feed_subscription = user.feed_subscriptions.find_by feed_id: feed.id
  Rails.logger.debug "Incrementing unread entries count for user #{user.id} - #{user.email}, feed #{feed.id} - #{feed.fetch_url}. Current: #{feed_subscription.unread_entries}, incremented by #{increment}"
  feed_subscription.unread_entries += increment
  feed_subscription.save!

  return nil
end

.feed_unread_count(feed, user) ⇒ Object

Retrieve the count of unread entries in a feed for a given user. This count is not calculated when this method is invoked, but rather it is retrieved from a pre-calculated field in the database.

Receives as arguments:

  • feed from which to retrieve the count

  • user for whom the unread entries count is to be retrieved

Returns a positive (or zero) integer with the count. If the user is not actually subscribed to the feed, a NotSubscribedError is raised.


73
74
75
76
77
78
79
80
81
# File 'lib/subscriptions_manager.rb', line 73

def self.feed_unread_count(feed, user)
  if !user_subscribed? feed, user
    Rails.logger.warn "User #{user.id} - #{user.id} tried to retrieve unread count from feed #{feed.id} - #{feed.fetch_url} but he is not subscribed"
    raise NotSubscribedError.new
  end

  feed_subscription = user.feed_subscriptions.find_by feed_id: feed.id
  return feed_subscription.unread_entries
end

.recalculate_unread_count(feed, user) ⇒ Object

Recalculate the count of unread entries in a feed for a given user.

This method counts the unread entries in the feed and updates the unread_entries field accordingly. It can be used to ensure the unread_entries field is correct.

Receives as arguments:

  • feed: feed for which the count will be recalculated.

  • user: user for whom the count will be recalculated.

Returns the recalculated count.

This method writes in the database only if necessary (i.e. the currently saved unread_entries does not match the calculated count). This avoids unnecessary database writes, which are expensive operations.


137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/subscriptions_manager.rb', line 137

def self.recalculate_unread_count(feed, user)
  Rails.logger.debug "Recalculating unread entries count for feed #{feed.id} - #{feed.title}, user #{user.id} - #{user.email}"
  count = EntryState.joins(entry: :feed).where(read: false, user: user, feeds: {id: feed.id}).count
  if user.feed_unread_count(feed) != count
    Rails.logger.debug "Unread entries count calculated: #{count}, current value #{user.feed_unread_count(feed)}. Updating DB record."
    feed_subscription = FeedSubscription.find_by user_id: user.id, feed_id: feed.id
    feed_subscription.update unread_entries: count
  else
    Rails.logger.debug "Unread entries count calculated: #{count}, current value is correct. No need to update DB record."
  end

  return count
end

.remove_subscription(feed, user) ⇒ Object

Unsubscribes a user from a feed.

Receives as argument the feed to unsubscribe, and the user who is unsubscribing.

If the user is not subscribed to the feed, a NotSubscribedError is raised.


31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/subscriptions_manager.rb', line 31

def self.remove_subscription(feed, user)
  if !user_subscribed? feed, user
    Rails.logger.warn "User #{user.id} - #{user.id} tried to unsubscribe from feed #{feed.id} - #{feed.fetch_url} but he is not subscribed"
    raise NotSubscribedError.new
  end

  feed_subscription = FeedSubscription.find_by feed_id: feed.id, user_id: user.id
  Rails.logger.info "unsubscribing user #{user.id} - #{user.email} from feed #{feed.id} - #{feed.fetch_url}"
  user.feed_subscriptions.delete feed_subscription

  return nil
end