๐Ÿ“ฆ obafemitayor / newsletter-subscription-application

๐Ÿ“„ subscription.rb ยท 59 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59class Subscription < ApplicationRecord
  # Soft delete
  scope :active, -> { where(deleted_at: nil) }

  FETCH_SUBSCRIPTIONS = lambda do |limit:, category_guids: nil, pagination_id: nil, pagination_direction: 'forward'|
    query = active
            .joins(:customer, :category)
            .select(
              'customers.id as customer_id',
              'customers.work_email',
              'customers.first_name',
              'customers.last_name',
              'GROUP_CONCAT(categories.name) as category_names'
            )
            .group(
              'customers.id',
              'customers.work_email',
              'customers.first_name',
              'customers.last_name'
            )

    query = query.where(categories: { guid: category_guids }) if category_guids.present?

    # using cursor-based pagination because it is more efficient and
    # scales better with large data sets than offset-based pagination
    if pagination_id.present?
      query = query.where(
        pagination_direction == 'forward' ? 'customers.id > ?' : 'customers.id < ?',
        pagination_id
      )
    end

    query.order("customers.id #{pagination_direction == 'forward' ? 'ASC' : 'DESC'}")
         .limit(limit)
  end

  scope :fetch_subscriptions, FETCH_SUBSCRIPTIONS

  # Relationships
  belongs_to :customer
  belongs_to :category

  # Validations
  validates :customer_id, uniqueness: { scope: :category_id }

  # Instance methods
  def soft_delete
    update(deleted_at: Time.current)
  end

  def restore
    update(deleted_at: nil)
  end

  def deleted?
    deleted_at.present?
  end
end