podia/counter

Refactor the conditional counters to make it easier to write

ideasasylum opened this issue · 2 comments

This sort of thing is tedious, ugly, and error-prone:

  conditional create: ->(student) { student.subscribed? && student.confirmed? },
    delete: ->(student) { student.subscribed? && student.confirmed? },
    update: ->(student) {
      became_subscribed = student.has_changed? :subscribed_at,
        from: nil,
        to: Counter::Any
      return 1 if became_subscribed

      became_unsubscribed = student.has_changed? :subscribed_at,
        from: Counter::Any,
        to: nil
      return -1 if became_unsubscribed

      became_confirmed = student.has_changed? :confirmed,
        from: false,
        to: true
      return 1 if became_confirmed

      became_unconfirmed = student.has_changed? :confirmed,
        from: true,
        to: false
      return -1 if became_unconfirmed

      return 0
    }

I was wondering about something like:

on_create :increment, if: ->(student) { student.subscribed? && student.confirmed? }
on_delete :decrement, if: ->(student) { student.subscribed? && student.confirmed? }
on_update :increment, if: ->(student) { student.has_changed? :subscribed_at, from: nil, to: Counter::Any }
on_update :increment, if: ->(student) { student.has_changed? :confirmed, from: false, to: true }
on_update :decrement, if: ->(student) { student.has_changed? :subscribed_at, from: Counter::Any, to: nil }
on_update :increment, if: ->(student) { student.has_changed? :confirmed, from: true, to: false }

i.e., be explicit about increment/decrement so we don't need to return numbers, and allow multiple checks for update.

???

increment_on_create_if ->(student) { student.subscribed? && student.confirmed? }
decrement_on_delete_if, ->(student) { student.subscribed? && student.confirmed? }
increment_on_update_if ->(student) { student.has_changed? :subscribed_at, from: nil, to: Counter::Any }
increment_on_update_if ->(student) { student.has_changed? :confirmed, from: false, to: true }
decrement_on_update_if: ->(student) { student.has_changed? :subscribed_at, from: Counter::Any, to: nil }
decrement_on_update_if ->(student) { student.has_changed? :confirmed, from: true, to: false }

or maybe

on :create do
  increment_if ->(student) { student.subscribed? && student.confirmed? }
end

on :delete do
  decrement_if ->(student) { student.subscribed? && student.confirmed? }
end

on :update do
  increment_if ->(student) { student.has_changed? :subscribed_at, from: nil, to: Counter::Any }
  increment_if ->(student) { student.has_changed? :confirmed, from: false, to: true }
  decrement_if ->(student) { student.has_changed? :subscribed_at, from: Counter::Any, to: nil }
  decrement_if ->(student) { student.has_changed? :confirmed, from: true, to: false }
end