Refactor to introduce an entropy model
Instead of keeping two tracks of similar logic (auto-reconsider / auto-close).
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
class Account < ApplicationRecord
|
||||
include Entropy, Joinable
|
||||
include Entropic, Joinable
|
||||
|
||||
has_many_attached :uploads
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module Account::Entropy
|
||||
module Account::Entropic
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
class Card < ApplicationRecord
|
||||
include Assignable, Colored, Engageable, Entropy, Eventable,
|
||||
include Assignable, Colored, Engageable, Entropic, Eventable,
|
||||
Golden, Mentions, Pinnable, Closeable, Readable, Searchable,
|
||||
Staged, Statuses, Taggable, Watchable
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
module Card::Entropic
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
scope :entropic_by, ->(period_name) do
|
||||
left_outer_joins(collection: :entropy_configuration)
|
||||
.where("last_active_at <= DATETIME('now', '-' || COALESCE(entropy_configurations.#{period_name}, ?) || ' seconds')",
|
||||
Entropy::Configuration.default.public_send(period_name))
|
||||
end
|
||||
|
||||
scope :stagnated, -> { doing.entropic_by(:auto_reconsider_period) }
|
||||
scope :due_to_be_closed, -> { considering.entropic_by(:auto_close_period) }
|
||||
delegate :auto_close_period, :auto_reconsider_period, to: :collection
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def auto_close_all_due
|
||||
due_to_be_closed.find_each do |card|
|
||||
card.close(user: User.system, reason: "Closed")
|
||||
end
|
||||
end
|
||||
|
||||
def auto_reconsider_all_stagnated
|
||||
stagnated.find_each(&:reconsider)
|
||||
end
|
||||
end
|
||||
|
||||
def entropy
|
||||
Card::Entropy.for(self)
|
||||
end
|
||||
|
||||
def has_entropy?
|
||||
entropy.present?
|
||||
end
|
||||
end
|
||||
+14
-52
@@ -1,62 +1,24 @@
|
||||
module Card::Entropy
|
||||
extend ActiveSupport::Concern
|
||||
class Card::Entropy
|
||||
attr_reader :card, :auto_clean_period
|
||||
|
||||
AUTO_RECONSIDER_PERIOD = 30.days
|
||||
ENTROPY_REMINDER_BEFORE = 7.days
|
||||
class << self
|
||||
def for(card)
|
||||
return unless card.last_active_at
|
||||
|
||||
included do
|
||||
scope :entropic_by, ->(period_name) do
|
||||
left_outer_joins(collection: :entropy_configuration)
|
||||
.where("last_active_at <= DATETIME('now', '-' || COALESCE(entropy_configurations.#{period_name}, ?) || ' seconds')",
|
||||
Entropy::Configuration.default.public_send(period_name))
|
||||
end
|
||||
|
||||
scope :stagnated, -> { doing.entropic_by(:auto_reconsider_period) }
|
||||
scope :due_to_be_closed, -> { considering.entropic_by(:auto_close_period) }
|
||||
delegate :auto_close_period, :auto_reconsider_period, to: :collection
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def auto_close_all_due
|
||||
due_to_be_closed.find_each do |card|
|
||||
card.close(user: User.system, reason: "Closed")
|
||||
if card.considering?
|
||||
new(card, card.auto_close_period)
|
||||
elsif card.doing?
|
||||
new(card, card.auto_reconsider_period)
|
||||
end
|
||||
end
|
||||
|
||||
def auto_reconsider_all_stagnated
|
||||
stagnated.find_each(&:reconsider)
|
||||
end
|
||||
end
|
||||
|
||||
def subject_to_entropy?
|
||||
auto_reconsidering? || auto_closing?
|
||||
def initialize(card, auto_clean_period)
|
||||
@card = card
|
||||
@auto_clean_period = auto_clean_period
|
||||
end
|
||||
|
||||
def auto_reconsidering?
|
||||
doing? && last_active_at
|
||||
end
|
||||
|
||||
def auto_closing?
|
||||
considering? && last_active_at
|
||||
end
|
||||
|
||||
def auto_close_at
|
||||
last_active_at + auto_close_period if auto_closing?
|
||||
end
|
||||
|
||||
def days_until_close
|
||||
(auto_close_at.to_date - Date.current).to_i if auto_close_at
|
||||
end
|
||||
|
||||
def auto_reconsider_at
|
||||
last_active_at + auto_reconsider_period if auto_reconsidering?
|
||||
end
|
||||
|
||||
def days_until_reconsider
|
||||
(auto_reconsider_at.to_date - Date.current).to_i if auto_reconsider_at
|
||||
end
|
||||
|
||||
def entropy_cleaned_at
|
||||
auto_close_at || auto_reconsider_at
|
||||
def auto_clean_at
|
||||
card.last_active_at + auto_clean_period
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Collection < ApplicationRecord
|
||||
include AutoClosing, Accessible, Broadcastable, Entropy, Filterable, Workflowing
|
||||
include AutoClosing, Accessible, Broadcastable, Entropic, Filterable, Workflowing
|
||||
|
||||
belongs_to :creator, class_name: "User", default: -> { Current.user }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module Collection::Entropy
|
||||
module Collection::Entropic
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
@@ -22,10 +22,12 @@
|
||||
</details>
|
||||
|
||||
<span class="card-perma__closure-message">
|
||||
<% if card.doing? %>
|
||||
Falls back to <em>Considering</em> if no activity <%= local_datetime_tag(card.auto_reconsider_at, style: :indays) -%>.
|
||||
<% elsif card.auto_closing? %>
|
||||
Auto-closes if no activity <%= local_datetime_tag(card.auto_close_at, style: :indays) -%>.
|
||||
<% if card.has_entropy? %>
|
||||
<% if card.doing? %>
|
||||
Falls back to <em>Considering</em> if no activity <%= local_datetime_tag(card.entropy.auto_clean_at, style: :indays) -%>.
|
||||
<% else %>
|
||||
Auto-closes if no activity <%= local_datetime_tag(card.entropy.auto_clean_at, style: :indays) -%>.
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<%= render "cards/display/common/background", card: card %>
|
||||
|
||||
<% if card.subject_to_entropy? %>
|
||||
<% if card.has_entropy? %>
|
||||
<%= render "cards/display/preview/bubble", card: card %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div hidden class="bubble bubble--<%= card.engagement_status %>"
|
||||
data-controller="bubble" data-action="turbo:morph-element->bubble#update"
|
||||
data-bubble-reminder-before-value="<%= Card::ENTROPY_REMINDER_BEFORE.in_days.to_i %>"
|
||||
data-bubble-closes-at-value="<%= card.entropy_cleaned_at.iso8601 %>"
|
||||
data-bubble-reminder-before-value="<%= card.entropy.auto_clean_period.seconds.in_days.to_i %>"
|
||||
data-bubble-closes-at-value="<%= card.entropy.auto_clean_at.iso8601 %>"
|
||||
data-bubble-entropy-action-value="<%= card_entropy_action(card) %>">
|
||||
<svg viewBox="0 0 200 100">
|
||||
<path id="top-half" fill="transparent" d="M 20,100 A 80,80 0 0,1 180,100" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require "test_helper"
|
||||
|
||||
class Card::EntropyTest < ActiveSupport::TestCase
|
||||
class Card::EntropicTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
Current.session = sessions(:david)
|
||||
end
|
||||
@@ -11,7 +11,7 @@ class Card::EntropyTest < ActiveSupport::TestCase
|
||||
entropy_configurations(:writebook_collection).destroy
|
||||
entropy_configurations("37s_account").reload.update! auto_close_period: 456.days
|
||||
cards(:layout).update! last_active_at: 2.day.ago
|
||||
assert_equal (456 - 2).days.from_now, cards(:layout).auto_close_at
|
||||
assert_equal (456 - 2).days.from_now, cards(:layout).entropy.auto_clean_at
|
||||
end
|
||||
|
||||
test "auto_close_at infers the period from the collection when present" do
|
||||
@@ -19,7 +19,7 @@ class Card::EntropyTest < ActiveSupport::TestCase
|
||||
|
||||
entropy_configurations(:writebook_collection).update! auto_close_period: 123.days
|
||||
cards(:layout).update! last_active_at: 2.day.ago
|
||||
assert_equal (123 - 2).days.from_now, cards(:layout).auto_close_at
|
||||
assert_equal (123 - 2).days.from_now, cards(:layout).entropy.auto_clean_at
|
||||
end
|
||||
|
||||
test "auto_reconsider_at uses the period defined in the account by default" do
|
||||
@@ -29,7 +29,7 @@ class Card::EntropyTest < ActiveSupport::TestCase
|
||||
entropy_configurations(:writebook_collection).destroy
|
||||
entropy_configurations("37s_account").reload.update! auto_reconsider_period: 456.days
|
||||
cards(:layout).update! last_active_at: 2.day.ago
|
||||
assert_equal (456 - 2).days.from_now, cards(:layout).auto_reconsider_at
|
||||
assert_equal (456 - 2).days.from_now, cards(:layout).entropy.auto_clean_at
|
||||
end
|
||||
|
||||
test "auto_reconsider_at infers the period from the collection when present" do
|
||||
@@ -38,7 +38,7 @@ class Card::EntropyTest < ActiveSupport::TestCase
|
||||
cards(:layout).engage
|
||||
entropy_configurations(:writebook_collection).update! auto_reconsider_period: 123.days
|
||||
cards(:layout).update! last_active_at: 2.day.ago
|
||||
assert_equal (123 - 2).days.from_now, cards(:layout).auto_reconsider_at
|
||||
assert_equal (123 - 2).days.from_now, cards(:layout).entropy.auto_clean_at
|
||||
end
|
||||
|
||||
test "auto close all due using the default account entropy configuration" do
|
||||
@@ -105,11 +105,11 @@ class Card::EntropyTest < ActiveSupport::TestCase
|
||||
assert_equal Time.current, cards(:logo).last_active_at
|
||||
end
|
||||
|
||||
test "entropy_cleaned_at returns when the entropy will be cleaned" do
|
||||
assert_equal cards(:layout).auto_close_at, cards(:layout).entropy_cleaned_at
|
||||
assert_not_nil cards(:layout).entropy_cleaned_at
|
||||
test ".entropy.auto_clean_at returns when the entropy will be cleaned" do
|
||||
assert_equal cards(:layout).entropy.auto_clean_at, cards(:layout).entropy.auto_clean_at
|
||||
assert_not_nil cards(:layout).entropy.auto_clean_at
|
||||
|
||||
assert_equal cards(:logo).auto_reconsider_at, cards(:logo).entropy_cleaned_at
|
||||
assert_not_nil cards(:logo).entropy_cleaned_at
|
||||
assert_equal cards(:logo).entropy.auto_clean_at, cards(:logo).entropy.auto_clean_at
|
||||
assert_not_nil cards(:logo).entropy.auto_clean_at
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user